예제 #1
0
struct peropen *
netfs_make_peropen (struct node *np, int flags, struct peropen *context)
{
  struct peropen *po = malloc (sizeof (struct peropen));
  
  po->filepointer = 0;
  po->lock_status = LOCK_UN;
  po->refcnt = 0;
  po->openstat = flags;
  po->np = np;

  if (context)
    {
      po->root_parent = context->root_parent;
      if (po->root_parent != MACH_PORT_NULL)
	mach_port_mod_refs (mach_task_self (), po->root_parent,
			    MACH_PORT_RIGHT_SEND, 1);

      po->shadow_root = context->shadow_root;
      if (po->shadow_root)
	netfs_nref (po->shadow_root);

      po->shadow_root_parent = context->shadow_root_parent;
      if (po->shadow_root_parent != MACH_PORT_NULL)
	mach_port_mod_refs (mach_task_self (), po->shadow_root_parent,
			    MACH_PORT_RIGHT_SEND, 1);
    }

  netfs_nref (np);

  return po;
}
예제 #2
0
error_t procfs_lookup (struct node *np, const char *name, struct node **npp)
{
  error_t err = ENOENT;

  if (err && ! strcmp (name, "."))
    {
      netfs_nref(*npp = np);
      err = 0;
    }

  if (err && np->nn->parent && ! strcmp (name, ".."))
    {
      netfs_nref(*npp = np->nn->parent);
      err = 0;
    }

  if (err && np->nn->ops->lookup)
    {
      err = np->nn->ops->lookup (np->nn->hook, name, npp);
      if (! err)
        {
	  (*npp)->nn_stat.st_ino = procfs_make_ino (np, name);
	  netfs_nref ((*npp)->nn->parent = np);
	}
    }

  return err;
}
예제 #3
0
파일: netfs.c 프로젝트: ArneBab/tarfs
/* 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;
}
예제 #4
0
/* 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 = 0;

  debug ("dir: %p, file name: %s", dir, name);

  if (strcmp(name, ".") == 0)
    {
      netfs_nref(dir);
      *node = dir;
      return 0;
    }
  else if (strcmp(name, "..") == 0)
    {
      /*The supplied node is always root*/
      err = ENOENT;
      *node = NULL;

      /*unlock the directory*/
      pthread_mutex_unlock (&dir->lock);

      /*stop here*/
      return err;
    }

  *node = lookup (name);
  pthread_mutex_lock (&(*node)->lock);
  pthread_mutex_unlock (&dir->lock);
  return 0;
}
예제 #5
0
파일: netfs.c 프로젝트: ArneBab/tarfs
/* The user must define this function.  Lookup NAME in DIR (which is
   locked) for USER; set *NP to the found name upon return.  If the
   name was not found, then return ENOENT.  On any error, clear *NP.
   (*NP, if found, should be locked and a reference to it generated.
   This call should unlock DIR no matter what.)  */
error_t
netfs_attempt_lookup (struct iouser *user, struct node *dir, 
		      char *name, struct node **np)
{
  error_t err = 0;

  /* Lookups for "." and "..". */
  if (name[0] == '.' &&
      (name[1] == '\0' ||
       (name[1] == '.' && name[2] == '\0')) )
    /* Make sure that DIR is an actual directory. */
    if (S_ISDIR (dir->nn_stat.st_mode))
    {
      if (name[1] == '.')
        *np = dir->nn->dir;
      else
        *np = dir;
    }
    else
    {
      *np = NULL;
      err = ENOTDIR;
    }
  else
    /* Regular nodes. */
    err = backend.lookup_node (np, dir, name);

  /* Create a reference to the node (and lock it); unlock DIR. */
  if (!err && *np)
  {
    if (*np != dir)
      mutex_lock (&(*np)->lock);

    debug (("Node %s: %i references", name, (*np)->references));
    netfs_nref (*np);
  }

  mutex_unlock (&dir->lock);

  return err;
}
예제 #6
0
/* Add NODE to the recently-used-node cache, which adds a reference to
   prevent it from going away.  NODE should be locked.  */
void
ftpfs_cache_node (struct node *node)
{
  struct netnode *nn = node->nn;
  struct ftpfs *fs = nn->fs;

  mutex_lock (&fs->node_cache_lock);

  if (fs->params.node_cache_max > 0 || fs->node_cache_len > 0)
    {
      if (fs->node_cache_mru != node)
	{
	  if (nn->ncache_next || nn->ncache_prev)
	    /* Node is already in the cache.  */
	    node_unlink (node, fs);
	  else
	    /* Add a reference from the cache.  */
	    netfs_nref (node);

	  nn->ncache_next = fs->node_cache_mru;
	  nn->ncache_prev = 0;
	  if (fs->node_cache_mru)
	    fs->node_cache_mru->nn->ncache_prev = node;
	  if (! fs->node_cache_lru)
	    fs->node_cache_lru = node;
	  fs->node_cache_mru = node;
	  fs->node_cache_len++;
	}

      /* Forget the least used nodes.  */
      while (fs->node_cache_len > fs->params.node_cache_max)
	{
	  struct node *lru = fs->node_cache_lru;
	  node_unlink (lru, fs);
	  netfs_nrele (lru);
	}
    }

  mutex_unlock (&fs->node_cache_lock);
}
예제 #7
0
파일: cache.c 프로젝트: LastAvenger/hurd
/* Called by libnetfs when node NP has no more references.  (See
   <hurd/libnetfs.h> for details.  */
void
netfs_node_norefs (struct node *np)
{
  if (np->nn->dead_dir)
    {
      struct fnd *args;
      pthread_t thread;
      error_t err;

      args = malloc (sizeof (struct fnd));
      assert (args);

      netfs_nref (np);

      args->dir = np->nn->dead_dir;
      args->name = np->nn->dead_name;
      np->nn->dead_dir = 0;
      np->nn->dead_name = 0;
      netfs_nput (np);

      /* Do this in a separate thread so that we don't wait for it; it
	 acquires a lock on the dir, which we are not allowed to
	 do.  */
      err = pthread_create (&thread, NULL, forked_node_delete, args);
      if (!err)
	pthread_detach (thread);
      else
	{
	  errno = err;
	  perror ("pthread_create");
	}
    }
  else
    {
      if (np->nn->dtrans == SYMLINK)
        free (np->nn->transarg.name);
      free (np);
    }
}
예제 #8
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;
}
예제 #9
0
파일: cache.c 프로젝트: LastAvenger/hurd
/* Lookup the file handle HANDLE in the hash table.  If it is
   not present, initialize a new node structure and insert it into the
   hash table.  Whichever course, a new reference is generated and the
   node is returned in *NPP; the lock on the node, (*NPP)->LOCK, is
   held.  */
void
lookup_fhandle (struct fhandle *handle, struct node **npp)
{
  struct node *np;
  struct netnode *nn;

  pthread_mutex_lock (&nodehash_ihash_lock);
  np = hurd_ihash_find (&nodehash, (hurd_ihash_key_t) handle);
  if (np)
    {
      netfs_nref (np);
      pthread_mutex_unlock (&nodehash_ihash_lock);
      pthread_mutex_lock (&np->lock);
      *npp = np;
      return;
    }
  
  /* Could not find it */
  np = netfs_make_node_alloc (sizeof (struct netnode));
  assert (np);
  nn = netfs_node_netnode (np);

  nn->handle.size = handle->size;
  memcpy (nn->handle.data, handle->data, handle->size);
  nn->stat_updated = 0;
  nn->dtrans = NOT_POSSIBLE;
  nn->dead_dir = 0;
  nn->dead_name = 0;
  
  hurd_ihash_add (&nodehash, (hurd_ihash_key_t) &nn->handle, np);
  netfs_nref_light (np);
  pthread_mutex_unlock (&nodehash_ihash_lock);
  pthread_mutex_lock (&np->lock);
  
  *npp = np;
}
예제 #10
0
/* cvsfs_make_node
 *
 * create a struct node* for the specified netnode 'nn'.
 */
struct node *
cvsfs_make_node(struct netnode *nn)
{
    struct node *node;

    rwlock_writer_lock(&nn->lock);

    if(nn->node)
    {
        /* there already is a node structure, just return another reference
         * to this one, instead of wasting memory for yet another one
         */
        mutex_lock(&nn->node->lock);
        netfs_nref(nn->node);
        mutex_unlock(&nn->node->lock);

        rwlock_writer_unlock(&nn->lock);
        return nn->node;
    }

    if(! (node = netfs_make_node(nn)))
    {
        rwlock_writer_unlock(&nn->lock);
        return NULL;
    }

    /* put timestamp on file */
    fshelp_touch(&node->nn_stat,
                 TOUCH_ATIME | TOUCH_MTIME | TOUCH_CTIME, cvsfs_maptime);

    /* initialize stats of new node ... */
    node->nn_stat.st_fstype = FSTYPE_MISC;
    node->nn_stat.st_fsid = stat_template.fsid;
    node->nn_stat.st_ino = nn->fileno;
    node->nn_stat.st_mode = stat_template.mode;
    node->nn_stat.st_nlink = 1;
    node->nn_stat.st_uid = stat_template.uid;
    node->nn_stat.st_gid = stat_template.gid;
    node->nn_stat.st_size = 0;
    node->nn_stat.st_blksize = 4096; /* is there a better default?? */
    node->nn_stat.st_blocks = 0;
    node->nn_stat.st_author = stat_template.author;

    if(! nn->revision)
    {
        /* we're creating a node for a directory, mark as such! */
        node->nn_stat.st_mode |= S_IFDIR;

        /* since we got a directory we need to supply "executable"
         * permissions, so our user is enabled to make use of this dir
         */
        if(node->nn_stat.st_mode & S_IRUSR)
            node->nn_stat.st_mode |= S_IXUSR;

        if(node->nn_stat.st_mode & S_IRGRP)
            node->nn_stat.st_mode |= S_IXGRP;

        if(node->nn_stat.st_mode & S_IROTH)
            node->nn_stat.st_mode |= S_IXOTH;
    }
    else
    {
        if(nn->revision->contents
                && ! config.nostats)
        {
            node->nn_stat.st_mode = nn->revision->perm;
            node->nn_stat.st_size = nn->revision->length;
            node->nn_stat.st_blocks = (node->nn_stat.st_size >> 9) + 1;

            node->nn_stat.st_atime =
                node->nn_stat.st_mtime =
                    node->nn_stat.st_ctime = nn->revision->time;

            node->nn_stat.st_atime_usec =
                node->nn_stat.st_mtime_usec =
                    node->nn_stat.st_ctime_usec = 0;
        }

        /* well, we're creating a new node for a file ... */
        node->nn_stat.st_mode |= S_IFREG;

        /* for now simply drop all execute permissions, this needs to be fixed,
         * since CVS support executables, e.g. shell scripts, that we need to
         * support .... FIXME
         */
        node->nn_stat.st_mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH);
    }