Esempio n. 1
0
ssize_t read(
  int         fd,
  void       *buffer,
  size_t      count
)
{
  ssize_t      rc;
  rtems_libio_t *iop;

  rtems_libio_check_fd( fd );
  iop = rtems_libio_iop( fd );
  rtems_libio_check_is_open( iop );
  rtems_libio_check_buffer( buffer );
  rtems_libio_check_count( count );
  rtems_libio_check_permissions_with_error( iop, LIBIO_FLAGS_READ, EBADF );

  /*
   *  Now process the read().
   */

  if ( !iop->handlers->read_h )
    rtems_set_errno_and_return_minus_one( ENOTSUP );

  rc = (*iop->handlers->read_h)( iop, buffer, count );

  if ( rc > 0 )
    iop->offset += rc;

  return rc;
}
Esempio n. 2
0
File: write.c Progetto: rtemss/rtems
ssize_t write(
  int         fd,
  const void *buffer,
  size_t      count
)
{
  ssize_t  rc;
  rtems_libio_t     *iop;

  rtems_libio_check_fd( fd );
  iop = rtems_libio_iop( fd );
  rtems_libio_check_is_open( iop );
  rtems_libio_check_buffer( buffer );
  rtems_libio_check_count( count );
  rtems_libio_check_permissions_with_error( iop, LIBIO_FLAGS_WRITE, EBADF );

  /*
   *  Now process the write() request.
   */
  rc = (*iop->pathinfo.handlers->write_h)( iop, buffer, count );

  if ( rc > 0 )
    iop->offset += rc;

  return rc;
}
Esempio n. 3
0
int ftruncate(
  int     fd,
  off_t   length
)
{
  rtems_libio_t                    *iop;
  rtems_filesystem_location_info_t  loc;

  rtems_libio_check_fd( fd );
  iop = rtems_libio_iop( fd );
  rtems_libio_check_is_open(iop);
  rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );

  /*
   *  Now process the ftruncate() request.
   */

  /*
   *  Make sure we are not working on a directory
   */

  loc = iop->pathinfo;
  if ( !loc.ops->node_type_h )
    rtems_set_errno_and_return_minus_one( ENOTSUP );

  if ( (*loc.ops->node_type_h)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY )
    rtems_set_errno_and_return_minus_one( EISDIR );

  rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );

  if ( !iop->handlers->ftruncate_h )
    rtems_set_errno_and_return_minus_one( ENOTSUP );

  return (*iop->handlers->ftruncate_h)( iop, length );
}
Esempio n. 4
0
int ioctl(
  int  fd,
  ioctl_command_t  command,
  ...
)
{
  va_list            ap;
  int                rc;
  rtems_libio_t     *iop;
  void              *buffer;

  rtems_libio_check_fd( fd );
  iop = rtems_libio_iop( fd );
  rtems_libio_check_is_open(iop);

  va_start(ap, command);

  buffer = va_arg(ap, void *);

  /*
   *  Now process the ioctl().
   */
  rc = (*iop->pathinfo.handlers->ioctl_h)( iop, command, buffer );

  va_end( ap );
  return rc;
}
Esempio n. 5
0
off_t lseek(
    int     fd,
    off_t   offset,
    int     whence
)
{
    rtems_libio_t *iop;
    off_t          old_offset;
    off_t          status;

    rtems_libio_check_fd( fd );
    iop = rtems_libio_iop( fd );
    rtems_libio_check_is_open(iop);

    /*
     *  Check as many errors as possible before touching iop->offset.
     */

    if ( !iop->handlers->lseek_h )
        rtems_set_errno_and_return_minus_one( ENOTSUP );

    /*
     *  Now process the lseek().
     */

    old_offset = iop->offset;
    switch ( whence ) {
    case SEEK_SET:
        iop->offset = offset;
        break;

    case SEEK_CUR:
        iop->offset += offset;
        break;

    case SEEK_END:
        iop->offset = iop->size + offset;
        break;

    default:
        rtems_set_errno_and_return_minus_one( EINVAL );
    }

    /*
     *  At this time, handlers assume iop->offset has the desired
     *  new offset.
     */

    status = (*iop->handlers->lseek_h)( iop, offset, whence );
    if ( status == (off_t) -1 )
        iop->offset = old_offset;

    /*
     *  So if the operation failed, we have to restore iop->offset.
     */

    return status;
}
Esempio n. 6
0
int fchdir(
    int       fd
)
{
    rtems_libio_t *iop;
    rtems_filesystem_location_info_t loc, saved;

    rtems_libio_check_fd( fd );
    iop = rtems_libio_iop( fd );
    rtems_libio_check_is_open(iop);

    /*
     * Verify you can change directory into this node.
     */

    if ( !iop->pathinfo.ops ) {
        rtems_set_errno_and_return_minus_one( ENOTSUP );
    }

    if ( !iop->pathinfo.ops->node_type_h ) {
        rtems_set_errno_and_return_minus_one( ENOTSUP );
    }

    if (  (*iop->pathinfo.ops->node_type_h)( &iop->pathinfo ) !=
            RTEMS_FILESYSTEM_DIRECTORY ) {
        rtems_set_errno_and_return_minus_one( ENOTDIR );
    }


    /*
     * FIXME : I feel there should be another call to
     *         actually take into account the extra reference to
     *         this node which we are making here. I can
     *         see the freenode interface but do not see
     *         allocnode node interface. It maybe node_type.
     *
     * FIXED:  T.Straumann: it is evaluate_path()
     *         but note the race condition. Threads who
     *         share their rtems_filesystem_current better
     *         be synchronized!
     */

    saved                    = rtems_filesystem_current;
    rtems_filesystem_current = iop->pathinfo;

    /* clone the current node */
    if (rtems_filesystem_evaluate_path(".", 1, 0, &loc, 0)) {
        /* cloning failed; restore original and bail out */
        rtems_filesystem_current = saved;
        return -1;
    }
    /* release the old one */
    rtems_filesystem_freenode( &saved );

    rtems_filesystem_current = loc;

    return 0;
}
Esempio n. 7
0
off_t lseek( int fd, off_t offset, int whence )
{
  rtems_libio_t *iop;

  rtems_libio_check_fd( fd );
  iop = rtems_libio_iop( fd );
  rtems_libio_check_is_open(iop);

  return (*iop->pathinfo.handlers->lseek_h)( iop, offset, whence );
}
Esempio n. 8
0
File: fsync.c Progetto: rtemss/rtems
int fsync(
  int     fd
)
{
  rtems_libio_t *iop;

  rtems_libio_check_fd( fd );
  iop = rtems_libio_iop( fd );
  rtems_libio_check_is_open(iop);

  /*
   *  Now process the fsync().
   */

  return (*iop->pathinfo.handlers->fsync_h)( iop );
}
Esempio n. 9
0
int fdatasync(
  int     fd
)
{
  rtems_libio_t *iop;

  rtems_libio_check_fd( fd );
  iop = rtems_libio_iop( fd );
  rtems_libio_check_is_open(iop);
  rtems_libio_check_permissions_with_error( iop, LIBIO_FLAGS_WRITE, EBADF );

  /*
   *  Now process the fdatasync().
   */

  return (*iop->pathinfo.handlers->fdatasync_h)( iop );
}
Esempio n. 10
0
/**
 *  POSIX 1003.1b 5.6.5 - Change Owner and Group of a File
 */
int fchown( int fd, uid_t owner, gid_t group )
{
  int rv;
  rtems_libio_t *iop;

  rtems_libio_check_fd( fd );
  iop = rtems_libio_iop( fd );
  rtems_libio_check_is_open(iop);

  rtems_filesystem_instance_lock( &iop->pathinfo );

  rv = rtems_filesystem_chown( &iop->pathinfo, owner, group );

  rtems_filesystem_instance_unlock( &iop->pathinfo );

  return rv;
}
Esempio n. 11
0
int close(
  int  fd
)
{
  rtems_libio_t      *iop;
  int                 rc;

  rtems_libio_check_fd(fd);
  iop = rtems_libio_iop(fd);
  rtems_libio_check_is_open(iop);

  iop->flags &= ~LIBIO_FLAGS_OPEN;

  rc = (*iop->pathinfo.handlers->close_h)( iop );

  rtems_libio_free( iop );

  return rc;
}
int fchmod(
  int       fd,
  mode_t    mode
)
{
  rtems_libio_t *iop;

  rtems_libio_check_fd( fd );
  iop = rtems_libio_iop( fd );
  rtems_libio_check_is_open(iop);

  /*
   *  Now process the fchmod().
   */
  if ( !iop->handlers->fchmod_h )
    rtems_set_errno_and_return_minus_one( ENOTSUP );

  return (*iop->pathinfo.handlers->fchmod_h)( &iop->pathinfo, mode );
}
Esempio n. 13
0
int close(
  int  fd
)
{
  rtems_libio_t      *iop;
  rtems_status_code   rc;

  rtems_libio_check_fd(fd);
  iop = rtems_libio_iop(fd);
  rtems_libio_check_is_open(iop);

  rc = RTEMS_SUCCESSFUL;
  if ( iop->handlers->close_h )
    rc = (*iop->handlers->close_h)( iop );

  rtems_filesystem_freenode( &iop->pathinfo );
  rtems_libio_free( iop );

  return rc;
}
Esempio n. 14
0
/**
 *  POSIX 1003.1b 6.4.1 - Read From a File
 */
ssize_t read(
  int         fd,
  void       *buffer,
  size_t      count
)
{
  rtems_libio_t *iop;

  rtems_libio_check_fd( fd );
  iop = rtems_libio_iop( fd );
  rtems_libio_check_is_open( iop );
  rtems_libio_check_buffer( buffer );
  rtems_libio_check_count( count );
  rtems_libio_check_permissions_with_error( iop, LIBIO_FLAGS_READ, EBADF );

  /*
   *  Now process the read().
   */
  return (*iop->pathinfo.handlers->read_h)( iop, buffer, count );
}
Esempio n. 15
0
int ftruncate( int fd, off_t length )
{
  int rv = 0;

  if ( length >= 0 ) {
    rtems_libio_t *iop;

    rtems_libio_check_fd( fd );
    iop = rtems_libio_iop( fd );
    rtems_libio_check_is_open( iop );
    rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );

    rv = (*iop->pathinfo.handlers->ftruncate_h)( iop, length );
  } else {
    errno = EINVAL;
    rv = -1;
  }

  return rv;
}
Esempio n. 16
0
int fchdir( int fd )
{
  int rv = 0;
  rtems_libio_t *iop;
  struct stat st;
  rtems_filesystem_location_info_t loc;

  st.st_mode = 0;
  st.st_uid = 0;
  st.st_gid = 0;

  rtems_libio_check_fd( fd );
  iop = rtems_libio_iop( fd );
  rtems_libio_check_is_open( iop );

  rtems_filesystem_instance_lock( &iop->pathinfo );
  rv = (*iop->pathinfo.handlers->fstat_h)( &iop->pathinfo, &st );
  if ( rv == 0 ) {
    bool access_ok = rtems_filesystem_check_access(
      RTEMS_FS_PERMS_EXEC,
      st.st_mode,
      st.st_uid,
      st.st_gid
    );

    if ( access_ok ) {
      rtems_filesystem_location_clone( &loc, &iop->pathinfo );
    } else {
      errno = EACCES;
      rv = -1;
    }
  }
  rtems_filesystem_instance_unlock( &iop->pathinfo );

  if ( rv == 0 ) {
    rv = rtems_filesystem_chdir( &loc );
  }

  return rv;
}
Esempio n. 17
0
long fpathconf(
  int   fd,
  int   name
)
{
  long                                    return_value;
  rtems_libio_t                          *iop;
  rtems_filesystem_limits_and_options_t  *the_limits;

  rtems_libio_check_fd(fd);
  iop = rtems_libio_iop(fd);
  rtems_libio_check_is_open(iop);
  rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ);

  /*
   *  Now process the information request.
   */

  the_limits = &iop->pathinfo.mt_entry->pathconf_limits_and_options;

  switch ( name ) {
    case _PC_LINK_MAX:
      return_value = the_limits->link_max;
      break;
    case _PC_MAX_CANON:
      return_value = the_limits->max_canon;
      break;
    case _PC_MAX_INPUT:
      return_value = the_limits->max_input;
      break;
    case _PC_NAME_MAX:
      return_value = the_limits->name_max;
      break;
    case _PC_PATH_MAX:
      return_value = the_limits->path_max;
      break;
    case _PC_PIPE_BUF:
      return_value = the_limits->pipe_buf;
      break;
    case _PC_CHOWN_RESTRICTED:
      return_value = the_limits->posix_chown_restrictions;
      break;
    case _PC_NO_TRUNC:
      return_value = the_limits->posix_no_trunc;
      break;
    case _PC_VDISABLE:
      return_value = the_limits->posix_vdisable;
      break;
    case _PC_ASYNC_IO:
      return_value = the_limits->posix_async_io;
      break;
    case _PC_PRIO_IO:
      return_value = the_limits->posix_prio_io;
      break;
    case _PC_SYNC_IO:
      return_value = the_limits->posix_sync_io;
      break;
    default:
      rtems_set_errno_and_return_minus_one( EINVAL );
      break;
  }

  return return_value;
}
Esempio n. 18
0
ssize_t writev(
  int                 fd,
  const struct iovec *iov,
  int                 iovcnt
)
{
  ssize_t        total;
  int            v;
  int            bytes;
  rtems_libio_t *iop;
  ssize_t        old;
  bool           all_zeros;

  rtems_libio_check_fd( fd );
  iop = rtems_libio_iop( fd );
  rtems_libio_check_is_open( iop );
  rtems_libio_check_permissions_with_error( iop, LIBIO_FLAGS_WRITE, EBADF );

  /*
   *  Argument validation on IO vector
   */
  if ( !iov )
    rtems_set_errno_and_return_minus_one( EINVAL );

  if ( iovcnt <= 0 )
    rtems_set_errno_and_return_minus_one( EINVAL );

  if ( iovcnt > IOV_MAX )
    rtems_set_errno_and_return_minus_one( EINVAL );

  if ( !iop->handlers->write_h )
    rtems_set_errno_and_return_minus_one( ENOTSUP );

  /*
   *  OpenGroup says that you are supposed to return EINVAL if the
   *  sum of the iov_len values in the iov array would overflow a
   *  ssize_t.
   *
   *  Also we would like to ensure that no IO is performed if there
   *  are obvious errors in the iovec.  So this extra loop ensures
   *  that we do not do anything if there is an argument error.
   *
   *  In addition,the OpenGroup specification says that if all the
   *  iov_len entries are zero, then the call has no effect.  So
   *  this loop does that check as well and sets "all-zero" appropriately.
   *  The variable "all_zero" is used as an early exit point before
   *  entering the write loop.
   */
  all_zeros = true;
  for ( old=0, total=0, v=0 ; v < iovcnt ; v++ ) {

    if ( !iov[v].iov_base )
      rtems_set_errno_and_return_minus_one( EINVAL );

    if ( iov[v].iov_len < 0 )
      rtems_set_errno_and_return_minus_one( EINVAL );

    if ( iov[v].iov_len )
      all_zeros = false;

    /* check for wrap */
    old    = total;
    total += iov[v].iov_len;
    if ( total < old || total > SSIZE_MAX )
      rtems_set_errno_and_return_minus_one( EINVAL );
  }

  /*
   * A writev with all zeros is supposed to have no effect per OpenGroup.
   */
  if ( all_zeros == true ) {
    return 0;
  }

  /*
   *  Now process the writev().
   */
  for ( total=0, v=0 ; v < iovcnt ; v++ ) {
    /* all zero lengths has no effect */
    if ( iov[v].iov_len == 0 )
      continue;

    bytes = (*iop->handlers->write_h)( iop, iov[v].iov_base, iov[v].iov_len );

    if ( bytes < 0 )
      return -1;

    if ( bytes > 0 ) {
      iop->offset += bytes;
      total       += bytes;
    }

    if (bytes != iov[ v ].iov_len)
      break;
  }

  return total;
}
Esempio n. 19
0
File: fcntl.c Progetto: AoLaD/rtems
static int vfcntl(
  int fd,
  int cmd,
  va_list ap
)
{
  rtems_libio_t *iop;
  int            fd2;
  int            flags;
  int            mask;
  int            ret = 0;

  rtems_libio_check_fd( fd );
  iop = rtems_libio_iop( fd );
  rtems_libio_check_is_open(iop);

  /*
   *  Now process the fcntl().
   */

  /*
   *  This switch should contain all the cases from POSIX.
   */

  switch ( cmd ) {
    case F_DUPFD:        /* dup */
      ret = duplicate_iop( iop );
      break;

    case F_DUP2FD:       /* dup2 */
      fd2 = va_arg( ap, int );
      ret = duplicate2_iop( iop, fd2 );
      break;

    case F_GETFD:        /* get f_flags */
      ret = ((iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC) != 0);
      break;

    case F_SETFD:        /* set f_flags */
      /*
       *  Interpret the third argument as the "close on exec()" flag.
       *  If this argument is 1, then the file descriptor is to be closed
       *  if a new process is exec()'ed.  Since RTEMS does not support
       *  processes, then we can ignore this one except to make
       *  F_GETFD work.
       */

      if ( va_arg( ap, int ) )
        iop->flags |= LIBIO_FLAGS_CLOSE_ON_EXEC;
      else
        iop->flags &= ~LIBIO_FLAGS_CLOSE_ON_EXEC;
      break;

    case F_GETFL:        /* more flags (cloexec) */
      ret = rtems_libio_to_fcntl_flags( iop->flags );
      break;

    case F_SETFL:
      flags = rtems_libio_fcntl_flags( va_arg( ap, int ) );
      mask = LIBIO_FLAGS_NO_DELAY | LIBIO_FLAGS_APPEND;

      /*
       *  XXX If we are turning on append, should we seek to the end?
       */

      iop->flags = (iop->flags & ~mask) | (flags & mask);
      break;

    case F_GETLK:
      errno = ENOTSUP;
      ret = -1;
      break;

    case F_SETLK:
      errno = ENOTSUP;
      ret = -1;
      break;

    case F_SETLKW:
      errno = ENOTSUP;
      ret = -1;
      break;

    case F_SETOWN:       /*  for sockets. */
      errno = ENOTSUP;
      ret = -1;
      break;

    case F_GETOWN:       /*  for sockets. */
      errno = ENOTSUP;
      ret = -1;
      break;

    default:
      errno = EINVAL;
      ret = -1;
      break;
  }
Esempio n. 20
0
ssize_t readv(
  int                 fd,
  const struct iovec *iov,
  int                 iovcnt
)
{
  ssize_t        total;
  int            v;
  int            bytes;
  rtems_libio_t *iop;
  bool           all_zeros;

  rtems_libio_check_fd( fd );
  iop = rtems_libio_iop( fd );
  rtems_libio_check_is_open( iop );
  rtems_libio_check_permissions_with_error( iop, LIBIO_FLAGS_READ, EBADF );

  /*
   *  Argument validation on IO vector
   */
  if ( !iov )
    rtems_set_errno_and_return_minus_one( EINVAL );

  if ( iovcnt <= 0 )
    rtems_set_errno_and_return_minus_one( EINVAL );

  if ( iovcnt > IOV_MAX )
    rtems_set_errno_and_return_minus_one( EINVAL );

  /*
   *  OpenGroup says that you are supposed to return EINVAL if the
   *  sum of the iov_len values in the iov array would overflow a
   *  ssize_t.
   *
   *  Also we would like to ensure that no IO is performed if there
   *  are obvious errors in the iovec.  So this extra loop ensures
   *  that we do not do anything if there is an argument error.
   */

  all_zeros = true;
  for ( total=0, v=0 ; v < iovcnt ; v++ ) {
    ssize_t old;

    /*
     *  iov[v].iov_len cannot be less than 0 because size_t is unsigned.
     *  So we only check for zero.
     */
    if ( iov[v].iov_base == 0 )
      rtems_set_errno_and_return_minus_one( EINVAL );

    /* check for wrap */
    old    = total;
    total += iov[v].iov_len;
    if ( total < old )
      rtems_set_errno_and_return_minus_one( EINVAL );

    if ( iov[v].iov_len )
      all_zeros = false;
  }

  /*
   *  A readv with all zeros logically has no effect.  Even though
   *  OpenGroup didn't address this case as they did with writev(),
   *  we will handle it the same way for symmetry.
   */
  if ( all_zeros == true ) {
    return 0;
  }

  /*
   *  Now process the readv().
   */
  for ( total=0, v=0 ; v < iovcnt ; v++ ) {
    bytes = (*iop->pathinfo.handlers->read_h)(
      iop,
      iov[v].iov_base,
      iov[v].iov_len
    );

    if ( bytes < 0 )
      return -1;

    if ( bytes > 0 ) {
      iop->offset += bytes;
      total       += bytes;
    }

    if (bytes != iov[ v ].iov_len)
      break;
  }

  return total;
}