Exemple #1
0
/* The user must define this function.  Attempt to create a file named
   NAME in DIR (which is locked) for USER with MODE.  Set *NP to the
   new node upon return.  On any error, clear *NP.  *NP should be
   locked on success; no matter what, unlock DIR before returning.  */
error_t
netfs_attempt_create_file (struct iouser *user, struct node *dir,
			   char *name, mode_t mode, struct node **np)
{
  error_t err = fshelp_isowner (&dir->nn_stat, user);

  if (!backend.create_node)
  {
    err = EROFS;
    *np = NULL;
  }
  else
  {
    /* Note: create_node () must handle nameless node creation
       (see netfs_attempt_mkfile ()).  */
    err = backend.create_node (np, dir, name, mode);

    /* Lock the new node and add a reference to it on success.  */
    if (!err && *np)
    {
      debug (("Node %s: %i references", name, (*np)->references));
      mutex_lock (&(*np)->lock);
      netfs_nref (*np);
    }
  }

  mutex_unlock (&dir->lock);

  return err;
}
Exemple #2
0
/* The user must define this function.  This should sync the entire
   remote filesystem.  If WAIT is set, return only after the sync is
   completely finished.  */
error_t
netfs_attempt_syncfs (struct iouser *cred, int wait)
{
  error_t err = 0;

  if (backend.sync_fs)
  {
    if (cred)
    {
      err = fshelp_isowner (&netfs_root_node->nn_stat, cred);
      if (err)
        return err;
      err = backend.sync_fs (wait);
    }
    else
      /* From libnetfs source code, CRED is set to zero in the fsys-goaway
	 stub, so we call go_away () here.  */
      if (backend.go_away)
	err = backend.go_away (); /* This should call sync_fs () */
      else
        err = backend.sync_fs (wait);
  }
  else
    err = EOPNOTSUPP;

  return err;
}
Exemple #3
0
/* The user must define this function.  Delete NAME in DIR (which is
   locked) for USER.  */
error_t
netfs_attempt_unlink (struct iouser *user, struct node *dir,
		      char *name)
{
  error_t err;

  if (backend.unlink_node)
  {
    struct node *node;

    err = backend.lookup_node (&node, dir, name);
    //usleep (500); /* FIXME!!! The incredible race condition! */

    if (!err)
    {
      mutex_lock (&node->lock);

      debug (("Node %s: %i references", name, node->references));
      err = fshelp_isowner (&node->nn_stat, user);

      if (!err)
	err = backend.unlink_node (node);

      mutex_unlock (&node->lock);
    }
  }
  else
    err = EROFS;

  return err;
}
Exemple #4
0
/* The user must define this function.  This should attempt a chmod
   call for the user specified by CRED on locked node NP, to change
   the owner to UID and the group to GID.  */
error_t
netfs_attempt_chown (struct iouser *cred, struct node *np,
			     uid_t uid, uid_t gid)
{
  error_t err = 0;

  if (backend.change_stat)
  {
    io_statbuf_t st;

    err = fshelp_isowner (&np->nn_stat, cred);

    if (! err)
    {
      st = np->nn_stat;
      st.st_uid = uid;
      st.st_gid = gid;
      err = backend.change_stat (np, &st);
    }
  }
  else
    err = EROFS;

  return err;
}
Exemple #5
0
/* The user must define this function.  This should attempt a utimes
   call for the user specified by CRED on locked node NP, to change
   the atime to ATIME and the mtime to MTIME.  If ATIME or MTIME is
   null, then set to the current time.  */
error_t
netfs_attempt_utimes (struct iouser *cred, struct node *np,
			      struct timespec *atime, struct timespec *mtime)
{
  error_t err = 0;

  if (backend.change_stat)
  {
    int flags = TOUCH_CTIME;
    io_statbuf_t st = np->nn_stat;

    err = fshelp_isowner (&np->nn_stat, cred);

    if (! err)
      {
	if (atime)
	    st.st_atim = *atime;
	else
	  flags |= TOUCH_ATIME;

	if (mtime)
	    st.st_mtim = *mtime;
	else
	  flags |= TOUCH_MTIME;

	err = backend.change_stat (np, &st);
      }
  }
  else
    err = EROFS;

  return err;
}
Exemple #6
0
/* This should attempt a utimes call for the user specified by CRED on node
   NODE, to change the atime to ATIME and the mtime to MTIME. */
error_t
netfs_attempt_utimes (struct iouser *cred, struct node *node,
		      struct timespec *atime, struct timespec *mtime)
{
  error_t err = procfs_refresh_node (node);
  int flags = TOUCH_CTIME;

  if (! err)
    err = fshelp_isowner (&node->nn_stat, cred);

  if (! err)
    {
      if (atime)
	node->nn_stat.st_atim = *atime;
      else
	flags |= TOUCH_ATIME;

      if (mtime)
	node->nn_stat.st_mtim = *mtime;
      else
	flags |= TOUCH_MTIME;

      fshelp_touch (&node->nn_stat, flags, procfs_maptime);
    }

  return err;
}
/* Implement file_get_translator_cntl as described in <hurd/fs.defs>. */
kern_return_t
diskfs_S_file_get_translator_cntl (struct protid *cred,
				   mach_port_t *ctl,
				   mach_msg_type_name_t *ctltype)
{
  struct node *np;
  error_t error;
  
  if (!cred)
    return EOPNOTSUPP;
  
  np = cred->po->np;

  mutex_lock (&np->lock);

  error = fshelp_isowner (&np->dn_stat, cred->user);
  if (!error)
    error = fshelp_fetch_control (&np->transbox, ctl);
  if (!error && *ctl == MACH_PORT_NULL)
    error = ENXIO;
  if (!error)
    *ctltype = MACH_MSG_TYPE_MOVE_SEND;

  mutex_unlock (&np->lock);

  return error;
}
Exemple #8
0
/* The user must define this function.  Attempt to create a new
   directory named NAME in DIR (which is locked) for USER with mode
   MODE. */
error_t
netfs_attempt_mkdir (struct iouser *user, struct node *dir,
		     char *name, mode_t mode)
{
  error_t err = fshelp_isowner (&dir->nn_stat, user);
  struct node *newdir;

  if (!backend.create_node)
    err = EROFS;
  else
    err = backend.create_node (&newdir, dir, name, mode);

  return err;
}
Exemple #9
0
/* The user must define this function.  Create a link in DIR with name
   NAME to FILE for USER. Note that neither DIR nor FILE are
   locked. If EXCL is set, do not delete the target.  Return EEXIST if
   NAME is already found in DIR.  */
error_t
netfs_attempt_link (struct iouser *user, struct node *dir,
		    struct node *file, char *name, int excl)
{
  error_t err;

  if (backend.link_node)
  {
    err = fshelp_isowner (&dir->nn_stat, user);
    if (!err)
      err = backend.link_node (dir, file, name, excl);
  }
  else
    err = EROFS;

  return err;
}
/* This should attempt a chmod call for the user specified by CRED on node
   NODE, to change the mode to MODE.  Unlike the normal Unix and Hurd meaning
   of chmod, this function is also used to attempt to change files into other
   types.  If such a transition is attempted which is impossible, then return
   EOPNOTSUPP.  */
error_t netfs_attempt_chmod (struct iouser *cred, struct node *node,
			     mode_t mode)
{
  error_t err = 0;
  debug("");
  if (node->nn->ln == NULL)
    return EOPNOTSUPP;

  mode &= ~S_ITRANS;
  err = fshelp_isowner (&node->nn->ln->st, cred);
  if (err)
    return err;
  mode |= node->nn->ln->st.st_mode & S_IFMT;
  node->nn->ln->st.st_mode = mode;
  fshelp_touch (&node->nn_stat, TOUCH_CTIME, multiplexer_maptime);
  return err;
}
Exemple #11
0
/* The user must define this function.  This should attempt a chmod
   call for the user specified by CRED on locked node NODE, to change
   the mode to MODE.  Unlike the normal Unix and Hurd meaning of
   chmod, this function is also used to attempt to change files into
   other types.  If such a transition is attempted which is
   impossible, then return EOPNOTSUPP.  */
error_t
netfs_attempt_chmod (struct iouser *cred, struct node *np,
		     mode_t mode)
{
  error_t err = 0;

  if (backend.change_stat)
  {
    io_statbuf_t st;

    err = fshelp_isowner (&np->nn_stat, cred);

    if (! err)
    {
      st = np->nn_stat;

      if (mode & S_IFMT)
      {
        /* User wants to change file type, check whether this is possible */
        if (S_ISDIR (st.st_mode) || S_ISDIR (mode))
        {
          /* Any->Dir and Dir->Any are forbidden transitions */
          if ((st.st_mode & S_IFMT) != (mode & S_IFMT))
	    err = EOPNOTSUPP;
	}
        else
	  /* Let him do it */
	  st.st_mode = 0;
      }
      else
	/* Only clear the permission bits */
	st.st_mode &= ~S_ISPARE;

      if (!err)
      {
	st.st_mode |= mode;
	err = backend.change_stat (np, &st);
      }
    }
  }
  else
    err = EROFS;

  return err;
}
Exemple #12
0
/* The user must define this function.  Attempt to turn NODE (user
   CRED) into a device.  TYPE is either S_IFBLK or S_IFCHR.  NP is
   locked.  */
error_t
netfs_attempt_mkdev (struct iouser *cred, struct node *np,
		     mode_t type, dev_t indexes)
{
  error_t err;

  if (backend.mkdev_node)
  {
    err = fshelp_isowner (&np->nn_stat, cred); /* FIXME: See above */

    if (! err)
      err = backend.mkdev_node (np, type, indexes);
  }
  else
    err = EOPNOTSUPP;

  return err;
}
Exemple #13
0
/* The user must define this function.  Attempt to turn locked node NP
   (user CRED) into a symlink with target NAME.  */
error_t
netfs_attempt_mksymlink (struct iouser *cred, struct node *np,
			 char *name)
{
  error_t err;

  if (backend.symlink_node)
  {
    err = fshelp_isowner (&np->nn_stat, cred);
    /* FIXME: Call fshelp_access () ?! */

    if (! err)
      err = backend.symlink_node (np, name);
  }
  else
    err = EOPNOTSUPP;

  return err;
}
/* Implement io_revoke as described in <hurd/io.defs>. */
kern_return_t
diskfs_S_io_revoke (struct protid *cred)
{
  error_t err;
  struct node *np;

  error_t
    iterator_function (void *port)
    {
      struct protid *user = port;

      if ((user != cred)
	  && (user->po->np == np))
	ports_destroy_right (user);
      return 0;
    }

  if (!cred)
    return EOPNOTSUPP;

  np = cred->po->np;

  mutex_lock (&np->lock);

  err = fshelp_isowner (&np->dn_stat, cred->user);

  mutex_unlock (&np->lock);

  if (err)
    return err;

  ports_inhibit_bucket_rpcs (diskfs_port_bucket);
  ports_class_iterate (diskfs_protid_class, iterator_function);
  ports_resume_bucket_rpcs (diskfs_port_bucket);

  return 0;
}