📄 fs.c
字号:
| SOS_FS_OPEN_EXCL | SOS_FS_OPEN_NOFOLLOW | SOS_FS_OPEN_DIRECTORY); if (! (fsnode->access_rights & SOS_FS_WRITABLE)) open_flags &= ~(SOS_FS_OPEN_WRITE); if (! (fsnode->access_rights & SOS_FS_READABLE)) open_flags &= ~(SOS_FS_OPEN_READ); if (fsnode->fs->flags & SOS_FS_MOUNT_READONLY) open_flags &= ~(SOS_FS_OPEN_READ); /* * Ok, open it right now ! */ retval = sos_fs_new_opened_file(owner, nsnode, open_flags, of); sos_fs_nscache_unref_node(nsnode); return retval;}sos_ret_t sos_fs_close(struct sos_fs_opened_file * of){ return sos_fs_unref_opened_file(of);}sos_ret_t sos_fs_mark_dirty(struct sos_fs_opened_file * of){ struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(of->direntry); /* This function should never get called if the FS is read-only */ SOS_ASSERT_FATAL(! (fsnode->fs->flags & SOS_FS_MOUNT_READONLY)); return mark_dirty_fsnode(fsnode, of->open_flags & SOS_FS_OPEN_SYNC);}sos_ret_t sos_fs_read(struct sos_fs_opened_file * of, sos_uaddr_t dest_buf, sos_size_t * /* in/ou */len){ if (! (of->open_flags & SOS_FS_OPEN_READ)) return -SOS_EPERM; if (! of->ops_file->read) return -SOS_ENOSUP; return of->ops_file->read(of, dest_buf, len);}sos_ret_t sos_fs_write(struct sos_fs_opened_file * of, sos_uaddr_t src_buf, sos_size_t * /* in/out */len){ if (! (of->open_flags & SOS_FS_OPEN_WRITE)) return -SOS_EPERM; if (! of->ops_file->write) return -SOS_ENOSUP; return of->ops_file->write(of, src_buf, len);}sos_ret_t sos_fs_seek(struct sos_fs_opened_file *of, sos_lsoffset_t offset, sos_seek_whence_t whence, sos_lsoffset_t * result_position){ if (! of->ops_file->seek) return -SOS_ENOSUP; return of->ops_file->seek(of, offset, whence, result_position);}sos_ret_t sos_fs_ftruncate(struct sos_fs_opened_file *of, sos_lsoffset_t length){ sos_ret_t retval; struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(of->direntry); if (! (of->open_flags & SOS_FS_OPEN_WRITE)) return -SOS_EPERM; if (! fsnode->ops_file->truncate) return -SOS_ENOSUP; retval = fsnode->ops_file->truncate(fsnode, length); if (SOS_OK == retval) mark_dirty_fsnode(fsnode, FALSE); return retval;}sos_ret_t sos_fs_mmap(struct sos_fs_opened_file *of, sos_uaddr_t *uaddr, sos_size_t size, sos_ui32_t access_rights, sos_ui32_t flags, sos_luoffset_t offset){ sos_ui32_t required_access = 0; struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(of->direntry); if (! of->ops_file->mmap) return -SOS_ENOSUP; /* Translate VM requested rights into FS equivalent */ if (access_rights & SOS_VM_MAP_PROT_READ) required_access |= SOS_FS_OPEN_READ; if ( (access_rights & SOS_VM_MAP_PROT_WRITE) && (flags & SOS_VR_MAP_SHARED) ) required_access |= SOS_FS_OPEN_WRITE; if (access_rights & SOS_VM_MAP_PROT_EXEC) required_access |= SOS_FS_OPEN_READ; /* Make sure that the opened file allowed this access */ if ((of->open_flags & required_access) != required_access) return -SOS_EPERM; if ( (access_rights & SOS_VM_MAP_PROT_EXEC) && (fsnode->fs->flags & SOS_FS_MOUNT_NOEXEC) ) return -SOS_EPERM; return of->ops_file->mmap(of, uaddr, size, access_rights, flags, offset); }sos_ret_t sos_fs_fcntl(struct sos_fs_opened_file *of, int req_id, sos_ui32_t req_arg /* Usually: sos_uaddr_t */){ if (! of->ops_file->fcntl) return -SOS_ENOSUP; return of->ops_file->fcntl(of, req_id, req_arg);}sos_ret_t sos_fs_readdir(struct sos_fs_opened_file * of, struct sos_fs_dirent * result){ struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(of->direntry); if (fsnode->type != SOS_FS_NODE_DIRECTORY) return -SOS_ENOTDIR; return of->ops_dir->readdir(of, result);}sos_ret_t sos_fs_creat(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_REGULAR_FILE, NULL);}sos_ret_t sos_fs_link(const struct sos_process * creator, const char * _old_path, sos_size_t _old_pathlen, const char * _new_path, sos_size_t _new_pathlen){ sos_ret_t retval; struct sos_fs_nscache_node *old_nsnode, *dest_parent_nsnode, *new_nsnode; struct sos_fs_node * fsnode; struct sos_fs_pathname old_path, new_path; if (_old_pathlen <= 0) return -SOS_ENOENT; if (_new_pathlen <= 0) return -SOS_ENOENT; /* Resolve target FS node using "old_path" */ old_path.contents = _old_path; old_path.length = _old_pathlen; if (old_path.contents[0] == '/') old_nsnode = sos_process_get_root(creator)->direntry; else old_nsnode = sos_process_get_cwd(creator)->direntry; retval = fs_lookup_node(& old_path, FALSE /* don't follow symlink */, sos_process_get_root(creator)->direntry, old_nsnode, & old_nsnode, & old_path, 0); if (SOS_OK != retval) return retval; if (old_path.length > 0) { /* Could not resolve full path ! */ sos_fs_nscache_unref_node(old_nsnode); return -SOS_ENOENT; } fsnode = sos_fs_nscache_get_fs_node(old_nsnode); /* Not allowed to link directories ! */ if (fsnode->type == SOS_FS_NODE_DIRECTORY) { sos_fs_nscache_unref_node(old_nsnode); return -SOS_ENOENT; } /* Resolve destination path */ new_path.contents = _new_path; new_path.length = _new_pathlen; if (new_path.contents[0] == '/') dest_parent_nsnode = sos_process_get_root(creator)->direntry; else dest_parent_nsnode = sos_process_get_cwd(creator)->direntry; retval = fs_lookup_node(& new_path, TRUE /* Follow symlink */, sos_process_get_root(creator)->direntry, dest_parent_nsnode, & dest_parent_nsnode, & new_path, 0); if (SOS_OK != retval) { sos_fs_nscache_unref_node(old_nsnode); return retval; } if (new_path.length == 0) { /* Found the exact match ! Not allowed to overwrite it ! */ sos_fs_nscache_unref_node(dest_parent_nsnode); sos_fs_nscache_unref_node(old_nsnode); return -SOS_EEXIST; } /* Create a new entry in the file system */ retval = fs_register_child_node(creator, dest_parent_nsnode, & new_path, fsnode, 0, & new_nsnode); sos_fs_nscache_unref_node(dest_parent_nsnode); sos_fs_nscache_unref_node(old_nsnode); sos_fs_nscache_unref_node(new_nsnode); return retval;}sos_ret_t sos_fs_rename(const struct sos_process * actor, const char * _old_path, sos_size_t _old_pathlen, const char * _new_path, sos_size_t _new_pathlen){ sos_ret_t retval; struct sos_fs_nscache_node *old_nsnode, *old_parent_nsnode, *dest_parent_nsnode, *replaced_nsnode; struct sos_fs_pathname old_name, replaced_name; struct sos_fs_pathname old_path, new_path; old_nsnode = old_parent_nsnode = dest_parent_nsnode = replaced_nsnode = NULL; if (_old_pathlen <= 0) return -SOS_ENOENT; if (_new_pathlen <= 0) return -SOS_ENOENT; /* Resolve target FS node using "old_path" */ old_path.contents = _old_path; old_path.length = _old_pathlen; if (old_path.contents[0] == '/') old_nsnode = sos_process_get_root(actor)->direntry; else old_nsnode = sos_process_get_cwd(actor)->direntry; retval = fs_lookup_node(& old_path, FALSE /* don't follow symlink */, sos_process_get_root(actor)->direntry, old_nsnode, & old_nsnode, & old_path, 0); if (SOS_OK != retval) return retval; if (old_path.length > 0) { /* Could not resolve full path ! */ sos_fs_nscache_unref_node(old_nsnode); return -SOS_ENOENT; } /* Not allowed to rename mountpoints ! */ if (sos_fs_nscache_is_mountnode(old_nsnode)) { sos_fs_nscache_unref_node(old_nsnode); return -SOS_ENOENT; } /* Keep a reference on this node's parent, in case we must undo the rename */ retval = sos_fs_nscache_get_parent(old_nsnode, & old_parent_nsnode); if (SOS_OK != retval) { sos_fs_nscache_unref_node(old_nsnode); return retval; } sos_fs_nscache_ref_node(old_parent_nsnode); /* Resolve destination path */ replaced_nsnode = NULL; new_path.contents = _new_path; new_path.length = _new_pathlen; if (new_path.contents[0] == '/') dest_parent_nsnode = sos_process_get_root(actor)->direntry; else dest_parent_nsnode = sos_process_get_cwd(actor)->direntry; retval = fs_lookup_node(& new_path, TRUE /* Follow symlink */, sos_process_get_root(actor)->direntry, dest_parent_nsnode, & dest_parent_nsnode, & new_path, 0); if (SOS_OK != retval) { goto undo_rename; } /* Nothing to do ? */ if (old_nsnode == dest_parent_nsnode) { sos_fs_nscache_unref_node(old_nsnode); sos_fs_nscache_unref_node(old_parent_nsnode); sos_fs_nscache_unref_node(dest_parent_nsnode); return SOS_OK; } /* Remove old nsnode from file ns cache */ sos_fs_nscache_get_name(old_nsnode, & old_name); retval = fs_remove_node(actor, old_nsnode); if (SOS_OK != retval) { sos_fs_nscache_unref_node(old_nsnode); sos_fs_nscache_unref_node(old_parent_nsnode); sos_fs_nscache_unref_node(dest_parent_nsnode); return -SOS_ENOENT; } if (new_path.length == 0) { /* Found the exact match ! We disconnect it from the namespace, but keep it aside */ /* Not allowed to replace directories */ if (sos_fs_nscache_get_fs_node(dest_parent_nsnode)->type == SOS_FS_NODE_DIRECTORY) { retval = -SOS_EBUSY; goto undo_rename; } replaced_nsnode = dest_parent_nsnode; dest_parent_nsnode = NULL; /* Retrieve the parent of the node to replace */ retval = sos_fs_nscache_get_parent(replaced_nsnode, & dest_parent_nsnode); if (SOS_OK != retval) { dest_parent_nsnode = replaced_nsnode; goto undo_rename; } sos_fs_nscache_ref_node(dest_parent_nsnode); /* Disconnect this node from its parent */ sos_fs_nscache_get_name(replaced_nsnode, & replaced_name); retval = fs_remove_node(actor, replaced_nsnode); if (SOS_OK != retval) goto undo_rename; } /* Create a new entry in the file system */ retval = fs_connect_existing_child_node(actor, dest_parent_nsnode, & new_path, old_nsnode); if (SOS_OK != retval) goto undo_rename; sos_fs_nscache_unref_node(old_nsnode); sos_fs_nscache_unref_node(old_parent_nsnode); sos_fs_nscache_unref_node(dest_parent_nsnode); if (NULL != replaced_nsnode) sos_fs_nscache_unref_node(replaced_nsnode); return retval; undo_rename: /* Handle special case: the node replaced something. In case the previous operation failed, we try to reinsert the replaced node */ if (NULL != replaced_nsnode) { fs_connect_existing_child_node(actor, dest_parent_nsnode, & replaced_name, replaced_nsnode); sos_fs_nscache_unref_node(replaced_nsnode); } fs_connect_existing_child_node(actor, old_parent_nsnode, & old_name, old_nsnode); sos_fs_nscache_unref_node(old_nsnode); sos_fs_nscache_unref_node(old_parent_nsnode); if (NULL != dest_parent_nsnode) sos_fs_nscache_unref_node(dest_parent_nsnode); return retval;}sos_ret_t sos_fs_unlink(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; } if (sos_fs_nscache_get_fs_node(nsnode)->type == SOS_FS_NODE_DIRECTORY) retval = -SOS_EISDIR; else retval = fs_remove_node(actor, nsnode); sos_fs_nscache_unref_node(nsnode); return retval;}sos_ret_t sos_fs_symlink(const struct sos_process * creator, const char * _path, sos_size_t _pathlen, sos_uaddr_t symlink_target, sos_size_t symlink_target_len){ sos_ret_t retval; struct sos_fs_pathname path; struct sos_fs_node * fsnode; struct sos_fs_nscache_node * symlink; struct sos_fs_opened_file * tmp_of; sos_size_t len; path.contents = _path; path.length = _pathlen; retval = fs_create_node(& path, creator, SOS_FS_S_IRWXALL, SOS_FS_NODE_SYMLINK, & symlink); if (SOS_OK != retval) return retval; /* Artificially open the symlink to change its contents */ fsnode = sos_fs_nscache_get_fs_node(symlink); retval = fsnode->new_opened_file(fsnode, creator, SOS_FS_OPEN_WRITE, & tmp_of); if (SOS_OK != retval) { fs_remove_node(creator, symlink); sos_fs_nscache_unref_node(symlink); return retval; } tmp_of->ref_cnt = 1; retval = sos_fs_nscache_register_opened_file(symlink, tmp_of); if (SOS_OK != retval) { fsnode->close_opened_file(fsnode, tmp_of); fs_remove_node(creator, symlink); sos_fs_nscache_unref_node(symlink); return retval; } len = symlink_target_len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -