Exemple #1
0
FAR struct file *fs_getfilep(int fd)
{
	FAR struct filelist *list;
	int errcode;

	if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) {
		errcode = EBADF;
		goto errout;
	}

	/* The descriptor is in a valid range to file descriptor... Get the
	 * thread-specific file list.
	 */

	list = sched_getfiles();

	/* The file list can be NULL under one obscure cornercase:  When memory
	 * management debug output is enabled.  Then there may be attempts to
	 * write to stdout from malloc before the group data has been allocated.
	 */

	if (!list) {
		errcode = EAGAIN;
		goto errout;
	}

	/* And return the file pointer from the list */

	return &list->fl_files[fd];

errout:
	set_errno(errcode);
	return NULL;
}
Exemple #2
0
ssize_t sendfile(int outfd, int infd, off_t *offset, size_t count)
{
#if defined(CONFIG_NET_TCP) && CONFIG_NSOCKET_DESCRIPTORS > 0

  /* Check the destination file descriptor:  Is it a (probable) file
   * descriptor?  Check the source file:  Is it a normal file?
   */

  if ((unsigned int)outfd >= CONFIG_NFILE_DESCRIPTORS &&
      (unsigned int)infd < CONFIG_NFILE_DESCRIPTORS)
    {
      FAR struct filelist *list;

      /* This appears to be a file-to-socket transfer.  Get the thread-
       * specific file list.
       */

      list = sched_getfiles();
      DEBUGASSERT(list);

      /* Then let net_sendfile do the work. */

      return net_sendfile(outfd, &list->fl_files[infd], offset, count);
    }
  else
#endif
    {
      /* No... then this is probably a file-to-file transfer.  The generic
       * lib_sendfile() can handle that case.
       */

      return lib_sendfile(outfd, infd, offset, count);
    }
}
Exemple #3
0
int files_allocate(FAR struct inode *inode, int oflags, off_t pos, int minfd)
{
  FAR struct filelist *list;
  int i;

  list = sched_getfiles();
  DEBUGASSERT(list);

  _files_semtake(list);
  for (i = minfd; i < CONFIG_NFILE_DESCRIPTORS; i++)
    {
      if (!list->fl_files[i].f_inode)
        {
           list->fl_files[i].f_oflags = oflags;
           list->fl_files[i].f_pos    = pos;
           list->fl_files[i].f_inode  = inode;
           list->fl_files[i].f_priv   = NULL;
           _files_semgive(list);
           return i;
        }
    }

  _files_semgive(list);
  return ERROR;
}
Exemple #4
0
int ioctl(int fd, int req, unsigned long arg)
{
  int err;
#if CONFIG_NFILE_DESCRIPTORS > 0
  FAR struct filelist *list;
  FAR struct file     *filep;
  FAR struct inode    *inode;
  int                  ret = OK;

  /* Did we get a valid file descriptor? */

  if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
#endif
    {
      /* Perform the socket ioctl */

#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
      if ((unsigned int)fd < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
        {
          return netdev_ioctl(fd, req, arg);
        }
      else
#endif
        {
          err = EBADF;
          goto errout;
        }
    }

#if CONFIG_NFILE_DESCRIPTORS > 0
  /* Get the thread-specific file list */

  list = sched_getfiles();
  DEBUGASSERT(list);

  /* Is a driver registered? Does it support the ioctl method? */

  filep = &list->fl_files[fd];
  inode = filep->f_inode;

  if (inode && inode->u.i_ops && inode->u.i_ops->ioctl)
    {
      /* Yes, then let it perform the ioctl */

      ret = (int)inode->u.i_ops->ioctl(filep, req, arg);
      if (ret < 0)
        {
          err = -ret;
          goto errout;
        }
    }

  return ret;
#endif

errout:
  set_errno(err);
  return ERROR;
}
Exemple #5
0
static inline ssize_t file_write(int fd, FAR const void *buf, size_t nbytes)
{
  FAR struct filelist *list;
  FAR struct file *this_file;
  FAR struct inode *inode;
  int ret;
  int err;

  /* Get the thread-specific file list */

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

  /* Was this file opened for write access? */

  this_file = &list->fl_files[fd];
  if ((this_file->f_oflags & O_WROK) == 0)
    {
      err = EBADF;
      goto errout;
    }

  /* Is a driver registered? Does it support the write method? */

  inode = this_file->f_inode;
  if (!inode || !inode->u.i_ops || !inode->u.i_ops->write)
    {
      err = EBADF;
      goto errout;
    }

  /* Yes, then let the driver perform the write */

  ret = inode->u.i_ops->write(this_file, buf, nbytes);
  if (ret < 0)
    {
      err = -ret;
      goto errout;
    }

  return ret;

errout:
  *get_errno_ptr() = err;
  return ERROR;
}
Exemple #6
0
static int poll_fdsetup(int fd, FAR struct pollfd *fds, bool setup)
{
    FAR struct filelist *list;
    FAR struct file     *this_file;
    FAR struct inode    *inode;
    int                  ret = -ENOSYS;

    /* Check for a valid file descriptor */

    if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
    {
        /* Perform the socket ioctl */

#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
        if ((unsigned int)fd < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
        {
            return net_poll(fd, fds, setup);
        }
        else
#endif
        {
            return -EBADF;
        }
    }

    /* Get the thread-specific file list */

    list = sched_getfiles();
    if (!list)
    {
        return -EMFILE;
    }

    /* Is a driver registered? Does it support the poll method?
     * If not, return -ENOSYS
     */

    this_file = &list->fl_files[fd];
    inode     = this_file->f_inode;

    if (inode && inode->u.i_ops && inode->u.i_ops->poll)
    {
        /* Yes, then setup the poll */

        ret = (int)inode->u.i_ops->poll(this_file, fds, setup);
    }
    return ret;
}
Exemple #7
0
void files_release(int fd)
{
  FAR struct filelist *list;

  list = sched_getfiles();
  DEBUGASSERT(list);

  if (fd >=0 && fd < CONFIG_NFILE_DESCRIPTORS)
    {
      _files_semtake(list);
      list->fl_files[fd].f_oflags  = 0;
      list->fl_files[fd].f_pos     = 0;
      list->fl_files[fd].f_inode = NULL;
      _files_semgive(list);
    }
}
Exemple #8
0
int dup2(int fildes1, int fildes2)
#endif
{
  FAR struct filelist *list;

  /* Get the thread-specific file list */

  list = sched_getfiles();
  if (!list)
    {
      set_errno(EMFILE);
      return ERROR;
    }

  /* Verify that fildes is a valid, open file descriptor */

  if (!DUP_ISOPEN(fildes1, list))
    {
      set_errno(EBADF);
      return ERROR;
    }

  /* Handle a special case */

  if (fildes1 == fildes2)
    {
      return fildes1;
    }

  /* Verify fildes2 */

  if ((unsigned int)fildes2 >= CONFIG_NFILE_DESCRIPTORS)
    {
      set_errno(EBADF);
      return ERROR;
    }

  return files_dup(&list->fl_files[fildes1], &list->fl_files[fildes2]);
}
Exemple #9
0
int files_close(int fd)
{
  FAR struct filelist *list;
  int                  ret;

  /* Get the thread-specific file list */

  list = sched_getfiles();
  DEBUGASSERT(list);

  /* If the file was properly opened, there should be an inode assigned */

  if (fd < 0 || fd >= CONFIG_NFILE_DESCRIPTORS || !list->fl_files[fd].f_inode)
   {
     return -EBADF;
   }

  /* Perform the protected close operation */

  _files_semtake(list);
  ret = _files_close(&list->fl_files[fd]);
  _files_semgive(list);
  return ret;
}
Exemple #10
0
static inline int file_vfcntl(int fildes, int cmd, va_list ap)
{
  FAR struct filelist *list;
  FAR struct file *this_file;
  int err = 0;
  int ret = OK;

  /* Get the thread-specific file list */

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

  /* Was this file opened ? */

  this_file = &list->fl_files[fildes];
  if (!this_file->f_inode)
    {
      err = EBADF;
      goto errout;
    }

  switch (cmd)
    {
      case F_DUPFD:
        /* Return a new file descriptor which shall be the lowest numbered
         * available (that is, not already open) file descriptor greater than
         * or equal to the third argument, arg, taken as an integer of type
         * int. The new file descriptor shall refer to the same open file
         * description as the original file descriptor, and shall share any
         * locks.  The FD_CLOEXEC flag associated  with the new file descriptor
         * shall be cleared to keep the file open across calls to one of the
         * exec functions.
         */

        {
          ret = file_dup(fildes, va_arg(ap, int));
        }
        break;

      case F_GETFD:
        /* Get the file descriptor flags defined in <fcntl.h> that are associated
         * with the file descriptor fildes.  File descriptor flags are associated
         * with a single file descriptor and do not affect other file descriptors
         * that refer to the same file.
         */

      case F_SETFD:
        /* Set the file descriptor flags defined in <fcntl.h>, that are associated
         * with fildes, to the third argument, arg, taken as type int. If the
         * FD_CLOEXEC flag in the third argument is 0, the file shall remain open
         * across the exec functions; otherwise, the file shall be closed upon
         * successful execution of one  of  the  exec  functions.
         */

        err = ENOSYS;
        break;

      case F_GETFL:
        /* Get the file status flags and file access modes, defined in <fcntl.h>,
         * for the file description associated with fildes. The file access modes
         * can be extracted from the return value using the mask O_ACCMODE, which is
         * defined  in <fcntl.h>. File status flags and file access modes are associated
         * with the file description and do not affect other file descriptors that
         * refer to the same file with different open file descriptions.
         */

        {
          ret = this_file->f_oflags;
        }
        break;

      case F_SETFL:
        /* Set the file status flags, defined in <fcntl.h>, for the file description
         * associated with fildes from the corresponding  bits in the third argument,
         * arg, taken as type int. Bits corresponding to the file access mode and
         * the file creation flags, as defined in <fcntl.h>, that are set in arg shall
         * be ignored. If any bits in arg other than those mentioned here are changed
         * by the application, the result is unspecified.
         */

        {
          int oflags = va_arg(ap, int);

          oflags              &=  FFCNTL;
          this_file->f_oflags &= ~FFCNTL;
          this_file->f_oflags |=  oflags;
        }
        break;

      case F_GETOWN:
        /* If fildes refers to a socket, get the process or process group ID specified
         * to receive SIGURG signals when out-of-band data is available. Positive values
         * indicate a process ID; negative values, other than -1, indicate a process group
         * ID. If fildes does not refer to a socket, the results are unspecified.
         */

      case F_SETOWN:
        /* If fildes refers to a socket, set the process or process group ID specified
         * to receive SIGURG signals when out-of-band data is available, using the value
         * of the third argument, arg, taken as type int. Positive values indicate a 
         * process ID; negative values, other than -1, indicate a process group ID. If
         * fildes does not refer to a socket, the results are unspecified.
         */

        err = EBADF; /* Only valid on socket descriptors */
        break;

      case F_GETLK:
        /* Get the first lock which blocks the lock description pointed to by the third
         * argument, arg, taken as a pointer to type struct flock, defined in <fcntl.h>.
         * The information retrieved shall overwrite the information passed to fcntl() in
         * the structure flock. If no lock is found that would prevent this lock from being
         * created, then the structure shall be left unchanged except for the lock type
         * which shall be set to F_UNLCK.
         */

      case F_SETLK:
        /* Set or clear a file segment lock according to the lock description pointed to
         * by the third argument, arg, taken as a pointer to type struct flock, defined in
         * <fcntl.h>. F_SETLK can establish shared (or read) locks (F_RDLCK) or exclusive
         * (or write) locks (F_WRLCK), as well  as  to  remove  either  type  of  lock  (F_UNLCK).
         * F_RDLCK, F_WRLCK, and F_UNLCK are defined in <fcntl.h>. If a shared or exclusive
         * lock cannot be set, fcntl() shall return immediately with a return value of -1.
         */

      case F_SETLKW:
        /* This command shall be equivalent to F_SETLK except that if a shared or exclusive
         * lock is blocked by other locks, the thread shall wait until the request can be
         * satisfied. If a signal that is to be caught is received while fcntl() is waiting
         * for a region, fcntl() shall be interrupted. Upon return from the signal handler,
         * fcntl() shall return -1 with errno set to [EINTR], and the lock operation shall
         * not be done.
         */

        err = ENOSYS; /* Not implemented */
        break;

      default:
        err = EINVAL;
        break;
    }

errout:
  if (err != 0)
    {
      set_errno(err);
      return ERROR;
    }

  return ret;
}
Exemple #11
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 #12
0
off_t lseek(int fd, off_t offset, int whence)
{
  FAR struct filelist *list;
  FAR struct file     *filep;
  FAR struct inode    *inode;
  int                  err;

  /* Did we get a valid file descriptor? */

  if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
    {
      err = EBADF;
      goto errout;
    }

  /* Get the thread-specific file list */

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

  /* Is a driver registered? */

  filep = &list->fl_files[fd];
  inode =  filep->f_inode;

  if (inode && inode->u.i_ops)
    {
      /* Does it support the seek method */

      if (inode->u.i_ops->seek)
        {
           /* Yes, then let it perform the seek */

           err = (int)inode->u.i_ops->seek(filep, offset, whence);
           if (err < 0)
             {
               err = -err;
               goto errout;
             }
         }
      else
        {
           /* No... there are a couple of default actions we can take */

           switch (whence)
             {
               case SEEK_CUR:
                 offset += filep->f_pos;

               case SEEK_SET:
                 if (offset >= 0)
                   {
                     filep->f_pos = offset; /* Might be beyond the end-of-file */
                     break;
                   }
                 else
                   {
                     err = EINVAL;
                     goto errout;
                   }
                  break;

               case SEEK_END:
                 err = ENOSYS;
                 goto errout;

               default:
                 err = EINVAL;
                 goto errout;
             }
        }
    }
  return filep->f_pos;

errout:
  *get_errno_ptr() = err;
  return (off_t)ERROR;
}
Exemple #13
0
int files_dup(FAR struct file *filep1, FAR struct file *filep2)
{
  FAR struct filelist *list;
  FAR struct inode *inode;
  int err;
  int ret;

  if (!filep1 || !filep1->f_inode || !filep2)
    {
      err = EBADF;
      goto errout;
    }

  list = sched_getfiles();
  DEBUGASSERT(list);

  _files_semtake(list);

  /* If there is already an inode contained in the new file structure,
   * close the file and release the inode.
   */

  ret = _files_close(filep2);
  if (ret < 0)
    {
      /* An error occurred while closing the driver */

      goto errout_with_ret;
    }

  /* Increment the reference count on the contained inode */

  inode = filep1->f_inode;
  inode_addref(inode);

  /* Then clone the file structure */

  filep2->f_oflags = filep1->f_oflags;
  filep2->f_pos    = filep1->f_pos;
  filep2->f_inode  = inode;

  /* Call the open method on the file, driver, mountpoint so that it
   * can maintain the correct open counts.
   */

  if (inode->u.i_ops && inode->u.i_ops->open)
    {
#ifndef CONFIG_DISABLE_MOUNTPOINT
      if (INODE_IS_MOUNTPT(inode))
        {
         /* Dup the open file on the in the new file structure */

          ret = inode->u.i_mops->dup(filep1, filep2);
        }
      else
#endif
        {
          /* (Re-)open the pseudo file or device driver */

          ret = inode->u.i_ops->open(filep2);
        }

      /* Handle open failures */

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

  _files_semgive(list);
  return OK;

/* Handler various error conditions */

errout_with_inode:
  inode_release(filep2->f_inode);
  filep2->f_oflags = 0;
  filep2->f_pos    = 0;
  filep2->f_inode  = NULL;

errout_with_ret:
  err              = -ret;
  _files_semgive(list);

errout:
  set_errno(err);
  return ERROR;
}