Пример #1
0
int open(const char *path, int oflags, ...)
{
  FAR struct filelist *list;
  FAR struct inode    *inode;
  FAR const char      *relpath = NULL;
#if defined(CONFIG_FILE_MODE) || !defined(CONFIG_DISABLE_MOUNTPOINT)
  mode_t               mode = 0666;
#endif
  int                  ret;
  int                  fd;

  /* Get the thread-specific file list */

  list = sched_getfiles();
  if (!list)
    {
      ret = EMFILE;
      goto errout;
    }

#ifdef CONFIG_FILE_MODE
#  ifdef CONFIG_CPP_HAVE_WARNING
#    warning "File creation not implemented"
#  endif

  /* If the file is opened for creation, then get the mode bits */

  if (oflags & (O_WRONLY|O_CREAT) != 0)
    {
      va_list ap;
      va_start(ap, oflags);
      mode = va_arg(ap, mode_t);
      va_end(ap);
    }
#endif

  /* Get an inode for this file */

  inode = inode_find(path, &relpath);
  if (!inode)
    {
      /* "O_CREAT is not set and the named file does not exist.  Or, a
       * directory component in pathname does not exist or is a dangling
       * symbolic link."
       */

      ret = ENOENT;
      goto errout;
    }

  /* Verify that the inode is valid and either a "normal" or a mountpoint.  We
   * specifically exclude block drivers.
   */

#ifndef CONFIG_DISABLE_MOUNTPOINT
  if ((!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode)) || !inode->u.i_ops)
#else
  if (!INODE_IS_DRIVER(inode) || !inode->u.i_ops)
#endif
    {
      ret = ENXIO;
      goto errout_with_inode;
    }

  /* Make sure that the inode supports the requested access */

  ret = inode_checkflags(inode, oflags);
  if (ret < 0)
    {
      ret = -ret;
      goto errout_with_inode;
    }

  /* Associate the inode with a file structure */

  fd = files_allocate(inode, oflags, 0, 0);
  if (fd < 0)
    {
      ret = EMFILE;
      goto errout_with_inode;
    }

  /* Perform the driver open operation.  NOTE that the open method may be
   * called many times.  The driver/mountpoint logic should handled this
   * because it may also be closed that many times.
   */

  ret = OK;
  if (inode->u.i_ops->open)
    {
#ifndef CONFIG_DISABLE_MOUNTPOINT
      if (INODE_IS_MOUNTPT(inode))
        {
          ret = inode->u.i_mops->open((FAR struct file*)&list->fl_files[fd],
                                      relpath, oflags, mode);
        }
      else
#endif
        {
          ret = inode->u.i_ops->open((FAR struct file*)&list->fl_files[fd]);
        }
    }

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

  return fd;

 errout_with_fd:
  files_release(fd);
 errout_with_inode:
  inode_release(inode);
 errout:
  set_errno(ret);
  return ERROR;
}
Пример #2
0
int syslog_initialize(void)
{
  FAR struct inode    *inode;
  FAR const char      *relpath = NULL;
  int                  ret;

  /* At this point, the only expected states are SYSLOG_UNINITIALIZED or
   * SYSLOG_REOPEN..  Not SYSLOG_INITIALIZING, SYSLOG_FAILURE, SYSLOG_OPENED.
   */

  DEBUGASSERT(g_sysdev.sl_state == SYSLOG_UNINITIALIZED ||
              g_sysdev.sl_state == SYSLOG_REOPEN);

  g_sysdev.sl_state = SYSLOG_INITIALIZING;

  /* Try to open the device.
   *
   * Note that we cannot just call open.  The syslog device must work on all
   * threads.  Open returns a file descriptor that is valid only for the
   * task that opened the device (and its pthread children).  Instead, we
   * essentially re-implement the guts of open() here so that we can get to
   * the thread-independent structures of the inode.
   */

  /* Get an inode for this file/device */

  inode = inode_find(CONFIG_SYSLOG_DEVPATH, &relpath);
  if (!inode)
    {
      /* The inode was not found.  In this case, we will attempt to re-open
       * the device repeatedly.  The assumption is that the device path is
       * valid but that the driver has not yet been registered.
       */

      g_sysdev.sl_state = SYSLOG_REOPEN;
      return -ENOENT;
    }

  /* Verify that the inode is valid and either a character driver or a
   * mountpoint.
   */

#ifndef CONFIG_DISABLE_MOUNTPOINT
  if ((!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode)))
#else
  if (!INODE_IS_DRIVER(inode))
#endif
    {
      ret = -ENXIO;
      goto errout_with_inode;
    }

  /* Make sure that the "entity" at this inode supports write access */

  if (!inode->u.i_ops || !inode->u.i_ops->write)
    {
      ret = -EACCES;
      goto errout_with_inode;
    }

  /* Initialize the file structure */

  g_sysdev.sl_file.f_oflags = SYSLOG_OFLAGS;
  g_sysdev.sl_file.f_pos    = 0;
  g_sysdev.sl_file.f_inode  = inode;

  /* Perform the low-level open operation. */

  ret = OK;
  if (inode->u.i_ops->open)
    {
      /* Is the inode a mountpoint? */

#ifndef CONFIG_DISABLE_MOUNTPOINT
      if (INODE_IS_MOUNTPT(inode))
        {
          /* Yes.  Open the device write-only, try to create it if it
           * doesn't exist, if the file that already exists, then append the
           * new log data to end of the file.
           */

          ret = inode->u.i_mops->open(&g_sysdev.sl_file, relpath,
                                      SYSLOG_OFLAGS, 0666);
        }

      /* No... then it must be a character driver in the NuttX pseudo-
       * file system.
       */

      else
#endif
        {
          ret = inode->u.i_ops->open(&g_sysdev.sl_file);
        }
    }

  /* Was the file/device successfully opened? */

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

  /* The SYSLOG device is open and ready for writing. */

  sem_init(&g_sysdev.sl_sem, 0, 1);
  g_sysdev.sl_holder = NO_HOLDER;
  g_sysdev.sl_state  = SYSLOG_OPENED;
  return OK;

 errout_with_inode:
  inode_release(inode);
  g_sysdev.sl_state = SYSLOG_FAILURE;
  return ret;
}
Пример #3
0
int unlink(FAR const char *pathname)
{
  FAR struct inode *inode;
  const char       *relpath = NULL;
  int               errcode;
  int               ret;

  /* Get an inode for this file */

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

      errcode = ENOENT;
      goto errout;
    }

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

  if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops)
    {
      /* Perform the unlink operation using the relative path at the
       * mountpoint.
       */

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

#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
  /* If this is a "dangling" pseudo-file node (i.e., it has operations) then rm
   * should remove the node.
   */

  if (!INODE_IS_SPECIAL(inode) && inode->u.i_ops)
    {
      /* If this is a pseudo-file node (i.e., it has no operations)
       * then rmdir should remove the node.
       */

      if (inode->u.i_ops)
        {
          inode_semtake();

          /* Refuse to unlink the inode if it has children.  I.e., if it is
           * functioning as a directory and the directory is not empty.
           */

          if (inode->i_child != NULL)
            {
              errcode = ENOTEMPTY;
              inode_semgive();
              goto errout_with_inode;
            }

          /* Notify the driver that it has been unlinked.  If there are no
           * open references to the driver instance, then the driver should
           * release all resources because it is no longer accessible.
           */

          if (INODE_IS_DRIVER(inode) && inode->u.i_ops->unlink)
            {
              /* Notify the character driver that it has been unlinked */

              ret = inode->u.i_ops->unlink(inode);
              if (ret < 0)
                {
                  errcode = -ret;
                  goto errout_with_inode;
                }
            }
#ifndef CONFIG_DISABLE_MOUNTPOINT
          else if (INODE_IS_BLOCK(inode) && inode->u.i_bops->unlink)
            {
              /* Notify the block driver that it has been unlinked */

              ret = inode->u.i_bops->unlink(inode);
              if (ret < 0)
                {
                  errcode = -ret;
                  goto errout_with_inode;
                }
            }
#endif

          /* 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() will
           * return -EBUSY to indicate that the inode was not deleted now.
           */

          ret = inode_remove(pathname);
          inode_semgive();

          if (ret < 0 && ret != -EBUSY)
            {
              errcode = -ret;
              goto errout_with_inode;
            }
        }
      else
        {
          errcode = EISDIR;
          goto errout_with_inode;
        }
    }
  else
#endif
    {
      errcode = ENXIO;
      goto errout_with_inode;
    }

  /* Successfully unlinked */

  inode_release(inode);
  return OK;

errout_with_inode:
  inode_release(inode);
errout:
  set_errno(errcode);
  return ERROR;
}
Пример #4
0
int open(const char *path, int oflags, ...)
{
  FAR struct file *filep;
  FAR struct inode *inode;
  FAR const char *relpath = NULL;
#if defined(CONFIG_FILE_MODE) || !defined(CONFIG_DISABLE_MOUNTPOINT)
  mode_t mode = 0666;
#endif
  int ret;
  int fd;

#ifdef CONFIG_FILE_MODE
#  ifdef CONFIG_CPP_HAVE_WARNING
#    warning "File creation not implemented"
#  endif

  /* If the file is opened for creation, then get the mode bits */

  if ((oflags & (O_WRONLY | O_CREAT)) != 0)
    {
      va_list ap;
      va_start(ap, oflags);
      mode = va_arg(ap, mode_t);
      va_end(ap);
    }
#endif

  /* Get an inode for this file */

  inode = inode_find(path, &relpath);
  if (!inode)
    {
      /* "O_CREAT is not set and the named file does not exist.  Or, a
       * directory component in pathname does not exist or is a dangling
       * symbolic link."
       */

      ret = ENOENT;
      goto errout;
    }

#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && \
    !defined(CONFIG_DISABLE_MOUNTPOINT)
   /* If the inode is block driver, then we may return a character driver
    * proxy for the block driver.  block_proxy() will instantiate a BCH
    * character driver wrapper around the block driver, open(), then
    * unlink() the character driver.  On success, block_proxy() will
    * return the file descriptor of the opened character driver.
    *
    * NOTE: This will recurse to open the character driver proxy.
    */

   if (INODE_IS_BLOCK(inode))
     {
       /* Release the inode reference */

       inode_release(inode);

       /* Get the file descriptor of the opened character driver proxy */

       fd = block_proxy(path, oflags);
       if (fd < 0)
         {
           ret = fd;
           goto errout;
         }

       /* Return the file descriptor */

       return fd;
     }
   else
#endif

  /* Verify that the inode is either a "normal" character driver or a
   * mountpoint.  We specifically "special" inodes (semaphores, message
   * queues, shared memory).
   */

#ifndef CONFIG_DISABLE_MOUNTPOINT
  if ((!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode)) || !inode->u.i_ops)
#else
  if (!INODE_IS_DRIVER(inode) || !inode->u.i_ops)
#endif
    {
      ret = ENXIO;
      goto errout_with_inode;
    }

  /* Make sure that the inode supports the requested access */

  ret = inode_checkflags(inode, oflags);
  if (ret < 0)
    {
      ret = -ret;
      goto errout_with_inode;
    }

  /* Associate the inode with a file structure */

  fd = files_allocate(inode, oflags, 0, 0);
  if (fd < 0)
    {
      ret = EMFILE;
      goto errout_with_inode;
    }

  /* Get the file structure corresponding to the file descriptor. */

  filep = fs_getfilep(fd);
  if (!filep)
    {
      /* The errno value has already been set */

      return ERROR;
    }

  /* Perform the driver open operation.  NOTE that the open method may be
   * called many times.  The driver/mountpoint logic should handled this
   * because it may also be closed that many times.
   */

  ret = OK;
  if (inode->u.i_ops->open)
    {
#ifndef CONFIG_DISABLE_MOUNTPOINT
      if (INODE_IS_MOUNTPT(inode))
        {
          ret = inode->u.i_mops->open(filep, relpath, oflags, mode);
        }
      else
#endif
        {
          ret = inode->u.i_ops->open(filep);
        }
    }

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

  return fd;

errout_with_fd:
  files_release(fd);
errout_with_inode:
  inode_release(inode);
errout:
  set_errno(ret);
  return ERROR;
}