Beispiel #1
0
int unlink(
  const char *path
)
{
  int                               parentpathlen;
  const char                       *name;
  rtems_filesystem_location_info_t  parentloc;
  rtems_filesystem_location_info_t  loc;
  int                               i;
  int                               result;
  bool                              free_parentloc = false;

  /*
   * Get the node to be unlinked. Find the parent path first.
   */

  parentpathlen = rtems_filesystem_dirname ( path );

  if ( parentpathlen == 0 )
    rtems_filesystem_get_start_loc( path, &i, &parentloc );
  else {
    result = rtems_filesystem_evaluate_path( path, parentpathlen,
                                             RTEMS_LIBIO_PERMS_WRITE,
                                             &parentloc,
                                             false );
    if ( result != 0 )
      return -1;

    free_parentloc = true;
  }

  /*
   * Start from the parent to find the node that should be under it.
   */

  loc = parentloc;
  name = path + parentpathlen;
  name += rtems_filesystem_prefix_separators( name, strlen( name ) );

  result = rtems_filesystem_evaluate_relative_path( name , strlen( name ),
                                                    0, &loc, false );
  if ( result != 0 ) {
    if ( free_parentloc )
      rtems_filesystem_freenode( &parentloc );
    return -1;
  }

  if (  (*loc.ops->node_type_h)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY ) {
    rtems_filesystem_freenode( &loc );
    if ( free_parentloc )
      rtems_filesystem_freenode( &parentloc );
    rtems_set_errno_and_return_minus_one( EISDIR );
  }

  result = (*loc.ops->unlink_h)( &parentloc, &loc );

  rtems_filesystem_freenode( &loc );
  if ( free_parentloc )
    rtems_filesystem_freenode( &parentloc );

  return result;
}
Beispiel #2
0
/*
 *  IMFS_memfile_extend
 *
 *  This routine insures that the in-memory file is of the length
 *  specified.  If necessary, it will allocate memory blocks to
 *  extend the file.
 */
static int IMFS_memfile_extend(
   IMFS_memfile_t *memfile,
   bool            zero_fill,
   off_t           new_length
)
{
  unsigned int   block;
  unsigned int   new_blocks;
  unsigned int   old_blocks;
  unsigned int   offset;

  /*
   *  Perform internal consistency checks
   */
  IMFS_assert( memfile );

  /*
   *  Verify new file size is supported
   */
  if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE )
    rtems_set_errno_and_return_minus_one( EFBIG );

  /*
   *  Verify new file size is actually larger than current size
   */
  if ( new_length <= memfile->File.size )
    return 0;

  /*
   *  Calculate the number of range of blocks to allocate
   */
  new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK;
  old_blocks = memfile->File.size / IMFS_MEMFILE_BYTES_PER_BLOCK;
  offset = memfile->File.size - old_blocks * IMFS_MEMFILE_BYTES_PER_BLOCK;

  /*
   *  Now allocate each of those blocks.
   */
  for ( block=old_blocks ; block<=new_blocks ; block++ ) {
    if ( !IMFS_memfile_addblock( memfile, block ) ) {
       if ( zero_fill ) {
          size_t count = IMFS_MEMFILE_BYTES_PER_BLOCK - offset;
          block_p *block_ptr =
            IMFS_memfile_get_block_pointer( memfile, block, 0 );

          memset( &(*block_ptr) [offset], 0, count);
          offset = 0;
       }
    } else {
       for ( ; block>=old_blocks ; block-- ) {
         IMFS_memfile_remove_block( memfile, block );
       }
       rtems_set_errno_and_return_minus_one( ENOSPC );
    }
  }

  /*
   *  Set the new length of the file.
   */
  memfile->File.size = new_length;

  IMFS_mtime_ctime_update( &memfile->File.Node );

  return 0;
}
Beispiel #3
0
/* msdos_initialize_support --
 *     MSDOS filesystem initialization
 *
 * PARAMETERS:
 *     temp_mt_entry      - mount table entry
 *     op_table           - filesystem operations table
 *     file_handlers      - file operations table
 *     directory_handlers - directory operations table
 *
 * RETURNS:
 *     RC_OK and filled temp_mt_entry on success, or -1 if error occured
 *     (errno set apropriately)
 *
 */
int
msdos_initialize_support(
    rtems_filesystem_mount_table_entry_t    *temp_mt_entry,
    const rtems_filesystem_operations_table *op_table,
    const rtems_filesystem_file_handlers_r  *file_handlers,
    const rtems_filesystem_file_handlers_r  *directory_handlers,
    rtems_dosfs_convert_control             *converter
    )
{
    int                rc = RC_OK;
    rtems_status_code  sc = RTEMS_SUCCESSFUL;
    msdos_fs_info_t   *fs_info = NULL;
    fat_file_fd_t     *fat_fd = NULL;
    fat_dir_pos_t      root_pos;
    uint32_t           cl_buf_size;

    fs_info = (msdos_fs_info_t *)calloc(1, sizeof(msdos_fs_info_t));
    if (!fs_info)
        rtems_set_errno_and_return_minus_one(ENOMEM);

    temp_mt_entry->fs_info = fs_info;

    fs_info->converter = converter;

    rc = fat_init_volume_info(&fs_info->fat, temp_mt_entry->dev);
    if (rc != RC_OK)
    {
        free(fs_info);
        return rc;
    }

    fs_info->file_handlers      = file_handlers;
    fs_info->directory_handlers = directory_handlers;

    /*
     * open fat-file which correspondes to  root directory
     * (so inode number 0x00000010 is always used for root directory)
     */
    fat_dir_pos_init(&root_pos);
    root_pos.sname.cln = FAT_ROOTDIR_CLUSTER_NUM;
    rc = fat_file_open(&fs_info->fat, &root_pos, &fat_fd);
    if (rc != RC_OK)
    {
        fat_shutdown_drive(&fs_info->fat);
        free(fs_info);
        return rc;
    }

    /* again: unfortunately "fat-file" is just almost fat file :( */
    fat_fd->fat_file_type = FAT_DIRECTORY;
    fat_fd->size_limit = MSDOS_MAX_DIR_LENGTH;
    fat_fd->cln = fs_info->fat.vol.rdir_cl;

    fat_fd->map.file_cln = 0;
    fat_fd->map.disk_cln = fat_fd->cln;

    /* if we have FAT12/16 */
    if ( fat_fd->cln == 0 )
    {
        fat_fd->fat_file_size = fs_info->fat.vol.rdir_size;
        cl_buf_size = (fs_info->fat.vol.bpc > fs_info->fat.vol.rdir_size) ?
                      fs_info->fat.vol.bpc                                :
                      fs_info->fat.vol.rdir_size;
    }
    else
    {
        rc = fat_file_size(&fs_info->fat, fat_fd);
        if ( rc != RC_OK )
        {
            fat_file_close(&fs_info->fat, fat_fd);
            fat_shutdown_drive(&fs_info->fat);
            free(fs_info);
            return rc;
        }
        cl_buf_size = fs_info->fat.vol.bpc;
    }

    fs_info->cl_buf = (uint8_t *)calloc(cl_buf_size, sizeof(char));
    if (fs_info->cl_buf == NULL)
    {
        fat_file_close(&fs_info->fat, fat_fd);
        fat_shutdown_drive(&fs_info->fat);
        free(fs_info);
        rtems_set_errno_and_return_minus_one(ENOMEM);
    }

    sc = rtems_semaphore_create(3,
                                1,
                                RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY |
                                RTEMS_INHERIT_PRIORITY,
                                0,
                                &fs_info->vol_sema);
    if (sc != RTEMS_SUCCESSFUL)
    {
        fat_file_close(&fs_info->fat, fat_fd);
        fat_shutdown_drive(&fs_info->fat);
        free(fs_info->cl_buf);
        free(fs_info);
        rtems_set_errno_and_return_minus_one( EIO );
    }

    temp_mt_entry->mt_fs_root->location.node_access = fat_fd;
    temp_mt_entry->mt_fs_root->location.handlers = directory_handlers;
    temp_mt_entry->ops = op_table;

    return rc;
}
Beispiel #4
0
int rtems_filesystem_default_fsync_or_fdatasync(
  rtems_libio_t *iop
)
{
  rtems_set_errno_and_return_minus_one( EINVAL );
}
Beispiel #5
0
/*
 *  IMFS_memfile_write
 *
 *  This routine writes the specified data buffer into the in memory
 *  file pointed to by the_jnode.  The file is extended as needed.
 */
MEMFILE_STATIC ssize_t IMFS_memfile_write(
   IMFS_jnode_t          *the_jnode,
   off_t                  start,
   const unsigned char   *source,
   unsigned int           length
)
{
  block_p             *block_ptr;
  unsigned int         block;
  int                  status;
  unsigned int         my_length;
  unsigned int         to_copy = 0;
  unsigned int         last_byte;
  unsigned int         start_offset;
  int                  copied;
  const unsigned char *src;

  src = source;

  /*
   *  Perform internal consistency checks
   */
  IMFS_assert( source );
  IMFS_assert( the_jnode );
  IMFS_assert( IMFS_type( the_jnode ) == IMFS_MEMORY_FILE );

  my_length = length;
  /*
   *  If the last byte we are supposed to write is past the end of this
   *  in memory file, then extend the length.
   */

  last_byte = start + my_length;
  if ( last_byte > the_jnode->info.file.size ) {
    status = IMFS_memfile_extend( the_jnode, last_byte );
    if ( status )
      rtems_set_errno_and_return_minus_one( ENOSPC );
  }

  copied = 0;

  /*
   *  Three phases to the write:
   *    + possibly the last part of one block
   *    + all of zero of more blocks
   *    + possibly the first part of one block
   */

  /*
   *  Phase 1: possibly the last part of one block
   */
  start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
  block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
  if ( start_offset )  {
    to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
    if ( to_copy > my_length )
      to_copy = my_length;
    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
    if ( !block_ptr )
      return copied;
    #if 0
      fprintf(
        stderr,
        "write %d at %d in %d: %*s\n",
        to_copy,
        start_offset,
        block,
        to_copy,
        src
      );
    #endif
    memcpy( &(*block_ptr)[ start_offset ], src, to_copy );
    src += to_copy;
    block++;
    my_length -= to_copy;
    copied += to_copy;
  }

  /*
   *  Phase 2: all of zero of more blocks
   */

  to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
  while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
    if ( !block_ptr )
      return copied;
    #if 0
      fprintf(stdout, "write %d in %d: %*s\n", to_copy, block, to_copy, src );
    #endif
    memcpy( &(*block_ptr)[ 0 ], src, to_copy );
    src += to_copy;
    block++;
    my_length -= to_copy;
    copied += to_copy;
  }

  /*
   *  Phase 3: possibly the first part of one block
   */
  IMFS_assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );

  to_copy = my_length;
  if ( my_length ) {
    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
    if ( !block_ptr )
      return copied;
    #if 0
    fprintf(stdout, "write %d in %d: %*s\n", to_copy, block, to_copy, src );
    #endif
    memcpy( &(*block_ptr)[ 0 ], src, my_length );
    my_length = 0;
    copied += to_copy;
  }

  IMFS_mtime_ctime_update( the_jnode );

  return copied;
}
Beispiel #6
0
/**
 *  POSIX 1003.1b 4.5.2 - Get Process Times
 */
clock_t _times(
   struct tms  *ptms
)
{
  rtems_interval ticks;
  Thread_Control *executing;

  if ( !ptms )
    rtems_set_errno_and_return_minus_one( EFAULT );

  /*
   *  This call does not depend on TOD being initialized and can't fail.
   */

  ticks = rtems_clock_get_ticks_since_boot();

  /*
   *  RTEMS technically has no notion of system versus user time
   *  since there is no separation of OS from application tasks.
   *  But we can at least make a distinction between the number
   *  of ticks since boot and the number of ticks executed by this
   *  this thread.
   */

  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
    {
      Timestamp_Control per_tick;
      uint32_t          ticks_of_executing;
      uint32_t          fractional_ticks;

      _Timestamp_Set(
        &per_tick,
        rtems_configuration_get_microseconds_per_tick() /
            TOD_MICROSECONDS_PER_SECOND,
        (rtems_configuration_get_nanoseconds_per_tick() %
            TOD_NANOSECONDS_PER_SECOND)
      );

      _Thread_Disable_dispatch();
      executing = _Thread_Executing;
      _Thread_Update_cpu_time_used(
        executing,
        &_Thread_Time_of_last_context_switch
      );
      _Timestamp_Divide(
        &executing->cpu_time_used,
        &per_tick,
        &ticks_of_executing,
        &fractional_ticks
      );
      _Thread_Enable_dispatch();
      ptms->tms_utime = ticks_of_executing / 100;
    }
  #else
    executing = _Thread_Get_executing();
    ptms->tms_utime  = executing->cpu_time_used;
  #endif
  ptms->tms_stime  = ticks;
  ptms->tms_cutime = 0;
  ptms->tms_cstime = 0;

  return ticks;
} 
Beispiel #7
0
int _POSIX_Message_queue_Send_support(
  mqd_t               mqdes,
  const char         *msg_ptr,
  size_t              msg_len,
  unsigned int        msg_prio,
  bool                wait,
  Watchdog_Interval   timeout
)
{
  POSIX_Message_queue_Control    *the_mq;
  POSIX_Message_queue_Control_fd *the_mq_fd;
  Objects_Locations               location;
  CORE_message_queue_Status       msg_status;
  bool                            do_wait;

  /*
   * Validate the priority.
   * XXX - Do not validate msg_prio is not less than 0.
   */

  if ( msg_prio > MQ_PRIO_MAX )
    rtems_set_errno_and_return_minus_one( EINVAL );

  the_mq_fd = _POSIX_Message_queue_Get_fd( mqdes, &location );
  switch ( location ) {

    case OBJECTS_LOCAL:
      if ( (the_mq_fd->oflag & O_ACCMODE) == O_RDONLY ) {
        _Thread_Enable_dispatch();
        rtems_set_errno_and_return_minus_one( EBADF );
      }

      the_mq = the_mq_fd->Queue;

      /*
       *  A timed receive with a bad time will do a poll regardless.
       */
      if ( wait )
        do_wait = (the_mq_fd->oflag & O_NONBLOCK) ? false : true;
      else
        do_wait = wait;

      /*
       *  Now perform the actual message receive
       */
      msg_status = _CORE_message_queue_Submit(
        &the_mq->Message_queue,
        msg_ptr,
        msg_len,
        mqdes,      /* mqd_t is an object id */
        NULL,
        _POSIX_Message_queue_Priority_to_core( msg_prio ),
        do_wait,
        timeout    /* no timeout */
      );

      _Thread_Enable_dispatch();

      /*
       *  If we had to block, then this is where the task returns
       *  after it wakes up.  The returned status is correct for
       *  non-blocking operations but if we blocked, then we need
       *  to look at the status in our TCB.
       */

      if ( msg_status == CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT )
        msg_status = _Thread_Executing->Wait.return_code;

      if ( !msg_status )
        return msg_status;

      rtems_set_errno_and_return_minus_one(
        _POSIX_Message_queue_Translate_core_message_queue_return_code(
          msg_status
        )
      );

#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:
#endif
    case OBJECTS_ERROR:
      break;
  }

  rtems_set_errno_and_return_minus_one( EBADF );
}
ssize_t _POSIX_Message_queue_Receive_support(
  mqd_t               mqdes,
  char               *msg_ptr,
  size_t              msg_len,
  unsigned int       *msg_prio,
  bool                wait,
  Watchdog_Interval   timeout
)
{
  POSIX_Message_queue_Control     *the_mq;
  POSIX_Message_queue_Control_fd  *the_mq_fd;
  Objects_Locations                location;
  size_t                           length_out;
  bool                             do_wait;

  the_mq_fd = _POSIX_Message_queue_Get_fd( mqdes, &location );
  switch ( location ) {

    case OBJECTS_LOCAL:
      if ( (the_mq_fd->oflag & O_ACCMODE) == O_WRONLY ) {
        _Thread_Enable_dispatch();
        rtems_set_errno_and_return_minus_one( EBADF );
      }

      the_mq = the_mq_fd->Queue;

      if ( msg_len < the_mq->Message_queue.maximum_message_size ) {
        _Thread_Enable_dispatch();
        rtems_set_errno_and_return_minus_one( EMSGSIZE );
      }

      /*
       *  Now if something goes wrong, we return a "length" of -1
       *  to indicate an error.
       */

      length_out = -1;

      /*
       *  A timed receive with a bad time will do a poll regardless.
       */
      if ( wait )
        do_wait = (the_mq_fd->oflag & O_NONBLOCK) ? false : true;
      else
        do_wait = wait;

      /*
       *  Now perform the actual message receive
       */
      _CORE_message_queue_Seize(
        &the_mq->Message_queue,
        mqdes,
        msg_ptr,
        &length_out,
        do_wait,
        timeout
      );

      _Thread_Enable_dispatch();
      if (msg_prio) {
        *msg_prio = _POSIX_Message_queue_Priority_from_core(
             _Thread_Executing->Wait.count
          );
      }

      if ( !_Thread_Executing->Wait.return_code )
        return length_out;

      rtems_set_errno_and_return_minus_one(
        _POSIX_Message_queue_Translate_core_message_queue_return_code(
          _Thread_Executing->Wait.return_code
        )
      );

#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:
#endif
    case OBJECTS_ERROR:
      break;
  }

  rtems_set_errno_and_return_minus_one( EBADF );
}
Beispiel #9
0
/* msdos_creat_node --
 *     Create a new node. Determine if the name is a long name. If long we to
 *     scan the directory to create a short entry.
 *
 *



 *     If a new node is file, FAT 32 Bytes Directory
 *     Entry Structure is initialized, free space is found in parent
 *     directory and structure is written to the disk. In case of directory,
 *     all above steps present and also new cluster is allocated for a
 *     new directory and dot and dotdot nodes are created in alloceted cluster.
 *
 * PARAMETERS:
 *     parent_loc - parent (directory we are going to create node in)
 *     type       - new node type (file or directory)
 *     name       - new node name
 *     mode       - mode
 *     link_info  - fs_info of existing node for a pseudo "hard-link"
 *                  (see msdos_file.c, msdos_link for documentation)
 *
 * RETURNS:
 *     RC_OK on success, or -1 if error occured (errno set appropriately).
 *
 */
int
msdos_creat_node(const rtems_filesystem_location_info_t  *parent_loc,
                 msdos_node_type_t                        type,
                 const char                              *name,
                 int                                      name_len,
                 mode_t                                   mode,
                 const fat_file_fd_t                     *link_fd)
{
    int               rc = RC_OK;
    ssize_t           ret = 0;
    msdos_fs_info_t  *fs_info = parent_loc->mt_entry->fs_info;
    fat_file_fd_t    *parent_fat_fd = parent_loc->node_access;
    fat_file_fd_t    *fat_fd = NULL;
    time_t            time_ret = 0;
    uint16_t          time_val = 0;
    uint16_t          date = 0;
    fat_dir_pos_t     dir_pos;
    msdos_name_type_t name_type;
    char              short_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
    char              dot_dotdot[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2];
    char              link_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
    uint32_t          sec = 0;
    uint32_t          byte = 0;

    fat_dir_pos_init(&dir_pos);

    memset(short_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
    memset(dot_dotdot, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2);

    if (name_len > MSDOS_NAME_MAX_LFN_WITH_DOT) {
        rtems_set_errno_and_return_minus_one(ENAMETOOLONG);
    }

    name_type = msdos_long_to_short (name, name_len,
                                     MSDOS_DIR_NAME(short_node),
                                     MSDOS_NAME_MAX);
    if (name_type == MSDOS_NAME_INVALID) {
        rtems_set_errno_and_return_minus_one(EINVAL);
    }

    /* fill reserved field */
    *MSDOS_DIR_NT_RES(short_node) = MSDOS_RES_NT_VALUE;

    /* set up last write date and time */
    time_ret = time(NULL);
    if ( time_ret == -1 )
        return -1;

    msdos_date_unix2dos(time_ret, &date, &time_val);
    *MSDOS_DIR_CRT_TIME(short_node) = CT_LE_W(time_val);
    *MSDOS_DIR_CRT_DATE(short_node) = CT_LE_W(date);
    *MSDOS_DIR_WRITE_TIME(short_node) = CT_LE_W(time_val);
    *MSDOS_DIR_WRITE_DATE(short_node) = CT_LE_W(date);
    *MSDOS_DIR_LAST_ACCESS_DATE(short_node) = CT_LE_W(date);

    /* initialize directory/file size */
    *MSDOS_DIR_FILE_SIZE(short_node) = MSDOS_INIT_DIR_SIZE;

    if (type == MSDOS_DIRECTORY) {
      *MSDOS_DIR_ATTR(short_node) |= MSDOS_ATTR_DIRECTORY;
    }
    else if (type == MSDOS_HARD_LINK) {
      /*
       * when we establish a (temporary) hard link,
       * we must copy some information from the original
       * node to the newly created
       */
      /*
       * read the original directory entry
       */
      sec = fat_cluster_num_to_sector_num(&fs_info->fat,
                                          link_fd->dir_pos.sname.cln);
      sec += (link_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2);
      byte = (link_fd->dir_pos.sname.ofs & (fs_info->fat.vol.bps - 1));

      ret = _fat_block_read(&fs_info->fat,
                            sec, byte, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
                            link_node);
      if (ret < 0) {
          return -1;
      }
      /*
       * copy various attributes
       */
      *MSDOS_DIR_ATTR(short_node)          =*MSDOS_DIR_ATTR(link_node);
      *MSDOS_DIR_CRT_TIME_TENTH(short_node)=*MSDOS_DIR_CRT_TIME_TENTH(link_node);
      *MSDOS_DIR_CRT_TIME(short_node)      =*MSDOS_DIR_CRT_TIME(link_node);
      *MSDOS_DIR_CRT_DATE(short_node)      =*MSDOS_DIR_CRT_DATE(link_node);

      /*
       * copy/set "file size", "first cluster"
       */
      *MSDOS_DIR_FILE_SIZE(short_node)     =*MSDOS_DIR_FILE_SIZE(link_node);

      *MSDOS_DIR_FIRST_CLUSTER_LOW(short_node) =
           *MSDOS_DIR_FIRST_CLUSTER_LOW(link_node);
      *MSDOS_DIR_FIRST_CLUSTER_HI(short_node) =
           *MSDOS_DIR_FIRST_CLUSTER_HI(link_node);
      /*
       * set "archive bit" due to changes
       */
      *MSDOS_DIR_ATTR(short_node) |= MSDOS_ATTR_ARCHIVE;
    }
Beispiel #10
0
MEMFILE_STATIC ssize_t IMFS_memfile_read(
   IMFS_jnode_t    *the_jnode,
   off_t            start,
   unsigned char   *destination,
   unsigned int     length
)
{
  block_p             *block_ptr;
  unsigned int         block;
  unsigned int         my_length;
  unsigned int         to_copy = 0;
  unsigned int         last_byte;
  unsigned int         copied;
  unsigned int         start_offset;
  unsigned char       *dest;

  dest = destination;

  /*
   *  Perform internal consistency checks
   */

  assert( the_jnode );
  if ( !the_jnode )
    rtems_set_errno_and_return_minus_one( EIO );

  assert( the_jnode->type == IMFS_MEMORY_FILE ||
          the_jnode->type == IMFS_LINEAR_FILE );
  if ( the_jnode->type != IMFS_MEMORY_FILE &&
       the_jnode->type != IMFS_LINEAR_FILE )
    rtems_set_errno_and_return_minus_one( EIO );

  /*
   *  Error checks on arguments
   */

  assert( dest );
  if ( !dest )
    rtems_set_errno_and_return_minus_one( EINVAL );

  /*
   *  If there is nothing to read, then quick exit.
   */

  my_length = length;
  if ( !my_length )
    rtems_set_errno_and_return_minus_one( EINVAL );

  /*
   *  Linear files (as created from a tar file are easier to handle
   *  than block files).
   */
  if (the_jnode->type == IMFS_LINEAR_FILE) {
    unsigned char  *file_ptr;

    file_ptr = (unsigned char *)the_jnode->info.linearfile.direct;

    if (my_length > (the_jnode->info.linearfile.size - start))
      my_length = the_jnode->info.linearfile.size - start;

    memcpy(dest, &file_ptr[start], my_length);

    IMFS_update_atime( the_jnode );

    return my_length;
  }

  /*
   *  If the last byte we are supposed to read is past the end of this
   *  in memory file, then shorten the length to read.
   */

  last_byte = start + length;
  if ( last_byte > the_jnode->info.file.size )
    my_length = the_jnode->info.file.size - start;

  copied = 0;

  /*
   *  Three phases to the read:
   *    + possibly the last part of one block
   *    + all of zero of more blocks
   *    + possibly the first part of one block
   */

  /*
   *  Phase 1: possibly the last part of one block
   */

  start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
  block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
  if ( start_offset )  {
    to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
    if ( to_copy > my_length )
      to_copy = my_length;
    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
    assert( block_ptr );
    if ( !block_ptr )
      return copied;
    memcpy( dest, &(*block_ptr)[ start_offset ], to_copy );
    dest += to_copy;
    block++;
    my_length -= to_copy;
    copied += to_copy;
  }

  /*
   *  Phase 2: all of zero of more blocks
   */

  to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
  while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
    assert( block_ptr );
    if ( !block_ptr )
      return copied;
    memcpy( dest, &(*block_ptr)[ 0 ], to_copy );
    dest += to_copy;
    block++;
    my_length -= to_copy;
    copied += to_copy;
  }

  /*
   *  Phase 3: possibly the first part of one block
   */

  assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );

  if ( my_length ) {
    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
    assert( block_ptr );
    if ( !block_ptr )
      return copied;
    memcpy( dest, &(*block_ptr)[ 0 ], my_length );
    copied += my_length;
  }

  IMFS_update_atime( the_jnode );

  return copied;
}
Beispiel #11
0
int IMFS_memfile_remove(
 IMFS_jnode_t  *the_jnode
)
{
  IMFS_memfile_t  *info;
  int              i;
  int              j;
  unsigned int     to_free;
  block_p         *p;

  /*
   *  Perform internal consistency checks
   */

  assert( the_jnode );
  if ( !the_jnode )
    rtems_set_errno_and_return_minus_one( EIO );

  assert( the_jnode->type == IMFS_MEMORY_FILE );
  if ( the_jnode->type != IMFS_MEMORY_FILE )
    rtems_set_errno_and_return_minus_one( EIO );

  /*
   *  Eventually this could be set smarter at each call to
   *  memfile_free_blocks_in_table to greatly speed this up.
   */

  to_free = IMFS_MEMFILE_BLOCK_SLOTS;

  /*
   *  Now start freeing blocks in this order:
   *    + indirect
   *    + doubly indirect
   *    + triply indirect
   */

  info = &the_jnode->info.file;

  if ( info->indirect ) {
    memfile_free_blocks_in_table( &info->indirect, to_free );
  }

  if ( info->doubly_indirect ) {

    for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
      if ( info->doubly_indirect[i] ) {
        memfile_free_blocks_in_table(
         (block_p **)&info->doubly_indirect[i], to_free );
      }
    }
    memfile_free_blocks_in_table( &info->doubly_indirect, to_free );

  }

  if ( info->triply_indirect ) {
    for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
      p = (block_p *) info->triply_indirect[i];
      if ( !p )  /* ensure we have a valid pointer */
         break;
      for ( j=0 ; j<IMFS_MEMFILE_BLOCK_SLOTS ; j++ ) {
        if ( p[j] ) {
          memfile_free_blocks_in_table( (block_p **)&p[j], to_free);
        }
      }
      memfile_free_blocks_in_table(
        (block_p **)&info->triply_indirect[i], to_free );
    }
    memfile_free_blocks_in_table(
        (block_p **)&info->triply_indirect, to_free );
  }

  return 0;
}
Beispiel #12
0
int wait(
  int   *stat_loc
)
{
  rtems_set_errno_and_return_minus_one( ENOSYS );
}
Beispiel #13
0
/**
 * This method was initially added as part of porting NTP to RTEMS.
 *  It is a BSD compatability function and now is available on
 *  GNU/Linux.
 * 
 *  At one point there was a static variable named adjustment
 *  used by this implementation.  I don't see any reason for it
 *  to be here based upon the GNU/Linux documentation.
 */
int  adjtime(
  const struct timeval *delta,
  struct timeval *olddelta
)
{
  struct timespec ts;
  long   adjustment;

  /*
   * Simple validations
   */
  if ( !delta )
    rtems_set_errno_and_return_minus_one( EINVAL );

  if ( delta->tv_usec >= TOD_MICROSECONDS_PER_SECOND )
    rtems_set_errno_and_return_minus_one( EINVAL );

  if ( olddelta ) {
    olddelta->tv_sec  = 0;
    olddelta->tv_usec = 0;
  }

  /* convert delta to microseconds */
  adjustment  = (delta->tv_sec * TOD_MICROSECONDS_PER_SECOND);
  adjustment += delta->tv_usec;

  /* too small to account for */
  if ( adjustment < rtems_configuration_get_microseconds_per_tick() )
    return 0;

  /*
   * This prevents context switches while we are adjusting the TOD
   */

  _Thread_Disable_dispatch();

    _TOD_Get( &ts );

    ts.tv_sec  += delta->tv_sec;
    ts.tv_nsec += delta->tv_usec * TOD_NANOSECONDS_PER_MICROSECOND;

    /* if adjustment is too much positive */
    while ( ts.tv_nsec >= TOD_NANOSECONDS_PER_SECOND ) {
      ts.tv_nsec -= TOD_NANOSECONDS_PER_SECOND;
      ts.tv_sec++;
    }

    /* if adjustment is too much negative */
    while ( ts.tv_nsec <= (-1 * TOD_NANOSECONDS_PER_SECOND) ) {
      ts.tv_nsec += TOD_NANOSECONDS_PER_SECOND;
      ts.tv_sec--;
    }

    _TOD_Set( &ts );

  _Thread_Enable_dispatch();

  /* set the user's output */
  if ( olddelta )
    *olddelta = *delta;

  return 0;
}
Beispiel #14
0
int _POSIX_Message_queue_Create_support(
  const char                    *name_arg,
  size_t                         name_len,
  int                            pshared,
  struct mq_attr                *attr_ptr,
  POSIX_Message_queue_Control  **message_queue
)
{
  POSIX_Message_queue_Control   *the_mq;
  CORE_message_queue_Attributes *the_mq_attr;
  struct mq_attr                 attr;
  char                          *name;

  /* length of name has already been validated */

  _Thread_Disable_dispatch();

  /*
   *  There is no real basis for the default values.  They will work
   *  but were not compared against any existing implementation for
   *  compatibility.  See README.mqueue for an example program we
   *  think will print out the defaults.  Report anything you find with it.
   */
  if ( attr_ptr == NULL ) {
    attr.mq_maxmsg  = 10;
    attr.mq_msgsize = 16;
  } else {
    if ( attr_ptr->mq_maxmsg <= 0 ){
      _Thread_Enable_dispatch();
      rtems_set_errno_and_return_minus_one( EINVAL );
    }

    if ( attr_ptr->mq_msgsize <= 0 ){
      _Thread_Enable_dispatch();
      rtems_set_errno_and_return_minus_one( EINVAL );
    }

    attr = *attr_ptr;
  }

  the_mq = _POSIX_Message_queue_Allocate();
  if ( !the_mq ) {
    _Thread_Enable_dispatch();
    rtems_set_errno_and_return_minus_one( ENFILE );
  }

  /*
   * Make a copy of the user's string for name just in case it was
   * dynamically constructed.
   */
  name = _Workspace_String_duplicate( name_arg, name_len );
  if ( !name ) {
    _POSIX_Message_queue_Free( the_mq );
    _Thread_Enable_dispatch();
    rtems_set_errno_and_return_minus_one( ENOMEM );
  }

  the_mq->process_shared  = pshared;
  the_mq->named = true;
  the_mq->open_count = 1;
  the_mq->linked = true;

  /*
   *  NOTE: That thread blocking discipline should be based on the
   *  current scheduling policy.
   *
   *  Joel: Cite POSIX or OpenGroup on above statement so we can determine
   *        if it is a real requirement.
   */
  the_mq_attr = &the_mq->Message_queue.Attributes;
  the_mq_attr->discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO;

  if ( !_CORE_message_queue_Initialize(
           &the_mq->Message_queue,
           the_mq_attr,
           attr.mq_maxmsg,
           attr.mq_msgsize
      ) ) {

    _POSIX_Message_queue_Free( the_mq );
    _Workspace_Free(name);
    _Thread_Enable_dispatch();
    rtems_set_errno_and_return_minus_one( ENOSPC );
  }

  _Objects_Open_string(
    &_POSIX_Message_queue_Information,
    &the_mq->Object,
    name
  );

  *message_queue = the_mq;

  _Thread_Enable_dispatch();
  return 0;
}