我已經創建了一個JNI封裝現在訪問直接在C-API的擴展屬性。它是一個開源的Java Maven項目和繳費上GitHub/xattrj
僅供參考,我在這裏發表了有趣的來源作品。有關最新消息,請參閱上述項目頁面。
Xattrj.java
public class Xattrj {
/**
* Write the extended attribute to the given file
* @param file
* @param attrKey
* @param attrValue
*/
public void writeAttribute(File file, String attrKey, String attrValue){
writeAttribute(file.getAbsolutePath(), attrKey, attrValue);
}
/**
* Read the extended attribute from the given file
* @param file
* @param attrKey
* @return
*/
public String readAttribute(File file, String attrKey){
return readAttribute(file.getAbsolutePath(), attrKey);
}
/**
* Write the extended attribute to the given file
* @param file
* @param attrKey
* @param attrValue
*/
private native void writeAttribute(String file, String attrKey, String attrValue);
/**
* Read the extended attribute from the given file
* @param file
* @param attrKey
* @return
*/
private native String readAttribute(String file, String attrKey);
static {
try {
System.out.println("loading xattrj...");
LibraryLoader.loadLibrary("xattrj");
System.out.println("loaded!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
org_securityvision_xattrj_Xattrj.cpp
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "org_securityvision_xattrj_Xattrj.h"
#include <sys/xattr.h>
/**
* writeAttribute
* writes the extended attribute
*
*/
JNIEXPORT void JNICALL Java_org_securityvision_xattrj_Xattrj_writeAttribute
(JNIEnv *env, jobject jobj, jstring jfilePath, jstring jattrName, jstring jattrValue){
const char *filePath= env->GetStringUTFChars(jfilePath, 0);
const char *attrName= env->GetStringUTFChars(jattrName, 0);
const char *attrValue=env->GetStringUTFChars(jattrValue,0);
int res = setxattr(filePath,
attrName,
(void *)attrValue,
strlen(attrValue), 0, 0); //XATTR_NOFOLLOW != 0
if(res){
// an error occurred, see errno
printf("native:writeAttribute: error on write...");
perror("");
}
}
/**
* readAttribute
* Reads the extended attribute as string
*
* If the attribute does not exist (or any other error occurs)
* a null string is returned.
*
*
*/
JNIEXPORT jstring JNICALL Java_org_securityvision_xattrj_Xattrj_readAttribute
(JNIEnv *env, jobject jobj, jstring jfilePath, jstring jattrName){
jstring jvalue = NULL;
const char *filePath= env->GetStringUTFChars(jfilePath, 0);
const char *attrName= env->GetStringUTFChars(jattrName, 0);
// get size of needed buffer
int bufferLength = getxattr(filePath, attrName, NULL, 0, 0, 0);
if(bufferLength > 0){
// make a buffer of sufficient length
char *buffer = (char*)malloc(bufferLength);
// now actually get the attribute string
int s = getxattr(filePath, attrName, buffer, bufferLength, 0, 0);
if(s > 0){
// convert the buffer to a null terminated string
char *value = (char*)malloc(s+1);
*(char*)value = 0;
strncat(value, buffer, s);
free(buffer);
// convert the c-String to a java string
jvalue = env->NewStringUTF(value);
}
}
return jvalue;
}
現在這困擾了我相當多的把事情的工作makefile文件:
CC=gcc
LDFLAGS= -fPIC -bundle
CFLAGS= -c -shared -I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers -m64
SOURCES_DIR=src/main/c++
OBJECTS_DIR=target/c++
EXECUTABLE=target/classes/libxattrj.dylib
SOURCES=$(shell find '$(SOURCES_DIR)' -type f -name '*.cpp')
OBJECTS=$(SOURCES:$(SOURCES_DIR)/%.cpp=$(OBJECTS_DIR)/%.o)
all: $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o [email protected]
$(OBJECTS): $(SOURCES)
mkdir -p $(OBJECTS_DIR)
$(CC) $(CFLAGS) $< -o [email protected]
clean:
rm -rf $(OBJECTS_DIR) $(EXECUTABLE)
不錯,很高興看到你工作。只是對你的代碼的一些評論......你爲什麼在第二次調用getxattr()時硬編碼255作爲緩衝區大小?您已經動態確定了屬性值的大小。其次,如果這是爲了設置和檢索任意屬性(而不是特定於應用程序),你不能把所有XATTR值作爲字符串。他們可以並經常包含任意的二進制數據;例如,使用Safari下載文件並檢查其xattrs。 – jatoben 2013-05-03 17:26:57
我打算創建seaprate方法來支持二進制數據。緩衝區大小來自官方的OS X例子,我只是用同樣的方法。我會修改你的建議。 BTW:我在C/C++的經驗是相當有限的,因此任何其他的建議高度讚賞:)比如,我想因爲我使用C++ string.h中我的C-字符串的處理可以簡化... – IsNull 2013-05-03 17:43:59