int fskit_test_mkdir_LR_recursive( struct fskit_core* core, char const* path, int depth ) { if( depth <= 0 ) { return 0; } fskit_debug("mkdir('%s')\n", path ); int rc = fskit_mkdir( core, path, 0755, 0, 0 ); if( rc != 0 ) { fskit_error("fskit_mkdir('%s') rc = %d\n", path, rc ); return rc; } char* new_path_1 = fskit_fullpath( path, "L", NULL ); char* new_path_2 = fskit_fullpath( path, "R", NULL ); rc = fskit_test_mkdir_LR_recursive( core, new_path_1, depth - 1 ); if( rc != 0 ) { fskit_error("fskit_test_mkdir_LR_recursive('%s') rc = %d\n", new_path_1, rc ); free( new_path_1 ); free( new_path_2 ); return rc; } rc = fskit_test_mkdir_LR_recursive( core, new_path_2, depth - 1 ); if( rc != 0 ) { fskit_error("fskit_test_mkdir_LR_recursive('%s') rc = %d\n", new_path_2, rc ); free( new_path_1 ); free( new_path_2 ); return rc; } free( new_path_1 ); free( new_path_2 ); return 0; }
// print out a tree to the given file stream int fskit_print_tree( FILE* out, struct fskit_entry* root ) { struct fskit_entry* node = NULL; char* next_path = NULL; char type_str[10]; int rc = 0; fskit_entry_set_itr itr; fskit_entry_set* child = NULL; vector< struct fskit_entry* > frontier; vector< char* > frontier_paths; frontier.push_back( root ); frontier_paths.push_back( strdup(root->name) ); while( frontier.size() > 0 ) { node = frontier[0]; next_path = frontier_paths[0]; frontier.erase( frontier.begin() ); frontier_paths.erase( frontier_paths.begin() ); fskit_type_to_string( node->type, type_str ); fprintf( out, "%s: inode=%" PRIX64 " size=%jd mode=%o user=%" PRIu64 " group=%" PRIu64 " ctime=(%" PRId64 ".%" PRId32 ") mtime=(%" PRId64 ".%" PRId32 ") atime=(%" PRId64 ".%" PRId32 ") mem=%p \"%s\"\n", type_str, node->file_id, node->size, node->mode, node->owner, node->group, node->ctime_sec, node->ctime_nsec, node->mtime_sec, node->mtime_nsec, node->atime_sec, node->atime_nsec, node, next_path ); if( node->type == FSKIT_ENTRY_TYPE_DIR ) { if( node->children == NULL ) { fskit_error("ERR: children of %p == NULL\n", node ); rc = -EINVAL; break; } // explore children for( child = fskit_entry_set_begin( node->children, &itr ); child != NULL; child = fskit_entry_set_next( &itr ) ) { char const* name = fskit_entry_set_name_at( &itr ); struct fskit_entry* child = fskit_entry_set_child_at( &itr ); if( child == NULL ) { continue; } if( strcmp(".", name) == 0 || strcmp("..", name) == 0 ) { continue; } frontier.push_back( child ); frontier_paths.push_back( fskit_fullpath( next_path, child->name, NULL ) ); } } free( next_path ); } if( rc != 0 ) { for( unsigned int i = 0; i < frontier_paths.size(); i++ ) { if( frontier_paths.at(i) ) { free( frontier_paths.at(i) ); } } frontier_paths.clear(); } return rc; }
// readdir: equivocate about which devices exist, depending on who's asking // omit entries if the ACLs forbid them int vdevfs_readdir( struct fskit_core* core, struct fskit_match_group* grp, struct fskit_entry* fent, struct fskit_dir_entry** dirents, size_t num_dirents ) { int rc = 0; struct fskit_entry* child = NULL; // entries to omit in the listing vector<int> omitted_idx; pid_t pid = 0; uid_t uid = 0; gid_t gid = 0; struct vdevfs* vdev = (struct vdevfs*)fskit_core_get_user_data( core ); struct fskit_fuse_state* fs_state = fskit_fuse_get_state(); struct stat sb; struct pstat ps; char* child_path = NULL; pid = fskit_fuse_get_pid(); uid = fskit_fuse_get_uid( fs_state ); gid = fskit_fuse_get_gid( fs_state ); vdev_debug("vdevfs_readdir(%s, %zu) from user %d group %d task %d\n", grp->path, num_dirents, uid, gid, pid ); // see who's asking rc = pstat( pid, &ps, 0 ); if( rc != 0 ) { vdev_error("pstat(%d) rc = %d\n", pid, rc ); return -EIO; } for( unsigned int i = 0; i < num_dirents; i++ ) { // skip . and .. if( strcmp(dirents[i]->name, ".") == 0 || strcmp(dirents[i]->name, "..") == 0 ) { continue; } // find the associated fskit_entry child = fskit_dir_find_by_name( fent, dirents[i]->name ); if( child == NULL ) { // strange, shouldn't happen... continue; } fskit_entry_rlock( child ); // construct a stat buffer from what we actually need memset( &sb, 0, sizeof(struct stat) ); sb.st_uid = child->owner; sb.st_gid = child->group; sb.st_mode = fskit_fullmode( child->type, child->mode ); child_path = fskit_fullpath( grp->path, child->name, NULL ); if( child_path == NULL ) { // can't continue; OOM fskit_entry_unlock( child ); rc = -ENOMEM; break; } // filter it rc = vdev_acl_apply_all( vdev->config, vdev->acls, vdev->num_acls, child_path, &ps, uid, gid, &sb ); if( rc < 0 ) { vdev_error("vdev_acl_apply_all('%s', uid=%d, gid=%d, pid=%d) rc = %d\n", child_path, uid, gid, pid, rc ); rc = -EIO; } else if( rc == 0 || (sb.st_mode & 0777) == 0 ) { // omit this one vdev_debug("Filter '%s'\n", child->name ); omitted_idx.push_back( i ); rc = 0; } else { // success; matched rc = 0; } fskit_entry_unlock( child ); free( child_path ); // error? if( rc != 0 ) { break; } } // skip ACL'ed entries for( unsigned int i = 0; i < omitted_idx.size(); i++ ) { fskit_readdir_omit( dirents, omitted_idx[i] ); } return rc; }