示例#1
0
文件: netfs.c 项目: GNUHurdTR/hurd
/* The user must define this function.  Return the valid access
   types (bitwise OR of O_READ, O_WRITE, and O_EXEC) in *TYPES for
   locked file NP and user CRED.  */
error_t netfs_report_access (struct iouser *cred, struct node *np,
			     int *types)
{
  *types = 0;
  if (fshelp_access (&np->nn_stat, S_IREAD, cred) == 0)
    *types |= O_READ;
  if (fshelp_access (&np->nn_stat, S_IWRITE, cred) == 0)
    *types |= O_WRITE;
  if (fshelp_access (&np->nn_stat, S_IEXEC, cred) == 0)
    *types |= O_EXEC;
  return 0;
}
示例#2
0
文件: netfs.c 项目: GNUHurdTR/hurd
/* The user must define this function. Locked node NP is being opened
   by USER, with FLAGS.  NEWNODE is nonzero if we just created this
   node.  Return an error if we should not permit the open to complete
   because of a permission restriction.  */
error_t netfs_check_open_permissions (struct iouser *user, struct node *np,
				      int flags, int newnode)
{
  error_t err = 0;
  if (!err && (flags & O_READ))
    err = fshelp_access (&np->nn_stat, S_IREAD, user);
  if (!err && (flags & O_WRITE))
    err = fshelp_access (&np->nn_stat, S_IWRITE, user);
  if (!err && (flags & O_EXEC))
    err = fshelp_access (&np->nn_stat, S_IEXEC, user);
  return err;
}
示例#3
0
/* Return the valid access types (bitwise OR of O_READ, O_WRITE, and O_EXEC)
   in *TYPES for file NODE and user CRED.  */
error_t
netfs_report_access (struct iouser *cred, struct node *node, int *types)
{
  error_t err = procfs_refresh_node (node);

  if (! err)
    {
      *types = 0;
      if (fshelp_access (&node->nn_stat, S_IREAD, cred) == 0)
	*types |= O_READ;
      if (fshelp_access (&node->nn_stat, S_IWRITE, cred) == 0)
	*types |= O_WRITE;
      if (fshelp_access (&node->nn_stat, S_IEXEC, cred) == 0)
	*types |= O_EXEC;
    }

  return err;
}
/* Node NODE is being opened by USER, with FLAGS.  NEWNODE is nonzero if we
   just created this node.  Return an error if we should not permit the open
   to complete because of a permission restriction. */
error_t
netfs_check_open_permissions (struct iouser *user, struct node *node,
			      int flags, int newnode)
{
  error_t err = 0;

  /*Cheks user's permissions*/
  if(flags & O_READ)
    err = fshelp_access(&node->nn_stat, S_IREAD, user);
  if(!err && (flags & O_WRITE))
    err = fshelp_access(&node->nn_stat, S_IWRITE, user);
  if(!err && (flags & O_EXEC))
    err = fshelp_access(&node->nn_stat, S_IEXEC, user);

  debug("the mode of node: %o, return result: %d",
	(node->nn_stat.st_mode & ~S_IFMT), err);
  /*Return the result of the check*/
  return err;
}
示例#5
0
文件: netfs.c 项目: ArneBab/tarfs
/* The user must define this function.  Return the valid access
   types (bitwise OR of O_READ, O_WRITE, and O_EXEC) in *TYPES for
   locked file NODE and user CRED.  */
error_t
netfs_report_access (struct iouser *cred, struct node *node,
			     int *types)
{
  error_t err = OWNERSHIP (node, cred);

  /* FIXME: For a ro-fs, this should only set TYPES to O_READ.  */
  if (! err)
    {
      *types = 0;
      if (fshelp_access (&node->nn_stat, S_IREAD, cred) == 0)
	*types |= O_READ;
      if (fshelp_access (&node->nn_stat, S_IWRITE, cred) == 0)
	*types |= O_WRITE;
      if (fshelp_access (&node->nn_stat, S_IEXEC, cred) == 0)
	*types |= O_EXEC;
    }

  return err;
}
示例#6
0
kern_return_t
diskfs_S_file_check_access (struct protid *cred,
			    int *type)
{
  struct node *np;
  
  if (!cred)
    return EOPNOTSUPP;

  np = cred->po->np;
  pthread_mutex_lock (&np->lock);
  *type = 0;
  if (fshelp_access (&np->dn_stat, S_IREAD, cred->user) == 0)
    *type |= O_READ;
  if (fshelp_access (&np->dn_stat, S_IWRITE, cred->user) == 0)
    *type |= O_WRITE;
  if (fshelp_access (&np->dn_stat, S_IEXEC, cred->user) == 0)
    *type |= O_EXEC;
  
  pthread_mutex_unlock (&np->lock);
  
  return 0;
}
示例#7
0
文件: mux.c 项目: GNUHurdTR/hurd
/* Lookup NAME in DIR for USER; set *NODE to the found name upon return.  If
   the name was not found, then return ENOENT.  On any error, clear *NODE.
   (*NODE, if found, should be locked, this call should unlock DIR no matter
   what.) */
error_t
netfs_attempt_lookup (struct iouser *user, struct node *dir,
		      char *name, struct node **node)
{
  error_t err;

  if (dir->nn->name)
    err = ENOTDIR;
  else
    err = fshelp_access (&dir->nn_stat, S_IEXEC, user);

  if (! err)
    {
      if (strcmp (name, ".") == 0)
	/* Current directory -- just add an additional reference to DIR and
	   return it.  */
	{
	  netfs_nref (dir);
	  *node = dir;
	  err = 0;
	}
      else if (strcmp (name, "..") == 0)
	err = EAGAIN;
      else
	err = lookup_host (dir->nn->mux, name, node);

      fshelp_touch (&dir->nn_stat, TOUCH_ATIME, hostmux_maptime);
    }

  pthread_mutex_unlock (&dir->lock);
  if (err)
    *node = 0;
  else
    pthread_mutex_lock (&(*node)->lock);

  return err;
}
/* Return in FILE & FILE_TYPE the file in FSYS corresponding to the NFS file
   handle HANDLE & HANDLE_LEN.  */
error_t
diskfs_S_fsys_getfile (mach_port_t fsys,
		       mach_port_t reply, mach_msg_type_name_t reply_type,
		       uid_t *uids, mach_msg_type_number_t nuids,
		       gid_t *gids, mach_msg_type_number_t ngids,
		       char *handle, mach_msg_type_number_t handle_len,
		       mach_port_t *file, mach_msg_type_name_t *file_type)
{
  int flags;
  error_t err;
  struct node *node;
  const union diskfs_fhandle *f;
  struct protid *new_cred;
  struct peropen *new_po;
  struct iouser *user;
  struct port_info *pt =
    ports_lookup_port (diskfs_port_bucket, fsys, diskfs_control_class);

  if (!pt)
    return EOPNOTSUPP;

  if (handle_len != sizeof *f)
    {
      ports_port_deref (pt);
      return EINVAL;
    }

  f = (const union diskfs_fhandle *) handle;

  err = diskfs_cached_lookup (f->data.cache_id, &node);
  if (err)
    {
      ports_port_deref (pt);
      return err;
    }

  if (node->dn_stat.st_gen != f->data.gen)
    {
      diskfs_nput (node);
      ports_port_deref (pt);
      return ESTALE;
    }

  err = iohelp_create_complex_iouser (&user, uids, nuids, gids, ngids);
  if (err)
    {
      diskfs_nput (node);
      ports_port_deref (pt);
      return err;
    }

  flags = 0;
  if (! fshelp_access (&node->dn_stat, S_IREAD, user))
    flags |= O_READ;
  if (! fshelp_access (&node->dn_stat, S_IEXEC, user))
    flags |= O_EXEC;
  if (! fshelp_access (&node->dn_stat, S_IWRITE, user)
      && ! S_ISDIR (node->dn_stat.st_mode)
      && ! diskfs_check_readonly ())
    flags |= O_WRITE;

  err = diskfs_make_peropen (node, flags, 0, &new_po);
  if (! err)
    {
      err = diskfs_create_protid (new_po, user, &new_cred);
      if (err)
	diskfs_release_peropen (new_po);
    }

  iohelp_free_iouser (user);

  diskfs_nput (node);
  ports_port_deref (pt);

  if (! err)
    {
      *file = ports_get_right (new_cred);
      *file_type = MACH_MSG_TYPE_MAKE_SEND;
    }

  return err;
}
示例#9
0
文件: lookup.c 项目: GNUHurdTR/hurd
/* Lookup in directory DP (which is locked) the name NAME.  TYPE will
   either be LOOKUP, CREATE, RENAME, or REMOVE.  CRED identifies the
   user making the call.

   NAME will have leading and trailing slashes stripped.  It is an
   error if there are internal slashes.  NAME will be modified in
   place if there are slashes in it; it is therefore an error to
   specify a constant NAME which contains slashes.

   If the name is found, return zero, and (if NP is nonzero) set *NP
   to point to the node for it, locked.  If the name is not found,
   return ENOENT, and (if NP is nonzero) set *NP to zero.  If NP is
   zero, then the node found must not be locked, even transitorily.
   Lookups for REMOVE and RENAME (which must often check permissions
   on the node being found) will always set NP.

   If DS is nonzero then:
     For LOOKUP: set *DS to be ignored by diskfs_drop_dirstat.
     For CREATE: on success, set *DS to be ignored by diskfs_drop_dirstat.
                 on failure, set *DS for a future call to diskfs_direnter.
     For RENAME: on success, set *DS for a future call to diskfs_dirrewrite.
                 on failure, set *DS for a future call to diskfs_direnter.
     For REMOVE: on success, set *DS for a future call to diskfs_dirremove.
                 on failure, set *DS to be ignored by diskfs_drop_dirstat.
   The caller of this function guarantees that if DS is nonzero, then
   either the appropriate call listed above or diskfs_drop_dirstat will
   be called with DS before the directory DP is unlocked, and guarantees
   that no lookup calls will be made on this directory between this
   lookup and the use (or descruction) of *DS.

   If you use the library's versions of diskfs_rename_dir,
   diskfs_clear_directory, and diskfs_init_dir, then lookups for `..'
   might have the flag SPEC_DOTDOT or'd in.  This has the following special
   meaning:
   For LOOKUP: DP should be unlocked and its reference dropped before
               returning.
   For RENAME and REMOVE: The node being found (*NP) is already held
               locked, so don't lock it or add a reference to it.
   (SPEC_DOTDOT will not be given with CREATE.)

   Return ENOTDIR if DP is not a directory.
   Return EACCES if CRED isn't allowed to search DP.
   Return EACCES if completing the operation will require writing
   the directory and diskfs_checkdirmod won't allow the modification.
   Return ENOENT if NAME isn't in the directory.
   Return EAGAIN if NAME refers to the `..' of this filesystem's root.
   Return EIO if appropriate.

   This function is a wrapper for diskfs_lookup_hard.  */
error_t
diskfs_lookup (struct node *dp, const char *name, enum lookup_type type,
	       struct node **np, struct dirstat *ds, struct protid *cred)
{
  error_t err;
  struct node *cached;

  if (type == REMOVE || type == RENAME)
    assert (np);

  if (!S_ISDIR (dp->dn_stat.st_mode))
    {
      if (ds)
	diskfs_null_dirstat (ds);
      return ENOTDIR;
    }

  /* Strip leading and trailing slashes. */
  while (*name == '/')
    name++;

  if (name[0] == '\0')
    {
      if (ds)
	diskfs_null_dirstat (ds);
      return EINVAL;
    }
  else
    {
      char *p = strchr (name, '/');
      if (p != 0)
	{
	  *p = '\0';
	  do
	    ++p;
	  while (*p == '/');
	  if (*p != '\0')
	    {
	      if (ds)
		diskfs_null_dirstat (ds);
	      return EINVAL;
	    }
	}
    }


  err = fshelp_access (&dp->dn_stat, S_IEXEC, cred->user);
  if (err)
    {
      if (ds)
	diskfs_null_dirstat (ds);
      return err;
    }

  if (dp == cred->po->shadow_root
      && name[0] == '.' && name[1] == '.' && name[2] == '\0')
    /* Ran into the root.  */
    {
      if (ds)
	diskfs_null_dirstat (ds);
      return EAGAIN;
    }

  if (type == LOOKUP)
    /* Check the cache first */
    cached = diskfs_check_lookup_cache (dp, name);
  else
    cached = 0;

  if (cached == (struct node *)-1)
    /* Negative lookup cached.  */
    {
      if (np)
	*np = 0;
      return ENOENT;
    }
  else if (cached)
    {
      if (np)
	*np = cached;	/* Return what we found.  */
      else
	/* Ick, the user doesn't want the result, we have to drop our
	   reference.  */
	if (cached == dp)
	  diskfs_nrele (cached);
	else
	  diskfs_nput (cached);

      if (ds)
	diskfs_null_dirstat (ds);
    }
  else
    {
      err = diskfs_lookup_hard (dp, name, type, np, ds, cred);
      if (err && err != ENOENT)
	return err;

      if (type == RENAME
	  || (type == CREATE && err == ENOENT)
	  || (type == REMOVE && err != ENOENT))
	{
	  error_t err2;

	  if (diskfs_name_max > 0 && strlen (name) > diskfs_name_max)
	    err2 = ENAMETOOLONG;
	  else
	    err2 = fshelp_checkdirmod (&dp->dn_stat,
				       (err || !np) ? 0 : &(*np)->dn_stat,
				       cred->user);
	  if (err2)
	    {
	      if (np && !err)
		{
		  if (*np == dp)
		    diskfs_nrele (*np);
		  else
		    diskfs_nput (*np);
		  *np = 0;
		}
	      return err2;
	    }
	}

      if ((type == LOOKUP || type == CREATE) && !err && np)
	diskfs_enter_lookup_cache (dp, *np, name);
      else if (type == LOOKUP && err == ENOENT)
	diskfs_enter_lookup_cache (dp, 0, name);
    }

  return err;
}