int fskit_fuse_fgetattr(const char *path, struct stat *statbuf, struct fuse_file_info *fi) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_FGETATTR) == 0 ) { return -ENOSYS; } fskit_debug("fgetattr(%s, %p, %p)\n", path, statbuf, fi ); struct fskit_fuse_file_info* ffi = NULL; ffi = (struct fskit_fuse_file_info*)((uintptr_t)fi->fh); int rc = 0; if( ffi->type == FSKIT_ENTRY_TYPE_FILE ) { rc = fskit_fstat( state->core, fskit_file_handle_get_path( ffi->handle.fh ), fskit_file_handle_get_entry( ffi->handle.fh ), statbuf ); } else { rc = fskit_fstat( state->core, fskit_dir_handle_get_path( ffi->handle.dh ), fskit_dir_handle_get_entry( ffi->handle.dh ), statbuf ); } fskit_debug("fgetattr(%s, %p, %p) rc = %d\n", path, statbuf, fi, rc ); return rc; }
// unlink/rmdir: remove the file or device node from the underlying filesystem int vdevfs_detach( struct fskit_core* core, struct fskit_match_group* grp, struct fskit_entry* fent, void* inode_cls ) { int rc = 0; struct vdevfs* vdev = (struct vdevfs*)fskit_core_get_user_data( core ); struct fskit_fuse_state* fs_state = fskit_fuse_get_state(); char const* method = NULL; if( fskit_entry_get_type( fent ) == FSKIT_ENTRY_TYPE_DIR ) { method = "rmdir"; } else { method = "unlink"; } rc = vdevfs_access_check( vdev, fs_state, method, grp->path ); if( rc < 0 ) { // denied! return -ENOENT; } if( rc != 0 ) { rc = -errno; vdev_error("%s('%s', '%s') rc = %d\n", method, vdev->mountpoint, grp->path, rc ); return rc; } return 0; }
int fskit_fuse_fsyncdir(const char *path, int datasync, struct fuse_file_info *fi) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_FSYNCDIR) == 0 ) { return -ENOSYS; } fskit_debug("fsyncdir(%s, %d, %p)\n", path, datasync, fi); // not addressed by fskit fskit_debug("fsyncdir(%s, %d, %p) rc = %d\n", path, datasync, fi, 0); return 0; }
int fskit_fuse_fsync(const char *path, int datasync, struct fuse_file_info *fi) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_FSYNC) == 0 ) { return -ENOSYS; } fskit_debug("fsync(%s, %d, %p)\n", path, datasync, fi ); struct fskit_fuse_file_info* ffi = (struct fskit_fuse_file_info*)((uintptr_t)fi->fh); int rc = fskit_fsync( state->core, ffi->handle.fh ); fskit_debug("fsync(%s, %d, %p) rc = %d\n", path, datasync, fi, rc ); return rc; }
int fskit_fuse_removexattr(const char *path, const char *name) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_REMOVEXATTR) == 0 ) { return -ENOSYS; } fskit_debug("removexattr(%s, %s)\n", path, name ); uid_t uid = fskit_fuse_get_uid( state ); gid_t gid = fskit_fuse_get_gid( state ); int rc = fskit_removexattr( state->core, path, uid, gid, name ); fskit_debug("removexattr(%s, %s) rc = %d\n", path, name, rc ); return rc; }
int fskit_fuse_setxattr(const char *path, const char *name, const char *value, size_t size, int flags) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_SETXATTR) == 0 ) { return -ENOSYS; } fskit_debug("setxattr(%s, %s, %p, %zu, %X)\n", path, name, value, size, flags ); uid_t uid = fskit_fuse_get_uid( state ); gid_t gid = fskit_fuse_get_gid( state ); int rc = fskit_setxattr( state->core, path, uid, gid, name, value, size, flags ); fskit_debug("setxattr(%s, %s, %p, %zu, %X) rc = %d\n", path, name, value, size, flags, rc ); return rc; }
// stat: equvocate about which devices exist, depending on who's asking // return -ENOENT not only if the file doesn't exist, but also if the file is blocked by the ACL int vdevfs_stat( struct fskit_core* core, struct fskit_match_group* grp, struct fskit_entry* fent, struct stat* sb ) { int rc = 0; struct vdevfs* vdev = (struct vdevfs*)fskit_core_get_user_data( core ); struct fskit_fuse_state* fs_state = fskit_fuse_get_state(); rc = vdevfs_access_check( vdev, fs_state, "stat", grp->path ); if( rc < 0 ) { // denied! return -ENOENT; } else { return 0; } }
int fskit_fuse_listxattr(const char *path, char *list, size_t size) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_LISTXATTR) == 0 ) { return -ENOSYS; } fskit_debug("listxattr(%s, %p, %zu)\n", path, list, size ); uid_t uid = fskit_fuse_get_uid( state ); gid_t gid = fskit_fuse_get_gid( state ); int rc = fskit_listxattr( state->core, path, uid, gid, list, size ); fskit_debug("listxattr(%s, %p, %zu) rc = %d\n", path, list, size, rc ); return rc; }
int fskit_fuse_link(const char *path, const char *newpath) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_LINK) == 0 ) { return -ENOSYS; } fskit_debug("link(%s, %s)\n", path, newpath ); uid_t uid = fskit_fuse_get_uid( state ); gid_t gid = fskit_fuse_get_gid( state ); int rc = fskit_link( state->core, path, newpath, uid, gid ); fskit_debug("link(%s, %s) rc = %d\n", path, newpath, rc ); return 0; }
int fskit_fuse_utime(const char *path, struct utimbuf *ubuf) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_UTIME) == 0 ) { return -ENOSYS; } fskit_debug("utime(%s, %ld.%ld)\n", path, ubuf->actime, ubuf->modtime ); uid_t uid = fskit_fuse_get_uid( state ); gid_t gid = fskit_fuse_get_gid( state ); int rc = fskit_utime( state->core, path, uid, gid, ubuf ); fskit_debug("utime(%s, %ld.%ld) rc = %d\n", path, ubuf->actime, ubuf->modtime, rc ); return rc; }
int fskit_fuse_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_WRITE) == 0 ) { return -ENOSYS; } fskit_debug("write(%s, %p, %zu, %jd, %p)\n", path, buf, size, offset, fi); struct fskit_fuse_file_info* ffi = (struct fskit_fuse_file_info*)((uintptr_t)fi->fh); ssize_t num_written = 0; num_written = fskit_write( state->core, ffi->handle.fh, buf, size, offset ); fskit_debug("write(%s, %p, %zu, %jd, %p) rc = %zd\n", path, buf, size, offset, fi, num_written); return (int)num_written; }
int fskit_fuse_chown(const char *path, uid_t new_uid, gid_t new_gid) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_CHOWN) == 0 ) { return -ENOSYS; } fskit_debug("chown(%s, %d, %d)\n", path, new_uid, new_gid ); uid_t uid = fskit_fuse_get_uid( state ); gid_t gid = fskit_fuse_get_gid( state ); int rc = fskit_chown( state->core, path, uid, gid, new_uid, new_gid ); fskit_debug("chown(%s, %d, %d) rc = %d\n", path, new_uid, new_gid, rc ); return rc; }
int fskit_fuse_truncate(const char *path, off_t newsize) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_TRUNCATE) == 0 ) { return -ENOSYS; } fskit_debug("truncate(%s, %jd)\n", path, newsize ); uid_t uid = fskit_fuse_get_uid( state ); gid_t gid = fskit_fuse_get_gid( state ); int rc = fskit_trunc( state->core, path, uid, gid, newsize ); fskit_debug("truncate(%s, %jd) rc = %d\n", path, newsize, rc ); return rc; }
int fskit_fuse_chmod(const char *path, mode_t mode) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_CHMOD) == 0 ) { return -ENOSYS; } fskit_debug("chmod(%s, %o)\n", path, mode ); uid_t uid = fskit_fuse_get_uid( state ); gid_t gid = fskit_fuse_get_gid( state ); int rc = fskit_chmod( state->core, path, uid, gid, mode ); fskit_debug("chmod(%s, %o) rc = %d\n", path, mode, rc ); return rc; }
int fskit_fuse_getattr(const char *path, struct stat *statbuf) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_GETATTR) == 0 ) { return -ENOSYS; } uid_t uid = fskit_fuse_get_uid( state ); gid_t gid = fskit_fuse_get_gid( state ); fskit_debug("getattr(%s, %p, %d, %d)\n", path, statbuf, uid, gid ); int rc = fskit_stat( state->core, path, uid, gid, statbuf ); fskit_debug("getattr(%s, %p, %d, %d) rc = %d\n", path, statbuf, uid, gid, rc ); return rc; }
int fskit_fuse_symlink(const char *target, const char *linkpath) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_SYMLINK) == 0 ) { return -ENOSYS; } fskit_debug("symlink(%s, %s)\n", target, linkpath ); int rc = 0; uid_t uid = fskit_fuse_get_uid( state ); gid_t gid = fskit_fuse_get_gid( state ); rc = fskit_symlink( state->core, target, linkpath, uid, gid ); fskit_debug("symlink(%s, %s) rc = %d\n", target, linkpath, rc ); return rc; }
int fskit_fuse_rmdir(const char *path) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_RMDIR) == 0 ) { return -ENOSYS; } fskit_debug("rmdir(%s)\n", path ); uid_t uid = fskit_fuse_get_uid( state ); gid_t gid = fskit_fuse_get_gid( state ); int rc = fskit_rmdir( state->core, path, uid, gid ); fskit_debug("rmdir(%s) rc = %d\n", path, rc ); return rc; }
int fskit_fuse_mknod(const char *path, mode_t mode, dev_t dev) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_MKNOD) == 0 ) { return -ENOSYS; } fskit_debug("mknod(%s, %o, %d, %d)\n", path, mode, major(dev), minor(dev) ); uid_t uid = fskit_fuse_get_uid( state ); gid_t gid = fskit_fuse_get_gid( state ); int rc = fskit_mknod( state->core, path, mode, dev, uid, gid ); fskit_debug("mknod(%s, %o, %d, %d) rc = %d\n", path, mode, major(dev), minor(dev), rc ); return rc; }
int fskit_fuse_statfs(const char *path, struct statvfs *statv) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_STATFS) == 0 ) { return -ENOSYS; } fskit_debug("statfs(%s, %p)\n", path, statv ); uid_t uid = fskit_fuse_get_uid( state ); gid_t gid = fskit_fuse_get_gid( state ); int rc = fskit_statvfs( state->core, path, uid, gid, statv ); fskit_debug("statfs(%s, %p) rc = %d\n", path, statv, rc ); return rc; }
int fskit_fuse_access(const char *path, int mask) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_ACCESS) == 0 ) { return -ENOSYS; } fskit_debug("access(%s, %X)\n", path, mask ); uid_t uid = fskit_fuse_get_uid( state ); gid_t gid = fskit_fuse_get_gid( state ); int rc = fskit_access( state->core, path, uid, gid, mask ); fskit_debug("access(%s, %X) rc = %d\n", path, mask, rc ); return rc; }
int fskit_fuse_ftruncate(const char *path, off_t new_size, struct fuse_file_info *fi) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_FTRUNCATE) == 0 ) { return -ENOSYS; } fskit_debug("ftruncate(%s, %jd, %p)\n", path, new_size, fi ); struct fskit_fuse_file_info* ffi = NULL; ffi = (struct fskit_fuse_file_info*)((uintptr_t)fi->fh); int rc = fskit_ftrunc( state->core, ffi->handle.fh, new_size ); fskit_debug("ftruncate(%s, %jd, %p) rc = %d\n", path, new_size, fi, rc ); return rc; }
int fskit_fuse_create(const char *path, mode_t mode, struct fuse_file_info *fi) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_CREATE) == 0 ) { return -ENOSYS; } fskit_debug("create(%s, %o, %p)\n", path, mode, fi ); uid_t uid = fskit_fuse_get_uid( state ); gid_t gid = fskit_fuse_get_gid( state ); struct fskit_fuse_file_info* ffi = NULL; int rc = 0; struct fskit_file_handle* fh = fskit_create( state->core, path, uid, gid, mode, &rc ); if( rc != 0 ) { fskit_debug("create(%s, %o, %p) rc = %d\n", path, mode, fi, rc ); return rc; } ffi = fskit_fuse_make_file_handle( fh ); if( ffi == NULL ) { fskit_close( state->core, fh ); fskit_debug("create(%s, %o, %p) rc = %d\n", path, mode, fi, -ENOMEM ); return -ENOMEM; } fi->fh = (uintptr_t)ffi; // NOTE: fskit_read() and fskit_write() return a negative error code on error, // so set direct_io to allow this error code to be propagated. fi->direct_io = 1; fskit_debug("create(%s, %o, %p) rc = %d\n", path, mode, fi, rc ); return rc; }
// creat: create the file as usual, but also write to the underlying filesystem as an emergency counter-measure // NOTE: since this is backed by FUSE, this handler will only be called for regular files int vdevfs_create( struct fskit_core* core, struct fskit_match_group* grp, struct fskit_entry* fent, mode_t mode, void** inode_cls, void** handle_cls ) { int fd = 0; struct vdevfs* vdev = (struct vdevfs*)fskit_core_get_user_data( core ); struct fskit_fuse_state* fs_state = fskit_fuse_get_state(); char const* path = NULL; int rc = 0; rc = vdevfs_access_check( vdev, fs_state, "create", grp->path ); if( rc < 0 ) { // denied! return -EACCES; } // must be relative path path = grp->path; while( *path == '/' && *path != '\0' ) { path++; } if( *path == '\0' ) { path = "."; } // success! fd = openat( vdev->mountpoint_dirfd, path, O_CREAT | O_WRONLY | O_TRUNC, mode ); if( fd < 0 ) { fd = -errno; vdev_error("openat('%s', '%s') rc = %d\n", vdev->mountpoint, path, fd ); return fd; } // careful... void* handle_data = NULL; memcpy( &handle_data, &fd, 4 ); *handle_cls = handle_data; return 0; }
int fskit_fuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_READDIR) == 0 ) { return -ENOSYS; } fskit_debug("readdir(%s, %jd, %p, %p)\n", path, offset, buf, fi ); struct fskit_dir_handle* fdh = NULL; struct fskit_fuse_file_info* ffi = NULL; int rc = 0; uint64_t num_read = 0; ffi = (struct fskit_fuse_file_info*)((uintptr_t)fi->fh); fdh = ffi->handle.dh; struct fskit_dir_entry** dirents = fskit_listdir( state->core, fdh, &num_read, &rc ); if( dirents == NULL || rc != 0 ) { fskit_debug("readdir(%s, %jd, %p, %p) rc = %d\n", path, offset, buf, fi, rc ); return rc; } for( uint64_t i = 0; i < num_read; i++ ) { rc = filler( buf, dirents[i]->name, NULL, 0 ); if( rc != 0 ) { rc = -ENOMEM; break; } } fskit_dir_entry_free_list( dirents ); if( rc > 0 ) { rc = 0; } fskit_debug("readdir(%s, %jd, %p, %p) rc = %d\n", path, offset, buf, fi, rc ); return rc; }
int fskit_fuse_release(const char *path, struct fuse_file_info *fi) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_RELEASE) == 0 ) { return -ENOSYS; } fskit_debug("release(%s, %p)\n", path, fi); struct fskit_fuse_file_info* ffi = (struct fskit_fuse_file_info*)((uintptr_t)fi->fh); int rc = fskit_close( state->core, ffi->handle.fh ); if( rc == 0 ) { free( ffi ); } fskit_debug("release(%s, %p) rc = %d\n", path, fi, rc); return rc; }
int fskit_fuse_flush(const char *path, struct fuse_file_info *fi) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_FLUSH) == 0 ) { return -ENOSYS; } int rc = 0; fskit_debug("flush(%s, %p)\n", path, fi); // if this is a file, then fsync it struct fskit_fuse_file_info* ffi = (struct fskit_fuse_file_info*)((uintptr_t)fi->fh); if( ffi->type == FSKIT_ENTRY_TYPE_FILE ) { // same as fsync rc = fskit_fsync( state->core, ffi->handle.fh ); } fskit_debug("flush(%s, %p) rc = %d\n", path, fi, rc); return rc; }
int fskit_fuse_readlink(const char *path, char *link, size_t size) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_READLINK) == 0 ) { return -ENOSYS; } fskit_debug("readlink(%s, %zu)\n", path, size ); ssize_t rc = 0; uid_t uid = fskit_fuse_get_uid( state ); gid_t gid = fskit_fuse_get_gid( state ); rc = fskit_readlink( state->core, path, uid, gid, link, size ); if( rc >= 0 ) { rc = 0; } fskit_debug("readlink(%s, %zu) rc = %zd\n", path, size, rc ); return (int)rc; }
// mkdir: create the directory as normal, but also write to the underlying filesystem as an emergency counter-measure int vdevfs_mkdir( struct fskit_core* core, struct fskit_match_group* grp, struct fskit_entry* fent, mode_t mode, void** inode_cls ) { int rc = 0; struct vdevfs* vdev = (struct vdevfs*)fskit_core_get_user_data( core ); struct fskit_fuse_state* fs_state = fskit_fuse_get_state(); char const* path = NULL; rc = vdevfs_access_check( vdev, fs_state, "mkdir", grp->path ); if( rc < 0 ) { // denied! return -EACCES; } // must be relative path path = grp->path; while( *path == '/' && *path != '\0' ) { path++; } if( *path == '\0' ) { path = "."; } rc = mkdirat( vdev->mountpoint_dirfd, path, mode ); if( rc != 0 ) { rc = -errno; vdev_error("mkdirat('%s', '%s') rc = %d\n", vdev->mountpoint, path, rc ); return rc; } return 0; }
int fskit_fuse_opendir(const char *path, struct fuse_file_info *fi) { struct fskit_fuse_state* state = fskit_fuse_get_state(); if( (state->callbacks & FSKIT_FUSE_OPENDIR) == 0 ) { return -ENOSYS; } fskit_debug("opendir(%s, %p)\n", path, fi ); uid_t uid = fskit_fuse_get_uid( state ); gid_t gid = fskit_fuse_get_gid( state ); struct fskit_fuse_file_info* ffi = NULL; int rc = 0; struct fskit_dir_handle* dh = fskit_opendir( state->core, path, uid, gid, &rc ); if( rc != 0 ) { fskit_debug("opendir(%s, %p) rc = %d\n", path, fi, rc ); return rc; } ffi = fskit_fuse_make_dir_handle( dh ); if( ffi == NULL ) { fskit_closedir( state->core, dh ); fskit_debug("opendir(%s, %p) rc = %d\n", path, fi, -ENOMEM ); return -ENOMEM; } fi->fh = (uintptr_t)ffi; fskit_debug("opendir(%s, %p) rc = %d\n", path, fi, 0 ); return 0; }
void *fskit_fuse_fuse_init(struct fuse_conn_info *conn) { return fskit_fuse_get_state(); }