struct MountsPublicInterface* mm_mount_byhandle( struct MountsManager *mounts_manager, int handle ){ const struct HandleItem* entry = get_handle_allocator()->entry(handle); /*if handle exist and related to opened file*/ if ( entry && NULL != get_open_files_pool()->entry(entry->open_file_description_id) ) return entry->mount_fs; else return NULL; }
int mm_fusemount_add( struct MountsManager *mounts_manager, const char* path, struct fuse_operations* fuse_mount, char expect_absolute_path, char proxy_mode){ struct MountsPublicInterface* fs = CONSTRUCT_L(FUSE_OPERATIONS_MOUNT)( get_handle_allocator(), get_open_files_pool(), fuse_mount, proxy_mode); return mm_mount_add( mounts_manager, path, fs, expect_absolute_path ); }
struct MountsManager* get_mounts_manager(){ s_mounts_manager.handle_allocator = get_handle_allocator(); s_mounts_manager.open_files_pool = get_open_files_pool(); return &s_mounts_manager; }
static int fuse_operations_mount_open(struct MountsPublicInterface* this_, const char* path, int oflag, uint32_t mode) { int ret=-1; int fd=-1; struct FuseOperationsMount* fs = (struct FuseOperationsMount*)this_; struct stat st; struct stat st_parent; int file_exist; CHECK_FUNC_ENSURE_EXIST(fs, open); file_exist=fs->fuse_operations->getattr(path, &st); /*file exist, do checks of O_CREAT, O_EXCL flags*/ if ( !file_exist && CHECK_FLAG(oflag, O_CREAT) && CHECK_FLAG(oflag, O_EXCL) ) { SET_ERRNO(EEXIST); return -1; } /*truncate existing writable file*/ if ( !file_exist && CHECK_FLAG(oflag, O_TRUNC) && (CHECK_FLAG(oflag, O_WRONLY) || CHECK_FLAG(oflag, O_RDWR)) ) { CHECK_FUNC_ENSURE_EXIST(fs, truncate); if ( (ret=fs->fuse_operations->truncate(path, 0)) <0 ) { /*truncate error*/ SET_ERRNO(-ret); return -1; } } /*create fuse object, it must be attached into ofd entry or be destroyed if zrt would not be able to return file handle*/ struct fuse_file_info *finfo = calloc(1, sizeof(struct fuse_file_info)); /*reset flags that should not be passed to fuse's open*/ finfo->flags = oflag & ~(O_CREAT|O_TRUNC|O_EXCL); /*is file exist?*/ if (!file_exist) { if ( (ret=fs->fuse_operations->open(path, finfo)) <0 ) { SET_ERRNO(-ret); } } else { /*file does not exist, create & open it*/ if ( CHECK_FLAG(oflag, O_CREAT) ) { CHECK_FUNC_ENSURE_EXIST(fs, create); if ( (ret=fs->fuse_operations->create(path, mode, finfo)) <0 ) { SET_ERRNO(-ret); } } } /*if path open/create success*/ if ( ! ret ) { int open_file_description_id; if ( fs->proxy_mode == EFuseProxyModeDisabled ) { /*in case if fs works in generic mode it use own handles stored in finfo->fh, so we need to issue a global fd visible across system*/ open_file_description_id = get_open_files_pool()->getnew_ofd(oflag); fd = fs->handle_allocator->allocate_handle(this_, st.st_ino, st_parent.st_ino, open_file_description_id); if ( fd < 0 ) { /*it's hipotetical but possible case if amount of open files are exceeded an maximum value.*/ fs->open_files_pool->release_ofd(open_file_description_id); SET_ERRNO(ENFILE); } } else if ( fs->proxy_mode == EFuseProxyModeEnabled) { /*proxy mode is enabled, so open already returned actual fd, therefore do not issue a new one and use returned*/ fd = finfo->fh; const struct HandleItem *hentry = fs->handle_allocator->entry(finfo->fh); if (hentry!=NULL) open_file_description_id = hentry->open_file_description_id; else { ZRT_LOG(L_ERROR, "can't open '%s' due to handle=%lld returned from fuse fs has no HandleEntry", path, finfo->fh ); SET_ERRNO(EINVAL); } } else { assert(0); } /*successfully opened, save fuse data*/ struct FuseFileOptionalData *fdata = malloc( sizeof(struct FuseFileOptionalData) ); fs->open_files_pool->set_optional_data( open_file_description_id, (intptr_t)fdata ); fdata->path = strdup(path); fdata->finfo = finfo; return fd; } else { free(finfo); return -1; } }