// 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; }
// close: close as usual // NOTE: since this is backed by FUSE, this handler will only be called for regular files int vdevfs_close( struct fskit_core* core, struct fskit_match_group* grp, struct fskit_entry* fent, void* handle_cls ) { // only care about close() for files if( fskit_entry_get_type( fent ) == FSKIT_ENTRY_TYPE_DIR ) { // done! return 0; } // careful... int fd = 0; memcpy( &fd, &handle_cls, 4 ); int rc = 0; rc = close( fd ); if( rc < 0 ) { rc = -errno; vdev_error("close(%d '%s') rc = %d\n", fd, grp->path, rc ); return rc; } return rc; }
int main( int argc, char** argv ) { struct fskit_core core; int rc; void* output; struct fskit_path_iterator* itr = NULL; struct fskit_file_handle* fh = NULL; rc = fskit_test_begin( &core, NULL ); if( rc != 0 ) { exit(1); } rc = fskit_test_mkdir_LR_recursive( &core, "/root", 7 ); if( rc != 0 ) { fskit_error("fskit_test_mkdir_LR_recursive('/root') rc = %d\n", rc ); exit(1); } fh = fskit_create( &core, "/root/L/R/L/R/L/R/.foo", 0, 0, 0777, &rc ); if( fh == NULL ) { fskit_error("fskit_create('/root/L/R/L/R/L/R/.foo') rc = %d\n", rc ); exit(1); } fskit_close( &core, fh ); fh = fskit_create( &core, "/bar.f", 0, 0, 0777, &rc ); if( fh == NULL ) { fskit_error("fskit_create('/bar.f') rc = %d\n", rc ); exit(1); } fskit_close( &core, fh ); rc = fskit_mkdir( &core, "/bar.d", 0755, 0, 0 ); if( rc < 0 ) { fskit_error("fskit_mkdir('/bar.d') rc = %d\n", rc ); exit(1); } ///////////////////////////////////////////////////////////////////////////////////// printf("\n\nIterate succeeds...\n\n"); for( itr = fskit_path_begin( &core, "/root/L/R/L/R/L/R/.foo", true ); !fskit_path_end( itr ); fskit_path_next( itr ) ) { struct fskit_entry* cur = fskit_path_iterator_entry( itr ); char* cur_path = fskit_path_iterator_path( itr ); printf("Entry %016" PRIX64 " (%p): %c %s\n", fskit_entry_get_file_id( cur ), cur, fskit_entry_get_type( cur ) == FSKIT_ENTRY_TYPE_FILE ? 'F' : 'D', cur_path ); free( cur_path ); } printf("Iterator error: %d\n", fskit_path_iterator_error( itr ) ); fskit_path_iterator_release( itr ); printf("\n\n"); for( itr = fskit_path_begin( &core, "/bar.f", true ); !fskit_path_end( itr ); fskit_path_next( itr ) ) { struct fskit_entry* cur = fskit_path_iterator_entry( itr ); char* cur_path = fskit_path_iterator_path( itr ); printf("Entry %016" PRIX64 " (%p): %c %s\n", fskit_entry_get_file_id( cur ), cur, fskit_entry_get_type( cur ) == FSKIT_ENTRY_TYPE_FILE ? 'F' : 'D', cur_path ); free( cur_path ); } printf("Iterator error: %d\n", fskit_path_iterator_error( itr ) ); fskit_path_iterator_release( itr ); printf("\n\n"); for( itr = fskit_path_begin( &core, "/bar.d", true ); !fskit_path_end( itr ); fskit_path_next( itr ) ) { struct fskit_entry* cur = fskit_path_iterator_entry( itr ); char* cur_path = fskit_path_iterator_path( itr ); printf("Entry %016" PRIX64 " (%p): %c %s\n", fskit_entry_get_file_id( cur ), cur, fskit_entry_get_type( cur ) == FSKIT_ENTRY_TYPE_FILE ? 'F' : 'D', cur_path ); free( cur_path ); } printf("Iterator error: %d\n", fskit_path_iterator_error( itr ) ); fskit_path_iterator_release( itr ); ///////////////////////////////////////////////////////////////////////////////////// printf("\n\nIterate succeeds on path with duplicate . and /...\n\n"); for( itr = fskit_path_begin( &core, "././root/L/R//L//././/R/L//.///R", true ); !fskit_path_end( itr ); fskit_path_next( itr ) ) { struct fskit_entry* cur = fskit_path_iterator_entry( itr ); char* cur_path = fskit_path_iterator_path( itr ); printf("Entry %016" PRIX64 " (%p): %c %s\n", fskit_entry_get_file_id( cur ), cur, fskit_entry_get_type( cur ) == FSKIT_ENTRY_TYPE_FILE ? 'F' : 'D', cur_path ); free( cur_path ); } printf("Iterator error: %d\n", fskit_path_iterator_error( itr ) ); fskit_path_iterator_release( itr ); printf("\n\n"); for( itr = fskit_path_begin( &core, "/././root///././/.//.", true ); !fskit_path_end( itr ); fskit_path_next( itr ) ) { struct fskit_entry* cur = fskit_path_iterator_entry( itr ); char* cur_path = fskit_path_iterator_path( itr ); printf("Entry %016" PRIX64 " (%p): %c %s\n", fskit_entry_get_file_id( cur ), cur, fskit_entry_get_type( cur ) == FSKIT_ENTRY_TYPE_FILE ? 'F' : 'D', cur_path ); free( cur_path ); } printf("Iterator error: %d\n", fskit_path_iterator_error( itr ) ); fskit_path_iterator_release( itr ); ///////////////////////////////////////////////////////////////////////////////////// printf("\n\nIterate fails (path too long)...\n\n"); for( itr = fskit_path_begin( &core, "/root/L/R/L/R/L/R/L/R/L/R/L/R/L/R/L/R", true ); !fskit_path_end( itr ); fskit_path_next( itr ) ) { struct fskit_entry* cur = fskit_path_iterator_entry( itr ); char* cur_path = fskit_path_iterator_path( itr ); printf("Entry %016" PRIX64 " (%p): %c %s\n", fskit_entry_get_file_id( cur ), cur, fskit_entry_get_type( cur ) == FSKIT_ENTRY_TYPE_FILE ? 'F' : 'D', cur_path ); free( cur_path ); } printf("Iterator error: %d\n", fskit_path_iterator_error( itr ) ); fskit_path_iterator_release( itr ); ///////////////////////////////////////////////////////////////////////////////////// printf("\n\nIterate fails (path does not exist)...\n\n"); for( itr = fskit_path_begin( &core, "/root/L/R/L/foo/L/R", true ); !fskit_path_end( itr ); fskit_path_next( itr ) ) { struct fskit_entry* cur = fskit_path_iterator_entry( itr ); char* cur_path = fskit_path_iterator_path( itr ); printf("Entry %016" PRIX64 " (%p): %c %s\n", fskit_entry_get_file_id( cur ), cur, fskit_entry_get_type( cur ) == FSKIT_ENTRY_TYPE_FILE ? 'F' : 'D', cur_path ); free( cur_path ); } printf("Iterator error: %d\n\n\n", fskit_path_iterator_error( itr ) ); fskit_path_iterator_release( itr ); fskit_test_end( &core, &output ); return 0; }
// open: open the file as usual, but from the underlying filesystem // NOTE: since this is backed by FUSE, this handler will only be called for regular files int vdevfs_open( struct fskit_core* core, struct fskit_match_group* grp, struct fskit_entry* fent, int flags, 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; // dir or file? char const* method = NULL; if( fskit_entry_get_type( fent ) == FSKIT_ENTRY_TYPE_DIR ) { rc = vdevfs_access_check( vdev, fs_state, "opendir", grp->path ); } else { rc = vdevfs_access_check( vdev, fs_state, "open", grp->path ); } if( rc < 0 ) { // denied! return -ENOENT; } // only care about open() for files if( fskit_entry_get_type( fent ) == FSKIT_ENTRY_TYPE_DIR ) { // done! return 0; } // must be relative path path = grp->path; while( *path == '/' && *path != '\0' ) { path++; } if( *path == '\0' ) { path = "."; } fd = openat( vdev->mountpoint_dirfd, path, flags ); if( fd < 0 ) { fd = -errno; vdev_error("openat(%d, '%s') rc = %d\n", vdev->mountpoint_dirfd, path, fd ); return fd; } // careful... void* handle_data = NULL; memcpy( &handle_data, &fd, 4 ); *handle_cls = handle_data; return 0; }