📄 fs.c
字号:
retval = sos_fs_write(tmp_of, symlink_target, & len); mark_dirty_fsnode(fsnode, FALSE); fsnode->close_opened_file(fsnode, tmp_of); if ((SOS_OK != retval) || (len != symlink_target_len)) { fs_remove_node(creator, symlink); if (SOS_OK == retval) retval = -SOS_ENAMETOOLONG; } sos_fs_nscache_unref_node(symlink); return retval;}sos_ret_t sos_fs_mkdir(const struct sos_process * creator, const char * _path, sos_size_t _pathlen, sos_ui32_t access_rights){ struct sos_fs_pathname path; path.contents = _path; path.length = _pathlen; return fs_create_node(& path, creator, access_rights, SOS_FS_NODE_DIRECTORY, NULL);}sos_ret_t sos_fs_rmdir(const struct sos_process * actor, const char * _path, sos_size_t _pathlen){ sos_ret_t retval; struct sos_fs_pathname path; struct sos_fs_nscache_node * nsnode; path.contents = _path; path.length = _pathlen; if (path.length <= 0) return -SOS_ENOENT; if (path.contents[0] == '/') nsnode = sos_process_get_root(actor)->direntry; else nsnode = sos_process_get_cwd(actor)->direntry; retval = fs_lookup_node(& path, FALSE, sos_process_get_root(actor)->direntry, nsnode, & nsnode, & path, 0); if (SOS_OK != retval) return retval; /* Make sure the whole path has been resolved */ if (path.length > 0) { sos_fs_nscache_unref_node(nsnode); return -SOS_ENOENT; } /* Cannot rmdir non-dir nodes */ if (sos_fs_nscache_get_fs_node(nsnode)->type != SOS_FS_NODE_DIRECTORY) retval = -SOS_ENOTDIR; /* Cannot remove directory if it is still used by somebody else */ else if (sos_fs_nscache_get_ref_cnt(nsnode) > 1) retval = -SOS_EBUSY; /* Cannot remove directory if it is still has children stored on disk */ else if (sos_fs_nscache_get_fs_node(nsnode)->ondisk_lnk_cnt > 1) retval = -SOS_ENOTEMPTY; /* Otherwise, yes : suppress the node on disk */ else retval = fs_remove_node(actor, nsnode); sos_fs_nscache_unref_node(nsnode); return retval;}sos_ret_t sos_fs_stat(const struct sos_process * actor, const char * _path, sos_size_t _pathlen, int nofollow, struct sos_fs_stat * result){ sos_ret_t retval; struct sos_fs_pathname path; struct sos_fs_nscache_node * nsnode; struct sos_fs_node * fsnode; path.contents = _path; path.length = _pathlen; if (path.length <= 0) return -SOS_ENOENT; if (path.contents[0] == '/') nsnode = sos_process_get_root(actor)->direntry; else nsnode = sos_process_get_cwd(actor)->direntry; retval = fs_lookup_node(& path, (nofollow != 0), sos_process_get_root(actor)->direntry, nsnode, & nsnode, & path, 0); if (SOS_OK != retval) return retval; /* Make sure the whole path has been resolved */ if (path.length > 0) { sos_fs_nscache_unref_node(nsnode); return -SOS_ENOENT; } fsnode = sos_fs_nscache_get_fs_node(nsnode); retval = fsnode->ops_file->stat(fsnode, result); sos_fs_nscache_unref_node(nsnode); return retval;}sos_ret_t sos_fs_fsync(struct sos_fs_opened_file * of){ struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(of->direntry); return fsnode->ops_file->sync(fsnode);}sos_ret_t sos_fs_chmod(const struct sos_process * actor, const char * _path, sos_size_t _pathlen, sos_ui32_t access_rights){ sos_ret_t retval; struct sos_fs_pathname path; struct sos_fs_nscache_node * nsnode; struct sos_fs_node * fsnode; path.contents = _path; path.length = _pathlen; if (path.length <= 0) return -SOS_ENOENT; if (path.contents[0] == '/') nsnode = sos_process_get_root(actor)->direntry; else nsnode = sos_process_get_cwd(actor)->direntry; retval = fs_lookup_node(& path, TRUE, sos_process_get_root(actor)->direntry, nsnode, & nsnode, & path, 0); if (SOS_OK != retval) return retval; /* Make sure the whole path has been resolved */ if (path.length > 0) { sos_fs_nscache_unref_node(nsnode); return -SOS_ENOENT; } fsnode = sos_fs_nscache_get_fs_node(nsnode); retval = fsnode->ops_file->chmod(fsnode, access_rights); if (SOS_OK == retval) mark_dirty_fsnode(fsnode, FALSE); sos_fs_nscache_unref_node(nsnode); return retval;}sos_ret_t sos_fs_vfstat(const struct sos_process * actor, const char * _path, sos_size_t _pathlen, struct sos_fs_statfs * result){ sos_ret_t retval; struct sos_fs_pathname path; struct sos_fs_nscache_node * nsnode; struct sos_fs_node * fsnode; path.contents = _path; path.length = _pathlen; if (path.length <= 0) return -SOS_ENOENT; if (path.contents[0] == '/') nsnode = sos_process_get_root(actor)->direntry; else nsnode = sos_process_get_cwd(actor)->direntry; retval = fs_lookup_node(& path, FALSE, sos_process_get_root(actor)->direntry, nsnode, & nsnode, & path, 0); if (SOS_OK != retval) return retval; /* Make sure the whole path has been resolved */ if (path.length > 0) { sos_fs_nscache_unref_node(nsnode); return -SOS_ENOENT; } fsnode = sos_fs_nscache_get_fs_node(nsnode); if (fsnode->fs->statfs) retval = fsnode->fs->statfs(fsnode->fs, result); else retval = -SOS_ENOSUP; sos_fs_nscache_unref_node(nsnode); return retval; }/** This function is resilient against mounting/unmounting of other FS */sos_ret_t sos_fs_sync_all_fs(){ int dummy = 0; sos_ui64_t uid = 0; while (1) { /* Iterate over the FS types */ struct sos_fs_manager_type * fstype; int ntype; list_foreach(fs_list, fstype, ntype) { /* Iterate over the FS instances */ struct sos_fs_manager_instance * fs; int ninst; list_foreach(fstype->instances, fs, ninst) { if (fs->uid <= uid) continue; uid = fs->uid; sos_fs_sync_fs(fs); /* We must NOT continue the loops because the prev/next/current fs types/instances might have been removed or added (sync blocks, by definition) ! */ goto lookup_next_fs; } } lookup_next_fs: /* Loop over */ dummy ++; } return SOS_OK;}/* ************************************************************* * mount/umount stuff */sos_ret_t sos_fs_register_fs_instance(struct sos_fs_manager_instance * fs, struct sos_fs_node * root_fsnode){ sos_ret_t retval; struct sos_fs_nscache_node * nsnode_root; retval = sos_fs_nscache_create_mounted_root(root_fsnode, & nsnode_root); if (SOS_OK != retval) return retval; fs->uid = ++last_fs_instance_uid; fs->root = nsnode_root; sos_hash_insert(fs->nodecache, root_fsnode); list_add_tail(fs->fs_type->instances, fs); return SOS_OK;}sos_ret_t sos_fs_unregister_fs_instance(struct sos_fs_manager_instance * fs){ fs->uid = 0; list_delete(fs->fs_type->instances, fs); return SOS_OK;}sos_ret_t sos_fs_register_fs_type(struct sos_fs_manager_type * fstype){ struct sos_fs_manager_type * iterator; int nbtypes; list_foreach_forward(fs_list, iterator, nbtypes) { if (! strncmp(fstype->name, iterator->name, SOS_FS_MANAGER_NAME_MAXLEN)) return -SOS_EEXIST; } list_add_tail(fs_list, fstype); return SOS_OK;}sos_ret_t sos_fs_unregister_fs_type(struct sos_fs_manager_type * fstype){ struct sos_fs_manager_type * iterator; int nbtypes; if (! list_is_empty(fstype->instances)) return -SOS_EBUSY; list_foreach_forward(fs_list, iterator, nbtypes) { if (! strncmp(fstype->name, iterator->name, SOS_FS_MANAGER_NAME_MAXLEN)) { list_delete(fs_list, fstype); return SOS_OK; } } return -SOS_EINVAL;}/** * _src_path may be empty */sos_ret_t sos_fs_mount(struct sos_process * actor, const char * _src_path, sos_size_t _src_pathlen, const char * _dst_path, sos_size_t _dst_pathlen, const char * fsname, sos_ui32_t mountflags, const char * args, struct sos_fs_manager_instance ** result_fs){ sos_ret_t retval; struct sos_fs_pathname src_path, dst_path; struct sos_fs_nscache_node * src_nsnode, * dst_nsnode; struct sos_fs_manager_type * fs_type; struct sos_fs_manager_instance * new_fs; int nb_fstypes; if (_dst_pathlen <= 0) return -SOS_ENOENT; /* Look for the FS manager type */ list_foreach(fs_list, fs_type, nb_fstypes) { if (! strcmp(fsname, fs_type->name)) break; } if (! list_foreach_early_break(fs_list, fs_type, nb_fstypes)) return -SOS_ENODEV; src_path.contents = _src_path; src_path.length = _src_pathlen; /* Compute the start_nsnode for the source */ if (src_path.length <= 0) src_nsnode = NULL; else if (src_path.contents[0] == '/') src_nsnode = sos_process_get_root(actor)->direntry; else src_nsnode = sos_process_get_cwd(actor)->direntry; /* Lookup the source node */ if (src_nsnode) { retval = fs_lookup_node(& src_path, TRUE, sos_process_get_root(actor)->direntry, src_nsnode, & src_nsnode, & src_path, 0); if (SOS_OK != retval) return retval; /* Make sure the whole path has been resolved */ if (src_path.length > 0) { sos_fs_nscache_unref_node(src_nsnode); return -SOS_ENOENT; } } dst_path.contents = _dst_path; dst_path.length = _dst_pathlen; /* Compute the start_nsnode for the destination */ if (dst_path.contents[0] == '/') dst_nsnode = sos_process_get_root(actor)->direntry; else dst_nsnode = sos_process_get_cwd(actor)->direntry; /* Lookup the destination node */ retval = fs_lookup_node(& dst_path, TRUE, sos_process_get_root(actor)->direntry, dst_nsnode, & dst_nsnode, & dst_path, 0); if ((SOS_OK != retval) || (dst_path.length > 0)) { if (src_nsnode) sos_fs_nscache_unref_node(src_nsnode); if (dst_path.length > 0) retval = -SOS_ENOENT; return retval; } /* Actually call the mount callback of the FS */ retval = fs_type->mount(fs_type, (src_nsnode)?sos_fs_nscache_get_fs_node(src_nsnode):NULL, args, & new_fs); if (SOS_OK != retval) { if (src_nsnode) sos_fs_nscache_unref_node(src_nsnode); sos_fs_nscache_unref_node(dst_nsnode); return retval; } /* Make sure the nodecache was created */ SOS_ASSERT_FATAL(NULL != new_fs->nodecache); SOS_ASSERT_FATAL(NULL != new_fs->root); /* Update some reserved fields */ sos_fs_nscache_get_fs_node(new_fs->root)->fs = new_fs; /* Register the mountpoint in the nscache */ retval = sos_fs_nscache_mount(dst_nsnode, new_fs->root); SOS_ASSERT_FATAL(SOS_OK == retval); /* Un-reference the temporary nsnodes */ if (src_nsnode) sos_fs_nscache_unref_node(src_nsnode); sos_fs_nscache_unref_node(dst_nsnode); if (result_fs) *result_fs = new_fs; return SOS_OK;}sos_ret_t sos_fs_umount(struct sos_process * actor, const char * _mounted_root_path, sos_size_t _mounted_root_pathlen){ sos_ret_t retval; struct sos_fs_pathname mounted_root_path; struct sos_fs_nscache_node * mounted_root_nsnode; struct sos_fs_manager_instance * fs; if (_mounted_root_pathlen <= 0) return -SOS_ENOENT; mounted_root_path.contents = _mounted_root_path; mounted_root_path.length = _mounted_root_pathlen; /* Compute the start_nsnode for the mounted_root */ if (mounted_root_path.contents[0] == '/') mounted_root_nsnode = sos_process_get_root(actor)->direntry; else mounted_root_nsnode = sos_process_get_cwd(actor)->direntry; /* Lookup the mounted_root node */ retval = fs_lookup_node(& mounted_root_path, TRUE, sos_process_get_root(actor)->direntry, mounted_root_nsnode, & mounted_root_nsnode, & mounted_root_path, 0); if (SOS_OK != retval) return retval; /* Make sure the whole path has been resolved */ if (mounted_root_path.length > 0) { sos_fs_nscache_unref_node(mounted_root_nsnode); return -SOS_ENOENT; } /* Make sure this node is the real root of the FS */ fs = sos_fs_nscache_get_fs_node(mounted_root_nsnode)->fs; if (fs->root != mounted_root_nsnode) { sos_fs_nscache_unref_node(mounted_root_nsnode); return -SOS_ENOENT; } /* Disconnect this FS mounted_root from namespace cache */ retval = sos_fs_nscache_umount(mounted_root_nsnode); /* Mounted_Root not needed anymore */ sos_fs_nscache_unref_node(mounted_root_nsnode); if (SOS_OK != retval) return retval; fs->root = NULL; /* Flush any changes to disk */ retval = sos_fs_sync_fs(fs); if (SOS_OK != retval) { return retval; } retval = fs->fs_type->umount(fs->fs_type, fs); return retval;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -