⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fs.c

📁 Simple Operating Systems (简称SOS)是一个可以运行在X86平台上(包括QEMU
💻 C
📖 第 1 页 / 共 4 页
字号:
		  | 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 + -