Exemple #1
0
static inline int fs_checkfd(FAR struct tcb_s *tcb, int fd, int oflags)
{
  FAR struct file *filep;
  FAR struct inode *inode;
  int ret;

  DEBUGASSERT(tcb && tcb->group);

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

  ret = fs_getfilep(fd, &filep);
  if (ret < 0)
    {
      return ret;
    }

  /* Get the inode associated with the file descriptor.  This should
   * normally be the case if fd >= 0.  But not in the case where the
   * called attempts to explicitly stdin with fdopen(0) but stdin has
   * been closed.
   */

  inode = filep->f_inode;
  if (!inode)
    {
      /* No inode -- descriptor does not correspond to an open file */

      return -ENOENT;
    }

  /* Make sure that the inode supports the requested access.  In
   * the case of fdopen, we are not actually creating the file -- in
   * particular w and w+ do not truncate the file and any files have
   * already been created.
   */

  if (inode_checkflags(inode, oflags) != OK)
    {
      /* Cannot support the requested access */

      return -EACCES;
    }

  /* Looks good to me */

  return OK;
}
Exemple #2
0
static inline int fs_checkfd(FAR _TCB *tcb, int fd, int oflags)
{
  FAR struct filelist *flist;
  FAR struct inode    *inode;

  /* Get the file list from the TCB */

  flist = tcb->filelist;

  /* Get the inode associated with the file descriptor.  This should
   * normally be the case if fd >= 0.  But not in the case where the
   * called attempts to explictly stdin with fdopen(0) but stdin has
   * been closed.
   */
  
  inode = flist->fl_files[fd].f_inode;
  if (!inode)
    {
      /* No inode -- descriptor does not correspond to an open file */

      return -ENOENT;
    }

  /* Make sure that the inode supports the requested access.  In
   * the case of fdopen, we are not actually creating the file -- in
   * particular w and w+ do not truncate the file and any files have
   * already been created.
   */

  if (inode_checkflags(inode, oflags) != OK)
    {
      /* Cannot support the requested access */

      return -EACCES;
    }

  /* Looks good to me */

  return OK;
}
Exemple #3
0
FAR struct file_struct *fs_fdopen(int fd, int oflags, FAR _TCB *tcb)
{
    FAR struct filelist   *flist;
    FAR struct streamlist *slist;
    FAR struct inode      *inode;
    FAR FILE              *stream;
    int                    err = OK;
    int                    ret;
    int                    i;

    /* Check input parameters */

    if (fd < 0)
    {
        err = EBADF;
        goto errout;
    }

    /* A NULL TCB pointer means to use this threads TCB.  This is a little
     * hack the let's this function be called from user-space (via a syscall)
     * without having access to the TCB.
     */

    if (!tcb)
    {
        tcb = sched_self();
    }

    /* Get the file and stream list from the TCB */

    flist = tcb->filelist;
    slist = tcb->streams;

    /* Get the inode associated with the file descriptor.  This should
     * normally be the case if fd >= 0.  But not in the case where the
     * called attempts to explictly stdin with fdopen(0) but stdin has
     * been closed.
     */

    inode = flist->fl_files[fd].f_inode;
    if (!inode)
    {
        err = ENOENT;
        goto errout;
    }

    /* Make sure that the inode supports the requested access.  In
     * the case of fdopen, we are not actually creating the file -- in
     * particular w and w+ do not truncate the file and any files have
     * already been created.
     */

    if (inode_checkflags(inode, oflags) != OK)
    {
        err = EACCES;
        goto errout;
    }

    /* Find an unallocated FILE structure */

    ret = sem_wait(&slist->sl_sem);
    if (ret != OK)
    {
        goto errout_with_errno;
    }

    for (i = 0 ; i < CONFIG_NFILE_STREAMS; i++)
    {
        stream = &slist->sl_streams[i];
        if (stream->fs_filedes < 0)
        {
            /* Zero the structure */
#if CONFIG_STDIO_BUFFER_SIZE > 0
            memset(stream, 0, sizeof(FILE));
#elif CONFIG_NUNGET_CHARS > 0
            stream->fs_nungotten = 0;
#endif

#if CONFIG_STDIO_BUFFER_SIZE > 0
            /* Initialize the semaphore the manages access to the buffer */

            (void)sem_init(&stream->fs_sem, 0, 1);

            /* Allocate the IO buffer */

            stream->fs_bufstart = kmalloc(CONFIG_STDIO_BUFFER_SIZE);
            if (!stream)
            {
                err = ENOMEM;
                goto errout_with_sem;
            }

            /* Set up pointers */

            stream->fs_bufend  = &stream->fs_bufstart[CONFIG_STDIO_BUFFER_SIZE];
            stream->fs_bufpos  = stream->fs_bufstart;
            stream->fs_bufpos  = stream->fs_bufstart;
            stream->fs_bufread = stream->fs_bufstart;
#endif
            /* Save the file description and open flags.  Setting the
             * file descriptor locks this stream.
             */

            stream->fs_filedes = fd;
            stream->fs_oflags  = oflags;

            sem_post(&slist->sl_sem);
            return stream;
        }
    }

#if CONFIG_STDIO_BUFFER_SIZE > 0
errout_with_sem:
#endif
    sem_post(&slist->sl_sem);

errout:
    set_errno(err);
errout_with_errno:
    return NULL;
}
Exemple #4
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;
}
Exemple #5
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;
}