示例#1
0
int register_driver(FAR const char *path, FAR const struct file_operations *fops,
                    mode_t mode, FAR void *priv)
{
  FAR struct inode *node;
  int ret;

  /* Insert a dummy node -- we need to hold the inode semaphore because we
   * will have a momentarily bad structure.
   */

  inode_semtake();
  ret = inode_reserve(path, &node);
  if (ret >= 0)
    {
      /* We have it, now populate it with driver specific information. */

      INODE_SET_DRIVER(node);

      node->u.i_ops   = fops;
#ifdef CONFIG_FILE_MODE
      node->i_mode    = mode;
#endif
      node->i_private = priv;
      ret             = OK;
    }

  inode_semgive();
  return ret;
}
int register_blockdriver(const char *path,
                         const struct block_operations *bops,
                         mode_t mode, void *priv)
{
    struct inode *node;
    int ret = -ENOMEM;

    /* Insert an inode for the device driver -- we need to hold the inode semaphore
     * to prevent access to the tree while we this.  This is because we will have a
     * momentarily bad true until we populate the inode with valid data.
     */

    inode_semtake();
    node = inode_reserve(path);
    if (node != NULL)
    {
        /* We have it, now populate it with block driver specific
         * information.
         */

        INODE_SET_BLOCK(node);

        node->u.i_bops  = bops;
#ifdef CONFIG_FILE_MODE
        node->i_mode    = mode;
#endif
        node->i_private = priv;
        ret             = OK;
    }

    inode_semgive();
    return ret;
}
int register_blockdriver(FAR const char *path,
                         FAR const struct block_operations *bops,
                         mode_t mode, FAR void *priv)
{
  FAR struct inode *node;
  int ret;

  /* Insert an inode for the device driver -- we need to hold the inode
   * semaphore to prevent access to the tree while we this.  This is because
   * we will have a momentarily bad true until we populate the inode with
   * valid data.
   */

  inode_semtake();
  ret = inode_reserve(path, &node);
  if (ret >= 0)
    {
      /* We have it, now populate it with block driver specific information.
       * NOTE that the initial reference count on the new inode is zero.
       */

      INODE_SET_BLOCK(node);

      node->u.i_bops  = bops;
#ifdef CONFIG_FILE_MODE
      node->i_mode    = mode;
#endif
      node->i_private = priv;
      ret             = OK;
    }

  inode_semgive();
  return ret;
}
示例#4
0
mqd_t mq_open(FAR const char *mq_name, int oflags, ...)
{
  FAR struct inode *inode;
  FAR const char *relpath = NULL;
  FAR struct mqueue_inode_s *msgq;
  char fullpath[MAX_MQUEUE_PATH];
  va_list ap;
  struct mq_attr *attr;
  mqd_t mqdes;
  mode_t mode;
  int errcode;
  int ret;

  /* Make sure that a non-NULL name is supplied */

  if (!mq_name)
    {
      errcode = EINVAL;
      goto errout;
    }

  /* Get the full path to the message queue */

  snprintf(fullpath, MAX_MQUEUE_PATH, CONFIG_FS_MQUEUE_MPATH "/%s", mq_name);

  /* Make sure that the check for the existence of the message queue
   * and the creation of the message queue are atomic with respect to
   * other processes executing mq_open().  A simple sched_lock() should
   * be sufficient.
   */

  sched_lock();

  /* Get the inode for this mqueue.  This should succeed if the message
   * queue has already been created.
   */

  inode = inode_find(fullpath, &relpath);
  if (inode)
    {
      /* It exists.  Verify that the inode is a message queue */

      if (!INODE_IS_MQUEUE(inode))
        {
          errcode = ENXIO;
          goto errout_with_inode;
        }

      /* It exists and is a message queue.  Check if the caller wanted to
       * create a new mqueue with this name.
       */

      if ((oflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
        {
          errcode = EEXIST;
          goto errout_with_inode;
        }

      /* Create a message queue descriptor for the current thread */

      msgq  = inode->u.i_mqueue;
      mqdes = mq_descreate(NULL, msgq, oflags);
      if (!mqdes)
        {
          errcode = ENOMEM;
          goto errout_with_inode;
        }
    }
  else
    {
      /* The mqueue does not exists.  Were we asked to create it? */

      if ((oflags & O_CREAT) == 0)
        {
          /* The mqueue does not exist and O_CREAT is not set */

          errcode = ENOENT;
          goto errout_with_lock;
        }

     /* Create the mqueue.  First we have to extract the additional
      * parameters from the variable argument list.
      */

      va_start(ap, oflags);
      mode = va_arg(ap, mode_t);
      attr = va_arg(ap, FAR struct mq_attr*);
      va_end(ap);

      /* Create an inode in the pseudo-filesystem at this path */

      inode_semtake();
      ret = inode_reserve(fullpath, &inode);
      inode_semgive();

      if (ret < 0)
        {
          errcode = -ret;
          goto errout_with_lock;
        }

      /* Allocate memory for the new message queue. */

      msgq = (FAR struct mqueue_inode_s*)mq_msgqalloc(mode, attr);
      if (!msgq)
        {
          errcode = ENOSPC;
          goto errout_with_inode;
        }

      /* Create a message queue descriptor for the TCB */

       mqdes = mq_descreate(NULL, msgq, oflags);
       if (!mqdes)
         {
           errcode = ENOMEM;
           goto errout_with_msgq;
         }

      /* Bind the message queue and the inode structure */

      INODE_SET_MQUEUE(inode);
      inode->u.i_mqueue = msgq;
      msgq->inode       = inode;

    }

  sched_unlock();
  return mqdes;

errout_with_msgq:
  mq_msgqfree(msgq);
  inode->u.i_mqueue = NULL;
errout_with_inode:
  inode_release(inode);
errout_with_lock:
  sched_unlock();
errout:
  set_errno(errcode);
  return (mqd_t)ERROR;
}
示例#5
0
int mkdir(const char *pathname, mode_t mode)
{
  FAR struct inode *inode;
  const char       *relpath = NULL;
  int               errcode;
  int               ret;

  /* Find the inode that includes this path */

  inode = inode_find(pathname, &relpath);
  if (inode)
    {
      /* An inode was found that includes this path and possibly refers to a
       * mountpoint.
       */

#ifndef CONFIG_DISABLE_MOUNTPOINT
      /* Check if the inode is a valid mountpoint. */

      if (!INODE_IS_MOUNTPT(inode) || !inode->u.i_mops)
        {
          /* The inode is not a mountpoint */

          errcode = ENXIO;
          goto errout_with_inode;
        }

      /* Perform the mkdir operation using the relative path
       * at the mountpoint.
       */

      if (inode->u.i_mops->mkdir)
        {
          ret = inode->u.i_mops->mkdir(inode, relpath, mode);
          if (ret < 0)
            {
              errcode = -ret;
              goto errout_with_inode;
            }
        }
      else
        {
          errcode = ENOSYS;
          goto errout_with_inode;
        }

      /* Release our reference on the inode */

      inode_release(inode);
#else
      /* But mountpoints are not supported in this configuration */

      errcode = EEXIST;
      goto errout_with_inode;
#endif
    }

#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
  /* No inode exists that contains this path.  Create a new inode in the
   * pseudo-filesystem at this location.
   */

  else
    {
      /* Create an inode in the pseudo-filesystem at this path */

      inode_semtake();
      ret = inode_reserve(pathname, &inode);
      inode_semgive();

      if (ret < 0)
        {
          errcode = -ret;
          goto errout;
        }
    }
#else
  else
    {
示例#6
0
int mount(const char *source, const char *target,
          const char *filesystemtype, unsigned long mountflags,
          const void *data)
{
#if defined(BDFS_SUPPORT) || defined(NONBDFS_SUPPORT)
#ifdef BDFS_SUPPORT
  FAR struct inode *blkdrvr_inode = NULL;
#endif
  FAR struct inode *mountpt_inode;
  FAR const struct mountpt_operations *mops;
  void *fshandle;
  int errcode;
  int status;

  /* Verify required pointer arguments */

  DEBUGASSERT(target && filesystemtype);

  /* Find the specified filesystem.  Try the block driver file systems first */

#ifdef BDFS_SUPPORT
  if ((mops = mount_findfs(g_bdfsmap, filesystemtype)) != NULL)
    {
      /* Make sure that a block driver argument was provided */

      DEBUGASSERT(source);

      /* Find the block driver */

      status = find_blockdriver(source, mountflags, &blkdrvr_inode);
      if (status < 0)
        {
           fdbg("Failed to find block driver %s\n", source);
           errcode = -status;
           goto errout;
        }
    }
  else
#endif /* BDFS_SUPPORT */
#ifdef NONBDFS_SUPPORT
  if ((mops = mount_findfs(g_nonbdfsmap, filesystemtype)) != NULL)
    {
    }
  else
#endif /* NONBDFS_SUPPORT */
    {
      fdbg("Failed to find file system %s\n", filesystemtype);
      errcode = ENODEV;
      goto errout;
    }

   /* Insert a dummy node -- we need to hold the inode semaphore
   * to do this because we will have a momentarily bad structure.
   */

  inode_semtake();
  mountpt_inode = inode_reserve(target);
  if (!mountpt_inode)
    {
      /* inode_reserve can fail for a couple of reasons, but the most likely
       * one is that the inode already exists.
       */

      fdbg("Failed to reserve inode\n");
      errcode = EBUSY;
      goto errout_with_semaphore;
    }

  /* Bind the block driver to an instance of the file system.  The file
   * system returns a reference to some opaque, fs-dependent structure
   * that encapsulates this binding.
   */

  if (!mops->bind)
    {
      /* The filesystem does not support the bind operation ??? */

      fdbg("Filesystem does not support bind\n");
      errcode = EINVAL;
      goto errout_with_mountpt;
    }

  /* Increment reference count for the reference we pass to the file system */

#ifdef BDFS_SUPPORT
#ifdef NONBDFS_SUPPORT
  if (blkdrvr_inode)
#endif
    {
      blkdrvr_inode->i_crefs++;
    }
#endif

  /* On failure, the bind method returns -errorcode */

#ifdef BDFS_SUPPORT
  status = mops->bind(blkdrvr_inode, data, &fshandle);
#else
  status = mops->bind(NULL, data, &fshandle);
#endif
  if (status != 0)
  {
      /* The inode is unhappy with the blkdrvr for some reason.  Back out
       * the count for the reference we failed to pass and exit with an
       * error.
       */

      fdbg("Bind method failed: %d\n", status);
#ifdef BDFS_SUPPORT
#ifdef NONBDFS_SUPPORT
      if (blkdrvr_inode)
#endif
        {
          blkdrvr_inode->i_crefs--;
        }
#endif
      errcode = -status;
      goto errout_with_mountpt;
  }

  /* We have it, now populate it with driver specific information. */

  INODE_SET_MOUNTPT(mountpt_inode);

  mountpt_inode->u.i_mops  = mops;
#ifdef CONFIG_FILE_MODE
  mountpt_inode->i_mode    = mode;
#endif
  mountpt_inode->i_private = fshandle;
  inode_semgive();

 /* We can release our reference to the blkdrver_inode, if the filesystem
  * wants to retain the blockdriver inode (which it should), then it must
  * have called inode_addref().  There is one reference on mountpt_inode
  * that will persist until umount() is called.
  */

#ifdef BDFS_SUPPORT
#ifdef NONBDFS_SUPPORT
  if (blkdrvr_inode)
#endif
    {
      inode_release(blkdrvr_inode);
    }
#endif
  return OK;

  /* A lot of goto's!  But they make the error handling much simpler */

errout_with_mountpt:
  mountpt_inode->i_crefs = 0;
  inode_remove(target);
  inode_semgive();
#ifdef BDFS_SUPPORT
#ifdef NONBDFS_SUPPORT
  if (blkdrvr_inode)
#endif
    {
       inode_release(blkdrvr_inode);
    }
#endif
  inode_release(mountpt_inode);
  goto errout;

errout_with_semaphore:
  inode_semgive();
#ifdef BDFS_SUPPORT
#ifdef NONBDFS_SUPPORT
  if (blkdrvr_inode)
#endif
    {
      inode_release(blkdrvr_inode);
    }
#endif

errout:
  errno = errcode;
  return ERROR;

#else
  fdbg("No filesystems enabled\n");
  ernno = ENOSYS;
  return error;
#endif /* BDFS_SUPPORT || NONBDFS_SUPPORT */
}
示例#7
0
int rename(FAR const char *oldpath, FAR const char *newpath)
{
  FAR struct inode *oldinode;
  FAR struct inode *newinode;
  const char       *oldrelpath = NULL;
#ifndef CONFIG_DISABLE_MOUNTPOINT
  const char       *newrelpath = NULL;
#endif
  int               errcode;
  int               ret;

  /* Ignore paths that are interpreted as the root directory which has no name
   * and cannot be moved
   */

  if (!oldpath || *oldpath == '\0' || oldpath[0] != '/' ||
      !newpath || *newpath == '\0' || newpath[0] != '/')
    {
      return -EINVAL;
    }

  /* Get an inode that includes the oldpath */

  oldinode = inode_find(oldpath, &oldrelpath);
  if (!oldinode)
    {
      /* There is no inode that includes in this path */

      errcode = ENOENT;
      goto errout;
    }

#ifndef CONFIG_DISABLE_MOUNTPOINT
  /* Verify that the old inode is a valid mountpoint. */

  if (INODE_IS_MOUNTPT(oldinode) && oldinode->u.i_mops)
    {
      /* Get an inode for the new relpath -- it should like on the same
       * mountpoint
       */

      newinode = inode_find(newpath, &newrelpath);
      if (!newinode)
        {
          /* There is no mountpoint that includes in this path */

          errcode = ENOENT;
          goto errout_with_oldinode;
        }

      /* Verify that the two paths lie on the same mountpoint inode */

      if (oldinode != newinode)
        {
          errcode = EXDEV;
          goto errout_with_newinode;
        }

      /* Perform the rename operation using the relative paths
       * at the common mountpoint.
       */

      if (oldinode->u.i_mops->rename)
        {
          ret = oldinode->u.i_mops->rename(oldinode, oldrelpath, newrelpath);
          if (ret < 0)
            {
              errcode = -ret;
              goto errout_with_newinode;
            }
        }
      else
        {
          errcode = ENOSYS;
          goto errout_with_newinode;
        }

      /* Successfully renamed */

      inode_release(newinode);
    }
  else
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
    {
      /* Create a new, empty inode at the destination location.
       * NOTE that the new inode will be created with a reference count
       * of  zero.
       */

      inode_semtake();
      ret = inode_reserve(newpath, &newinode);
      if (ret < 0)
        {
          /* It is an error if a node at newpath already exists in the tree
           * OR if we fail to allocate memory for the new inode (and possibly
           * any new intermediate path segments).
           */

          inode_semgive();
          errcode = EEXIST;
          goto errout_with_oldinode;
        }

      /* Copy the inode state from the old inode to the newly allocated inode */

      newinode->i_child   = oldinode->i_child;   /* Link to lower level inode */
      newinode->i_flags   = oldinode->i_flags;   /* Flags for inode */
      newinode->u.i_ops   = oldinode->u.i_ops;   /* Inode operations */
#ifdef CONFIG_FILE_MODE
      newinode->i_mode    = oldinode->i_mode;    /* Access mode flags */
#endif
      newinode->i_private = oldinode->i_private; /* Per inode driver private data */

      /* We now have two copies of the inode.  One with a reference count of
       * zero (the new one), and one that may have multiple references
       * including one by this logic (the old one)
       *
       * Remove the old inode.  Because we hold a reference count on the
       * inode, it will not be deleted now.  It will be deleted when all of
       * the references to to the inode have been released (perhaps when
       * inode_release() is called below).  inode_remove() should return
       * -EBUSY to indicate that the inode was not deleted now.
       */

      ret = inode_remove(oldpath);
      if (ret < 0 && ret != -EBUSY)
        {
          /* Remove the new node we just recreated */

          (void)inode_remove(newpath);
          inode_semgive();

          errcode = -ret;
          goto errout_with_oldinode;
        }

      /* Remove all of the children from the unlinked inode */

      oldinode->i_child = NULL;
      inode_semgive();
    }
#else
    {
      errcode = ENXIO;
      goto errout;
    }
#endif

  /* Successfully renamed */

  inode_release(oldinode);
  return OK;

#ifndef CONFIG_DISABLE_MOUNTPOINT
errout_with_newinode:
  inode_release(newinode);
#endif
errout_with_oldinode:
  inode_release(oldinode);
errout:
  set_errno(errcode);
  return ERROR;
}