RHO_GLOBAL void JNICALL Java_com_rhomobile_rhodes_file_RhoFileApi_updateStatTable (JNIEnv *env, jclass, jstring pathObj, jstring type, jlong size, jlong mtime) { std::string path = rho_cast<std::string>(env, pathObj); rho_stat_t st; std::string t = rho_cast<std::string>(env, type); if (t == "dir") st.type = rho_type_dir; else if (t == "file") st.type = rho_type_file; else { jclass clsRE = getJNIClass(RHODES_JAVA_CLASS_RUNTIME_EXCEPTION); if (!clsRE) return; env->ThrowNew(clsRE, "Unknown type of file"); return; } st.size = (size_t)size; st.mtime = (unsigned long)mtime; rho_stat_map.insert(std::make_pair(path, st)); if (st.type == rho_type_dir) { std::string fpath = rho_root_path() + "/" + path; RHO_LOG("updateStatTable: create dir: %s", fpath.c_str()); mkdir(fpath.c_str(), S_IRWXU); } }
RHO_GLOBAL int open(const char *path, int oflag, ...) { std::string fpath; if (path) fpath = path; if (fpath.empty()) { RHO_LOG("open: path is empty"); errno = EFAULT; return -1; } RHO_LOG("open: %s...", path); fpath = make_full_path(fpath); //RHO_LOG("open: %s: fpath: %s", path, fpath.c_str()); bool java_way = need_java_way(fpath); if (java_way && has_pending_exception()) { errno = EFAULT; return -1; } if (java_way && (oflag & (O_WRONLY | O_RDWR))) { //RHO_LOG("open: %s: copy from Android package", path); JNIEnv *env = jnienv(); jstring relPathObj = rho_cast<jstring>(env, make_rel_path(fpath).c_str()); env->CallStaticBooleanMethod(clsFileApi, midCopy, relPathObj); env->DeleteLocalRef(relPathObj); if (has_pending_exception()) { errno = EFAULT; return -1; } java_way = false; } int fd; if (java_way) { JNIEnv *env = jnienv(); jstring relPathObj = rho_cast<jstring>(env, make_rel_path(fpath).c_str()); jobject is = env->CallStaticObjectMethod(clsFileApi, midOpen, relPathObj); env->DeleteLocalRef(relPathObj); if (is != NULL) { scoped_lock_t guard(rho_fd_mtx); if (!rho_fd_free.empty()) { fd = rho_fd_free[0]; rho_fd_free.erase(rho_fd_free.begin()); } else fd = rho_fd_counter++; rho_fd_data_t d; d.is = env->NewGlobalRef(is); d.fpath = fpath; d.pos = 0; rho_fd_map[fd] = d; } else { errno = EFAULT; fd = -1; } env->DeleteLocalRef(is); } else { mode_t mode = 0; if (oflag & O_CREAT) { va_list vl; va_start(vl, oflag); mode = va_arg(vl, int); va_end(vl); } fd = real_open(path, oflag, mode); }
static void dump_stat(struct stat const &st) { RHO_LOG("st.st_dev: %llx", (long long)st.st_dev); RHO_LOG("st.st_ino: %lx", (long)st.st_ino); RHO_LOG("st.st_mode: %x", (int)st.st_mode); RHO_LOG("st.st_nlink: %x", (int)st.st_nlink); RHO_LOG("st.st_uid: %lx", (unsigned long)st.st_uid); RHO_LOG("st.st_gid: %lx", (unsigned long)st.st_gid); RHO_LOG("st.st_rdev: %llx", (long long)st.st_rdev); RHO_LOG("st.st_size: %lld", (long long)st.st_size); RHO_LOG("st.st_blksize: %lu", (unsigned long)st.st_blksize); RHO_LOG("st.st_blocks: %llu", (unsigned long long)st.st_blocks); RHO_LOG("st.st_atime: %lu", (unsigned long)st.st_atime); RHO_LOG("st.st_atime_nsec: %lu", (unsigned long)st.st_atime_nsec); RHO_LOG("st.st_mtime: %lu", (unsigned long)st.st_mtime); RHO_LOG("st.st_mtime_nsec: %lu", (unsigned long)st.st_mtime_nsec); RHO_LOG("st.st_ctime: %lu", (unsigned long)st.st_ctime); RHO_LOG("st.st_ctime_nsec: %lu", (unsigned long)st.st_ctime_nsec); RHO_LOG("st.st_ino: %llx", (unsigned long long)st.st_ino); }
RHO_GLOBAL int open(const char *path, int oflag, ...) { std::string fpath; if (path) fpath = path; if (fpath.empty()) { RHO_LOG("open: path is empty"); errno = EFAULT; return -1; } RHO_LOG("open: %s...", path); fpath = make_full_path(fpath); RHO_LOG("open: %s: fpath: %s", path, fpath.c_str()); bool emulate = need_emulate(fpath); RHO_LOG("open: %s: emulate: %d", path, (int)emulate); if (emulate && has_pending_exception()) { RHO_LOG("open: %s: has_pending_exception, return -1", path); errno = EFAULT; return -1; } if (emulate && (oflag & (O_WRONLY | O_RDWR))) { RHO_LOG("open: %s: copy from Android package", path); JNIEnv *env = jnienv(); jhstring relPathObj = rho_cast<jhstring>(env, make_rel_path(fpath).c_str()); env->CallStaticBooleanMethod(clsFileApi, midCopy, relPathObj.get()); if (has_pending_exception()) { RHO_LOG("open: %s: has_pending_exception, return -1", path); errno = EFAULT; return -1; } emulate = false; } RHO_LOG("open: %s: emulate: %d", path, (int)emulate); int fd; if (emulate) { RHO_LOG("open: %s: emulate", path); JNIEnv *env = jnienv(); jhstring relPathObj = rho_cast<jhstring>(env, make_rel_path(fpath).c_str()); jhobject is = jhobject(env->CallStaticObjectMethod(clsFileApi, midOpen, relPathObj.get())); if (!is) { errno = EFAULT; fd = -1; } else { scoped_lock_t guard(rho_file_mtx); if (!rho_fd_free.empty()) { fd = rho_fd_free[0]; rho_fd_free.erase(rho_fd_free.begin()); } else fd = rho_fd_counter++; rho_fd_data_t d; d.type = rho_type_file; d.is = env->NewGlobalRef(is.get()); d.dirp = NULL; d.fpath = fpath; d.pos = 0; rho_fd_map[fd] = d; } } else { RHO_LOG("open: %s: native", path); mode_t mode = 0; if (oflag & O_CREAT) { va_list vl; va_start(vl, oflag); mode = va_arg(vl, int); va_end(vl); } fd = real_open(path, oflag, mode); }
RHO_GLOBAL void JNICALL Java_com_rhomobile_rhodes_file_RhoFileApi_nativeInit (JNIEnv *env, jclass) { clsFileApi = getJNIClass(RHODES_JAVA_CLASS_RHOFILEAPI); if (!clsFileApi) return; midCopy = getJNIClassStaticMethod(env, clsFileApi, "copy", "(Ljava/lang/String;)Z"); if (!midCopy) return; midOpen = getJNIClassStaticMethod(env, clsFileApi, "openInPackage", "(Ljava/lang/String;)Ljava/io/InputStream;"); if (!midOpen) return; midClose = getJNIClassStaticMethod(env, clsFileApi, "close", "(Ljava/io/InputStream;)V"); if (!midClose) return; midRead = getJNIClassStaticMethod(env, clsFileApi, "read", "(Ljava/io/InputStream;[B)I"); if (!midRead) return; midSeek = getJNIClassStaticMethod(env, clsFileApi, "seek", "(Ljava/io/InputStream;I)V"); if (!midSeek) return; midGetChildren = getJNIClassStaticMethod(env, clsFileApi, "getChildren", "(Ljava/lang/String;)[Ljava/lang/String;"); if (!midGetChildren) return; const char *libc = "/system/lib/libc.so"; void *pc = dlopen(libc, RTLD_LAZY); __sflags = (func_sflags_t)dlsym(pc, "__sflags"); __sfp = (func_sfp_t)dlsym(pc, "__sfp"); real_access = (func_access_t)dlsym(pc, "access"); real_close = (func_close_t)dlsym(pc, "close"); real_dup = (func_dup_t)dlsym(pc, "dup"); real_dup2 = (func_dup2_t)dlsym(pc, "dup2"); real_chown = (func_chown_t)dlsym(pc, "chown"); real_fchown = (func_fchown_t)dlsym(pc, "fchown"); real_lchown = (func_lchown_t)dlsym(pc, "lchown"); real_link = (func_link_t)dlsym(pc, "link"); real_symlink = (func_symlink_t)dlsym(pc, "symlink"); real_readlink = (func_readlink_t)dlsym(pc, "readlink"); real_mkdir = (func_mkdir_t)dlsym(pc, "mkdir"); real_fchdir = (func_fchdir_t)dlsym(pc, "fchdir"); real_fcntl = (func_fcntl_t)dlsym(pc, "fcntl"); real_fsync = (func_fsync_t)dlsym(pc, "fsync"); real_fdatasync = (func_fdatasync_t)dlsym(pc, "fdatasync"); if (real_fdatasync == NULL) { //Android 2.1 have no fdatasync call. Use fsync instead RHO_LOG("No fdatasync implementation, using fsync instead"); real_fdatasync = real_fsync; } real_flock = (func_flock_t)dlsym(pc, "flock"); real_fstat = (func_fstat_t)dlsym(pc, "fstat"); real_ftruncate = (func_ftruncate_t)dlsym(pc, "ftruncate"); real_lseek = (func_lseek_t)dlsym(pc, "lseek"); real_lseek64 = (func_lseek64_t)dlsym(pc, "lseek64"); real_lstat = (func_lstat_t)dlsym(pc, "lstat"); real_open = (func_open_t)dlsym(pc, "open"); real_read = (func_read_t)dlsym(pc, "read"); real_select = (func_select_t)dlsym(pc, "select"); real_stat = (func_stat_t)dlsym(pc, "stat"); real_unlink = (func_unlink_t)dlsym(pc, "unlink"); real_write = (func_write_t)dlsym(pc, "write"); real_getdents = (func_getdents_t)dlsym(pc, "getdents"); real_rmdir = (func_rmdir_t)dlsym(pc, "rmdir"); real_opendir = (func_opendir_t)dlsym(pc, "opendir"); real_fdopendir = (func_fdopendir_t)dlsym(pc, "fdopendir"); real_readdir = (func_readdir_t)dlsym(pc, "readdir"); real_readdir_r = (func_readdir_r_t)dlsym(pc, "readdir_r"); real_closedir = (func_closedir_t)dlsym(pc, "closedir"); real_rewinddir = (func_rewinddir_t)dlsym(pc, "rewinddir"); real_dirfd = (func_dirfd_t)dlsym(pc, "dirfd"); real_scandir = (func_scandir_t)dlsym(pc, "scandir"); dlclose(pc); // This is just to get typical stat of file std::string librhodes = rho_root_path() + "../lib/librhodes.so"; RHO_LOG("Native library: %s", librhodes.c_str()); real_stat(librhodes.c_str(), &librhodes_st); librhodes_st.st_mode = S_IFREG|S_IRWXU; librhodes_st.st_nlink = 1; librhodes_st.st_uid = getuid(); librhodes_st.st_gid = getgid(); RHO_LOG("Library stat (mode: %d, uid: %d, gid: %d)", librhodes_st.st_mode, librhodes_st.st_uid, librhodes_st.st_gid); }