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

📄 fs.c

📁 Simple Operating Systems (简称SOS)是一个可以运行在X86平台上(包括QEMU
💻 C
📖 第 1 页 / 共 4 页
字号:
	   * disk...	   */	  current_fsnode = sos_fs_nscache_get_fs_node(current_nsnode);	  retval = current_fsnode->ops_dir	    ->lookup(current_fsnode,		     current_component.contents,		     current_component.length,		     & storage_location);	  if (SOS_OK != retval)	    {	      /* Well, we cannot go further, stop here */	      *result_nsnode = current_nsnode;	      return SOS_OK;	    }	  /* Now retrieve this node from disk or from the cache into	     memory */	  retval = fs_fetch_node(current_fsnode->fs,				 storage_location, & next_fsnode);	  if (SOS_OK != retval)	    {	      sos_fs_nscache_unref_node(current_nsnode);	      return retval;	    }      	  /* Integrate it in the nscache */	  retval = sos_fs_nscache_add_new_child_node(current_nsnode,						     & current_component,						     next_fsnode,						     & next_nsnode);	  sos_fs_nscache_unref_node(current_nsnode);	  if (SOS_OK != retval)	    return retval;	}      else	sos_fs_nscache_unref_node(current_nsnode);      /* Reaching a symlink ? */      if (sos_fs_nscache_get_fs_node(next_nsnode)->type	  == SOS_FS_NODE_SYMLINK)	{	  /* Expand the link only for non-terminal nodes, or for the	     terminal node only if follow_symlinks is TRUE */	  if ( (remaining.length != 0)	       || follow_symlinks )	    {	      struct sos_fs_nscache_node * symlink_target;	      retval = fs_resolve_symlink(root_nsnode, next_nsnode,					  & symlink_target,					  lookup_recursion_level);	      sos_fs_nscache_unref_node(next_nsnode);	      if (SOS_OK != retval)		return retval; /* Dangling symlink */	      next_nsnode = symlink_target;	    }	}            /* Make sure there was no slash after this component, unless	 this component is a directory */      if (slashes_after_first_component	  &&	  ( sos_fs_nscache_get_fs_node(next_nsnode)->type	    != SOS_FS_NODE_DIRECTORY) )	{	  sos_fs_nscache_unref_node(next_nsnode);	  return -SOS_ENOTDIR;	}      /* Ok, fine, we got it, update the path we still have to explore */      memcpy(result_remaining_path, & remaining, sizeof(remaining));      current_nsnode = next_nsnode;    }  sos_display_fatal_error("Should not get there");  return -SOS_EFATAL;}/** * It is assumed that parent does not already have a child with the * given name. We make sure that the "path" is a single entity (ie * not "a/b") * @return Error if fsnode is not on the same FS as parent_nsnode */static sos_ret_tfs_register_child_node(const struct sos_process * creator,		       struct sos_fs_nscache_node * parent_nsnode,		       const struct sos_fs_pathname * name,		       struct sos_fs_node * fsnode,		       sos_ui32_t flags,		       struct sos_fs_nscache_node ** result_nsnode){  sos_ret_t retval;  struct sos_fs_node * parent_fsnode;  struct sos_fs_pathname first_component, remaining;  sos_bool_t slashes_after_first_component = FALSE;  parent_fsnode = sos_fs_nscache_get_fs_node(parent_nsnode);  if (parent_fsnode->type != SOS_FS_NODE_DIRECTORY)    return -SOS_ENOTDIR;  if (name->length <= 0)    return -SOS_EINVAL;  slashes_after_first_component    = sos_fs_pathname_split_path(name, & first_component, & remaining);  if (fsnode->type != SOS_FS_NODE_DIRECTORY)    {      /* Make sure the given name is exactly a single path component	 (ie no '/') */      if (slashes_after_first_component)	return -SOS_EINVAL;    }  else    {      /* Make sure there aren't any other component behind the '/'s, if	 any */      if (remaining.length > 0)	return -SOS_EINVAL;    }  /* Make sure the parent directory is writeable */  if (! (parent_fsnode->access_rights & SOS_FS_WRITABLE) )    return -SOS_EACCES;  /* Make sure that the entries are located on the same FS */  if (fsnode->fs != parent_fsnode->fs)    return -SOS_EXDEV;  /* Make sure that the nsnode won't be destroyed */  sos_fs_nscache_ref_node(parent_nsnode);  /* Allocate the node in directory */  retval = parent_fsnode->ops_dir->link(parent_fsnode,					creator,					first_component.contents,					first_component.length,					fsnode);  if (SOS_OK != retval)    {      sos_fs_nscache_unref_node(parent_nsnode);      return retval;    }  /* Success: Consider the directory as dirty */  mark_dirty_fsnode(parent_fsnode, FALSE);  /* Allocate the node in nscache cache */  retval = sos_fs_nscache_add_new_child_node(parent_nsnode, & first_component,					     fsnode, result_nsnode);  sos_fs_nscache_unref_node(parent_nsnode);  return retval;}/** It is assumed that parent does not already have a child with the    given name. We make sure that the "path" is a single entity (ie    not "a/b"). Return a NEW reference to the newly-created NS node */static sos_ret_tfs_create_child_node(struct sos_fs_nscache_node * parent_nsnode,		     const struct sos_fs_pathname * name,		     sos_fs_node_type_t type,		     sos_ui32_t flags,		     const struct sos_process * creator,		     sos_ui32_t access_rights,		     struct sos_fs_nscache_node ** result_nsnode){  sos_ret_t retval;  struct sos_fs_node * fsnode, * parent_fsnode;  parent_fsnode = sos_fs_nscache_get_fs_node(parent_nsnode);  if (parent_fsnode->type != SOS_FS_NODE_DIRECTORY)    return -SOS_ENOTDIR;  /* Make sure that the nsnode won't be destroyed */  sos_fs_nscache_ref_node(parent_nsnode);  retval = fs_allocate_node(parent_fsnode->fs, type, flags, creator,			    access_rights, & fsnode);  if (SOS_OK != retval)    {      sos_fs_nscache_unref_node(parent_nsnode);      return retval;    }  retval = fs_register_child_node(creator,				  parent_nsnode, name, fsnode, flags,				  result_nsnode);  sos_fs_nscache_unref_node(parent_nsnode);  /* The function does not need it anymore */  sos_fs_unref_fsnode(fsnode);  return retval;}/** * It is assumed that parent does not already have a child with the * given name, and that the new child does not have a parent yet. We * make sure that the "path" is a single entity (ie not "a/b") @return * Error if fsnode is not on the same FS as parent_nsnode */static sos_ret_tfs_connect_existing_child_node(const struct sos_process * creator,			       struct sos_fs_nscache_node * parent_nsnode,			       const struct sos_fs_pathname * name,			       struct sos_fs_nscache_node * nsnode){  sos_ret_t retval;  struct sos_fs_node * parent_fsnode, * fsnode;  struct sos_fs_pathname first_component, remaining;  sos_bool_t slashes_after_first_component = FALSE;  fsnode = sos_fs_nscache_get_fs_node(nsnode);  parent_fsnode = sos_fs_nscache_get_fs_node(parent_nsnode);  if (parent_fsnode->type != SOS_FS_NODE_DIRECTORY)    return -SOS_ENOTDIR;  if (name->length <= 0)    return -SOS_EINVAL;  slashes_after_first_component    = sos_fs_pathname_split_path(name, & first_component, & remaining);  if (fsnode->type != SOS_FS_NODE_DIRECTORY)    {      /* Make sure the given name is exactly a single path component	 (ie no '/') */      if (slashes_after_first_component)	return -SOS_EINVAL;    }  else    {      /* Make sure there aren't any other component behind the '/'s, if	 any */      if (remaining.length > 0)	return -SOS_EINVAL;    }  /* Make sure the parent directory is writeable */  if (! (parent_fsnode->access_rights & SOS_FS_WRITABLE) )    return -SOS_EACCES;  /* Make sure that the entries are located on the same FS */  if (fsnode->fs != parent_fsnode->fs)    return -SOS_EXDEV;  /* Make sure that the nsnode won't be destroyed */  sos_fs_nscache_ref_node(parent_nsnode);  /* Allocate the node in directory */  retval = parent_fsnode->ops_dir->link(parent_fsnode,					creator,					first_component.contents,					first_component.length,					fsnode);  if (SOS_OK != retval)    {      sos_fs_nscache_unref_node(parent_nsnode);      return retval;    }  /* Success: Consider the directory as dirty */  mark_dirty_fsnode(parent_fsnode, FALSE);  /* Allocate the node in nscache cache */  retval = sos_fs_nscache_add_existing_child_node(parent_nsnode,						  & first_component,						  nsnode);  sos_fs_nscache_unref_node(parent_nsnode);  return retval;}/** Return a new reference to the new node inserted unless    result_nsnode is NULL */static sos_ret_tfs_create_node(const struct sos_fs_pathname * _path,	       const struct sos_process * creator,	       sos_ui32_t access_rights,	       sos_fs_node_type_t type,	       struct sos_fs_nscache_node ** result_nsnode){  sos_ret_t retval;  struct sos_fs_pathname path;  struct sos_fs_nscache_node *nsnode, *new_nsnode;  path.contents = _path->contents;  path.length   = _path->length;  if (path.length <= 0)    return -SOS_ENOENT;  if (path.contents[0] == '/')    nsnode = sos_process_get_root(creator)->direntry;  else    nsnode = sos_process_get_cwd(creator)->direntry;  retval = fs_lookup_node(& path,			  TRUE,			  sos_process_get_root(creator)->direntry,			  nsnode,			  & nsnode,			  & path,			  0);  if (SOS_OK != retval)    return retval;  if (path.length <= 0)    {      /* Found the exact match ! */      sos_fs_nscache_unref_node(nsnode);      return -SOS_EEXIST;    }  /* Create a new entry in the file system */  retval = fs_create_child_node(nsnode,				& path,				type,				/* flags */0,				creator, access_rights,				& new_nsnode);  sos_fs_nscache_unref_node(nsnode);  /* node not needed by this function ? */  if (NULL == result_nsnode)    sos_fs_nscache_unref_node(new_nsnode);  else    *result_nsnode = new_nsnode;  return retval;}static sos_ret_tfs_remove_node(const struct sos_process * actor,	       struct sos_fs_nscache_node * nsnode){  sos_ret_t retval;  struct sos_fs_nscache_node * parent_nsnode;  struct sos_fs_node * parent_fsnode;  struct sos_fs_pathname childname;  /* Refuse to do anything if this is the root of a mounted FS */  if (nsnode == sos_fs_nscache_get_fs_node(nsnode)->fs->root)    return -SOS_EBUSY;  retval = sos_fs_nscache_get_parent(nsnode, & parent_nsnode);  if (SOS_OK != retval)    return retval;  parent_fsnode = sos_fs_nscache_get_fs_node(parent_nsnode);  /* Make sure FS is writable ! */  if (parent_fsnode->fs->flags & SOS_FS_MOUNT_READONLY)    return -SOS_EPERM;  /* Make sure the parent directory is writeable */  if (! (parent_fsnode->access_rights & SOS_FS_WRITABLE) )    return -SOS_EACCES;  sos_fs_nscache_ref_node(parent_nsnode);  sos_fs_nscache_get_name(nsnode, & childname);  retval = parent_fsnode->ops_dir->unlink(parent_fsnode, actor,					  childname.contents,					  childname.length);  if (SOS_OK == retval)    sos_fs_nscache_disconnect_node(nsnode);  /* Unallocate the node */  if (SOS_OK == retval)    mark_dirty_fsnode(parent_fsnode, FALSE);  sos_fs_nscache_unref_node(parent_nsnode);  return retval;}/* ********************************************************** * Exported functions */sos_ret_t sos_fs_new_opened_file(const struct sos_process * owner,				 struct sos_fs_nscache_node * nsnode,				 sos_ui32_t open_flags,				 struct sos_fs_opened_file ** result_of){  sos_ret_t retval;  struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(nsnode);  retval = fsnode->new_opened_file(fsnode, owner, open_flags, result_of);  if (SOS_OK != retval)    {      sos_fs_nscache_unref_node(nsnode);      return retval;    }  (*result_of)->ref_cnt    = 1;  (*result_of)->generation = 1;  retval = sos_fs_nscache_register_opened_file(nsnode, *result_of);  if (SOS_OK != retval)    {      fsnode->close_opened_file(fsnode, *result_of);      return retval;    }  (*result_of)->open_flags = open_flags;  return SOS_OK;}sos_ret_tsos_fs_duplicate_opened_file(struct sos_fs_opened_file * src_of,			     const struct sos_process * dst_proc,			     struct sos_fs_opened_file ** result_of){  sos_ret_t retval = src_of->duplicate(src_of, dst_proc, result_of);  if (SOS_OK != retval)    return retval;  (*result_of)->ref_cnt    = 1;  (*result_of)->generation = 1;  retval = sos_fs_nscache_register_opened_file(src_of->direntry, *result_of);  if (SOS_OK != retval)    {      struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(src_of->direntry);      fsnode->close_opened_file(fsnode, *result_of);      return retval;    }  return retval;}sos_ret_t sos_fs_open(const struct sos_process *owner,		      const char *_path,		      sos_size_t _pathlen,		      sos_ui32_t open_flags,		      sos_ui32_t creat_access_rights,		      struct sos_fs_opened_file ** of){  sos_ret_t retval;  struct sos_fs_nscache_node *nsnode;  struct sos_fs_node * fsnode;  struct sos_fs_pathname path;  /* O_DIR | O_CREAT combination not supported */  if ((open_flags & SOS_FS_OPEN_DIRECTORY)      && (open_flags & SOS_FS_OPEN_CREAT))    return -SOS_EINVAL;  if (_pathlen <= 0)    return -SOS_ENOENT;  path.contents = _path;  path.length   = _pathlen;  if (path.contents[0] == '/')    nsnode = sos_process_get_root(owner)->direntry;  else    nsnode = sos_process_get_cwd(owner)->direntry;  retval = fs_lookup_node(& path,			  ! (open_flags & SOS_FS_OPEN_NOFOLLOW),			  sos_process_get_root(owner)->direntry,			  nsnode,			  & nsnode,			  & path,			  0);  if (SOS_OK != retval)    return retval;  if (path.length <= 0)    {      /* Found the exact match ! */      if (open_flags & SOS_FS_OPEN_EXCL)	{	  sos_fs_nscache_unref_node(nsnode);	  return -SOS_EEXIST;	}      fsnode = sos_fs_nscache_get_fs_node(nsnode);      if ((open_flags & SOS_FS_OPEN_DIRECTORY)	  && (fsnode->type != SOS_FS_NODE_DIRECTORY))	{	  sos_fs_nscache_unref_node(nsnode);	  return -SOS_ENOTDIR;	}    }  else    {      struct sos_fs_nscache_node * parent_nsnode = nsnode;      /* Did not find an exact match. Should create the node ! */      if (! (open_flags & SOS_FS_OPEN_CREAT))	{	  sos_fs_nscache_unref_node(parent_nsnode);	  return -SOS_ENOENT;	}      /* Create a new entry in the file system */      retval = fs_create_child_node(parent_nsnode,				    & path,				    SOS_FS_NODE_REGULAR_FILE,				    open_flags,				    owner,				    creat_access_rights,				    & nsnode);      sos_fs_nscache_unref_node(parent_nsnode);      if (SOS_OK != retval)	{	  return retval;	}      fsnode = sos_fs_nscache_get_fs_node(nsnode);    }  /* Recompute access rights */  open_flags &= ~(SOS_FS_OPEN_CREAT

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -