#include #include #include using boost::none; using cpputils::Random; using cpputils::SCrypt; using cryfs_cli::Cli; using cryfs_cli::program_options::ProgramOptions; using fspp::fuse::Fuse; std::set validFusePtrs; extern "C" jlong cryfs_init(JNIEnv *env, jstring jbaseDir, jstring jlocalStateDir, jbyteArray jpassword, jbyteArray jgivenHash, jobject jreturnedHash, jboolean createBaseDir, jstring jcipher) { const char* baseDir = env->GetStringUTFChars(jbaseDir, NULL); const char* localStateDir = env->GetStringUTFChars(jlocalStateDir, NULL); boost::optional cipher = none; if (jcipher != NULL) { const char* cipherName = env->GetStringUTFChars(jcipher, NULL); cipher = boost::optional(cipherName); env->ReleaseStringUTFChars(jcipher, cipherName); } auto &keyGenerator = Random::OSRandom(); ProgramOptions options = ProgramOptions(baseDir, none, localStateDir, false, false, createBaseDir, cipher, none, false, none); env->ReleaseStringUTFChars(jbaseDir, baseDir); env->ReleaseStringUTFChars(jlocalStateDir, localStateDir); struct SizedData returnedHash; struct Cli::Credentials credentials; credentials.returnedHash = nullptr; if (jpassword == NULL) { credentials.password = none; credentials.givenHash.data = reinterpret_cast(env->GetByteArrayElements(jgivenHash, NULL)); credentials.givenHash.size = env->GetArrayLength(jgivenHash); } else { jbyte* password = env->GetByteArrayElements(jpassword, NULL); credentials.password = string(reinterpret_cast(password)); env->ReleaseByteArrayElements(jpassword, password, 0); if (jreturnedHash != NULL) { credentials.returnedHash = &returnedHash; } } Fuse* fuse = Cli(keyGenerator, SCrypt::DefaultSettings).initFilesystem(options, credentials); if (jpassword == NULL) { env->ReleaseByteArrayElements(jgivenHash, reinterpret_cast(credentials.givenHash.data), 0); } jlong fusePtr = reinterpret_cast(fuse); if (fusePtr != 0) { validFusePtrs.insert(fusePtr); if (credentials.returnedHash != nullptr) { jfieldID value = env->GetFieldID(env->GetObjectClass(jreturnedHash), "value", "Ljava/lang/Object;"); jbyteArray jpasswordHash = env->NewByteArray(returnedHash.size); env->SetByteArrayRegion(jpasswordHash, 0, returnedHash.size, reinterpret_cast(returnedHash.data)); env->SetObjectField(jreturnedHash, value, jpasswordHash); } } return fusePtr; } extern "C" jlong cryfs_create(JNIEnv* env, jlong fusePtr, jstring jpath, mode_t mode) { Fuse* fuse = reinterpret_cast(fusePtr); const char* path = env->GetStringUTFChars(jpath, NULL); uint64_t fh; int result = fuse->create(path, mode, &fh); env->ReleaseStringUTFChars(jpath, path); if (result == 0) { return fh; } else { return -1; } } extern "C" jlong cryfs_open(JNIEnv* env, jlong fusePtr, jstring jpath, jint flags) { Fuse* fuse = reinterpret_cast(fusePtr); const char* path = env->GetStringUTFChars(jpath, NULL); uint64_t fh; int result = fuse->open(path, &fh, flags); env->ReleaseStringUTFChars(jpath, path); if (result == 0) { return fh; } else { return -1; } } extern "C" jint cryfs_read(JNIEnv* env, jlong fusePtr, jlong fileHandle, jbyteArray jbuffer, jlong offset) { Fuse* fuse = reinterpret_cast(fusePtr); const jsize size = env->GetArrayLength(jbuffer); char* buff = reinterpret_cast(env->GetByteArrayElements(jbuffer, NULL)); int result = fuse->read(buff, size, offset, fileHandle); env->ReleaseByteArrayElements(jbuffer, reinterpret_cast(buff), 0); return result; } extern "C" jint cryfs_write(JNIEnv* env, jlong fusePtr, jlong fileHandle, jlong offset, jbyteArray jbuffer, jint size) { Fuse* fuse = reinterpret_cast(fusePtr); char* buff = reinterpret_cast(env->GetByteArrayElements(jbuffer, NULL)); int result = fuse->write(buff, size, offset, fileHandle); env->ReleaseByteArrayElements(jbuffer, reinterpret_cast(buff), 0); return result; } extern "C" jint cryfs_truncate(JNIEnv* env, jlong fusePtr, jstring jpath, jlong size) { Fuse* fuse = reinterpret_cast(fusePtr); const char* path = env->GetStringUTFChars(jpath, NULL); int result = fuse->truncate(path, size); env->ReleaseStringUTFChars(jpath, path); return result; } extern "C" jint cryfs_unlink(JNIEnv* env, jlong fusePtr, jstring jpath) { Fuse* fuse = reinterpret_cast(fusePtr); const char* path = env->GetStringUTFChars(jpath, NULL); int result = fuse->unlink(path); env->ReleaseStringUTFChars(jpath, path); return result; } extern "C" jint cryfs_release(jlong fusePtr, jlong fileHandle) { Fuse* fuse = reinterpret_cast(fusePtr); return fuse->release(fileHandle); } struct readDirHelper { Fuse* fuse; boost::filesystem::path path; void* data; fuse_fill_dir_t filler; }; int readDir(void* data, const char* name, fspp::fuse::STAT* stat) { if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { return 0; } struct readDirHelper* helper = reinterpret_cast(data); mode_t mode = stat->st_mode; // saving mode because getattr sometimes modifies it badly helper->fuse->getattr(helper->path / name, stat); stat->st_mode = mode; return helper->filler(helper->data, name, stat); } extern "C" jint cryfs_readdir(JNIEnv* env, jlong fusePtr, jstring jpath, void* data, fuse_fill_dir_t filler) { Fuse* fuse = reinterpret_cast(fusePtr); const char* path = env->GetStringUTFChars(jpath, NULL); struct readDirHelper helper; helper.fuse = fuse; helper.path = boost::filesystem::path(path); helper.data = data; helper.filler = filler; int result = fuse->readdir(path, &helper, readDir); env->ReleaseStringUTFChars(jpath, path); return result; } extern "C" jint cryfs_mkdir(JNIEnv* env, jlong fusePtr, jstring jpath, mode_t mode) { Fuse* fuse = reinterpret_cast(fusePtr); const char* path = env->GetStringUTFChars(jpath, NULL); int result = fuse->mkdir(path, mode); env->ReleaseStringUTFChars(jpath, path); return result; } extern "C" jint cryfs_rmdir(JNIEnv* env, jlong fusePtr, jstring jpath) { Fuse* fuse = reinterpret_cast(fusePtr); const char* path = env->GetStringUTFChars(jpath, NULL); int result = fuse->rmdir(path); env->ReleaseStringUTFChars(jpath, path); return result; } extern "C" jint cryfs_getattr(JNIEnv* env, jlong fusePtr, jstring jpath, fspp::fuse::STAT* stat) { Fuse* fuse = reinterpret_cast(fusePtr); const char* path = env->GetStringUTFChars(jpath, NULL); int result = fuse->getattr(path, stat); env->ReleaseStringUTFChars(jpath, path); return result; } extern "C" jint cryfs_rename(JNIEnv* env, jlong fusePtr, jstring jsrcPath, jstring jdstPath) { Fuse* fuse = reinterpret_cast(fusePtr); const char* srcPath = env->GetStringUTFChars(jsrcPath, NULL); const char* dstPath = env->GetStringUTFChars(jdstPath, NULL); int result = fuse->rename(srcPath, dstPath); env->ReleaseStringUTFChars(jsrcPath, srcPath); env->ReleaseStringUTFChars(jdstPath, dstPath); return result; } extern "C" void cryfs_destroy(jlong fusePtr) { Fuse* fuse = reinterpret_cast(fusePtr); fuse->destroy(); delete fuse; validFusePtrs.erase(fusePtr); } extern "C" jboolean cryfs_is_closed(jlong fusePtr) { return validFusePtrs.find(fusePtr) == validFusePtrs.end(); }