예제 #1
0
int
rtems_rfs_inode_delete (rtems_rfs_file_system*  fs,
                        rtems_rfs_inode_handle* handle)
{
  int rc = 0;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_DELETE))
    printf("rtems-rfs: inode-delete: ino:%" PRIu32 " loaded:%s\n",
           rtems_rfs_inode_ino (handle),
           rtems_rfs_inode_is_loaded (handle) ? "yes" : "no");

  if (rtems_rfs_inode_is_loaded (handle))
  {
    rtems_rfs_block_map map;

    /*
     * Free the ino number.
     */
    rc = rtems_rfs_inode_free (fs, handle->ino);
    if (rc > 0)
      return rc;

    /*
     * Free the blocks the inode may have attached.
     */
    rc = rtems_rfs_block_map_open (fs, handle, &map);
    if (rc == 0)
    {
      int rrc;
      rrc = rtems_rfs_block_map_free_all (fs, &map);
      rc = rtems_rfs_block_map_close (fs, &map);
      if (rc > 0)
        rrc = rc;
      memset (handle->node, 0xff, RTEMS_RFS_INODE_SIZE);
      rtems_rfs_buffer_mark_dirty (&handle->buffer);
      /*
       * Do the release here to avoid the ctime field being set on a
       * close. Also if there loads is greater then one then other loads
       * active. Forcing the loads count to 0.
       */
      rc = rtems_rfs_buffer_handle_release (fs, &handle->buffer);
      handle->loads = 0;
      handle->node = NULL;
    }
  }
  return rc;
}
예제 #2
0
int
rtems_rfs_dir_empty (rtems_rfs_file_system*  fs,
                     rtems_rfs_inode_handle* dir)
{
  rtems_rfs_block_map     map;
  rtems_rfs_buffer_handle buffer;
  rtems_rfs_block_no      block;
  bool                    empty;
  int                     rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_READ))
    printf ("rtems-rfs: dir-empty: dir=%" PRId32 "\n", rtems_rfs_inode_ino (dir));

  empty = true;
  
  rc = rtems_rfs_block_map_open (fs, dir, &map);
  if (rc > 0)
    return rc;

  rc = rtems_rfs_block_map_seek (fs, &map, 0, &block);
  if (rc > 0)
  {
    rtems_rfs_block_map_close (fs, &map);
    return rc;
  }
  
  rc = rtems_rfs_buffer_handle_open (fs, &buffer);
  if (rc > 0)
  {
    rtems_rfs_block_map_close (fs, &map);
    return rc;
  }

  /*
   * Look for an empty entry and if this is the last block that is the end of
   * the directory.
   */
  while (empty)
  {
    uint8_t* entry;
    int      offset;
    
    rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, true);
    if (rc > 0)
      break;

    entry  = rtems_rfs_buffer_data (&buffer);
    offset = 0;
    
    while (offset < (rtems_rfs_fs_block_size (fs) - RTEMS_RFS_DIR_ENTRY_SIZE))
    {
      rtems_rfs_ino eino;
      int           elength;

      elength = rtems_rfs_dir_entry_length (entry);
      eino    = rtems_rfs_dir_entry_ino (entry);

      if (elength == RTEMS_RFS_DIR_ENTRY_EMPTY)
        break;

      if (rtems_rfs_dir_entry_valid (fs, elength, eino))
      {
        if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_EMPTY))
          printf ("rtems-rfs: dir-empty: "
                  "bad length or ino for ino %" PRIu32 ": %u/%" PRIu32 " @ %04x\n",
                  rtems_rfs_inode_ino (dir), elength, eino, offset);
        rc = EIO;
        break;
      }
        
      /*
       * Ignore the current (.) and parent (..) entries. Anything else means
       * the directory is not empty.
       */
      if (((elength != (RTEMS_RFS_DIR_ENTRY_SIZE + 1)) ||
           (entry[RTEMS_RFS_DIR_ENTRY_SIZE] != '.')) &&
          ((elength != (RTEMS_RFS_DIR_ENTRY_SIZE + 2)) ||
           (entry[RTEMS_RFS_DIR_ENTRY_SIZE] != '.') ||
           (entry[RTEMS_RFS_DIR_ENTRY_SIZE + 1] != '.')))
      {
        empty = false;
        break;
      }

      entry  += elength;
      offset += elength;
    }

    if (empty)
    {
      rc = rtems_rfs_block_map_next_block (fs, &map, &block);
      if (rc > 0)
      {
        if (rc == ENXIO)
          rc = 0;
        break;
      }
    }
  }

  if ((rc == 0) && !empty)
    rc = ENOTEMPTY;
  
  rtems_rfs_buffer_handle_close (fs, &buffer);
  rtems_rfs_block_map_close (fs, &map);
  return rc;
}
예제 #3
0
int
rtems_rfs_dir_lookup_ino (rtems_rfs_file_system*  fs,
                          rtems_rfs_inode_handle* inode,
                          const char*             name,
                          int                     length,
                          rtems_rfs_ino*          ino,
                          uint32_t*               offset)
{
  rtems_rfs_block_map     map;
  rtems_rfs_buffer_handle entries;
  int                     rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO))
  {
    int c;
    printf ("rtems-rfs: dir-lookup-ino: lookup ino: root=%" PRId32 ", path=",
            inode->ino);
    for (c = 0; c < length; c++)
      printf ("%c", name[c]);
    printf (", len=%d\n", length);
  }

  *ino = RTEMS_RFS_EMPTY_INO;
  *offset = 0;
  
  rc = rtems_rfs_block_map_open (fs, inode, &map);
  if (rc > 0)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO))
      printf ("rtems-rfs: dir-lookup-ino: map open failed for ino %" PRIu32 ": %d: %s",
              rtems_rfs_inode_ino (inode), rc, strerror (rc));
    return rc;
  }
  
  rc = rtems_rfs_buffer_handle_open (fs, &entries);
  if (rc > 0)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO))
      printf ("rtems-rfs: dir-lookup-ino: handle open failed for ino %" PRIu32 ": %d: %s",
              rtems_rfs_inode_ino (inode), rc, strerror (rc));
    rtems_rfs_block_map_close (fs, &map);
    return rc;
  }
  else
  {
    rtems_rfs_block_no block;
    uint32_t           hash;

    /*
     * Calculate the hash of the look up string.
     */
    hash = rtems_rfs_dir_hash (name, length);
  
    /*
     * Locate the first block. The map points to the start after open so just
     * seek 0. If an error the block will be 0.
     */
    rc = rtems_rfs_block_map_seek (fs, &map, 0, &block);
    if (rc > 0)
    {
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO))
        printf ("rtems-rfs: dir-lookup-ino: block map find failed: %d: %s\n",
                rc, strerror (rc));
      if (rc == ENXIO)
        rc = ENOENT;
      rtems_rfs_buffer_handle_close (fs, &entries);
      rtems_rfs_block_map_close (fs, &map);
      return rc;
    }
        
    while ((rc == 0) && block)
    {
      uint8_t* entry;
      
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO))
        printf ("rtems-rfs: dir-lookup-ino: block read, ino=%" PRIu32 " bno=%" PRId32 "\n",
                rtems_rfs_inode_ino (inode), map.bpos.bno);
      
      rc = rtems_rfs_buffer_handle_request (fs, &entries, block, true); 
      if (rc > 0)
      {
        if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO))
          printf ("rtems-rfs: dir-lookup-ino: block read, ino=%" PRIu32 " block=%" PRId32 ": %d: %s\n",
                  rtems_rfs_inode_ino (inode), block, rc, strerror (rc));
        break;
      }

      /*
       * Search the block to see if the name matches. A hash of 0xffff or 0x0
       * means the entry is empty.
       */

      entry = rtems_rfs_buffer_data (&entries);
      
      map.bpos.boff = 0;

      while (map.bpos.boff < (rtems_rfs_fs_block_size (fs) - RTEMS_RFS_DIR_ENTRY_SIZE))
      {
        uint32_t ehash;
        int      elength;
      
        ehash  = rtems_rfs_dir_entry_hash (entry);
        elength = rtems_rfs_dir_entry_length (entry);
        *ino = rtems_rfs_dir_entry_ino (entry);

        if (elength == RTEMS_RFS_DIR_ENTRY_EMPTY)
          break;
        
        if (rtems_rfs_dir_entry_valid (fs, elength, *ino))
        {
          if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO))
            printf ("rtems-rfs: dir-lookup-ino: "
                    "bad length or ino for ino %" PRIu32 ": %u/%" PRId32 " @ %04" PRIx32 "\n",
                    rtems_rfs_inode_ino (inode), elength, *ino, map.bpos.boff);
          rc = EIO;
          break;
        }
          
        if (ehash == hash)
        {
          if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO_CHECK))
            printf ("rtems-rfs: dir-lookup-ino: "
                    "checking entry for ino %" PRId32 ": bno=%04" PRIx32 "/off=%04" PRIx32
                    " length:%d ino:%" PRId32 "\n",
                    rtems_rfs_inode_ino (inode), map.bpos.bno, map.bpos.boff,
                    elength, rtems_rfs_dir_entry_ino (entry));

          if (memcmp (entry + RTEMS_RFS_DIR_ENTRY_SIZE, name, length) == 0)
          {
            *offset = rtems_rfs_block_map_pos (fs, &map);
            
            if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO_FOUND))
              printf ("rtems-rfs: dir-lookup-ino: "
                      "entry found in ino %" PRIu32 ", ino=%" PRIu32 " offset=%" PRIu32 "\n",
                      rtems_rfs_inode_ino (inode), *ino, *offset);

            rtems_rfs_buffer_handle_close (fs, &entries);
            rtems_rfs_block_map_close (fs, &map);
            return 0;
          }
        }

        map.bpos.boff += elength;
        entry += elength;
      }

      if (rc == 0)
      {
        rc = rtems_rfs_block_map_next_block (fs, &map, &block);
        if ((rc > 0) && (rc != ENXIO))
        {
          if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO))
            printf ("rtems-rfs: dir-lookup-ino: "
                    "block map next block failed in ino %" PRIu32 ": %d: %s\n",
                    rtems_rfs_inode_ino (inode), rc, strerror (rc));
        }
        if (rc == ENXIO)
          rc = ENOENT;
      }
    }

    if ((rc == 0) && (block == 0))
    {
      rc = EIO;
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO))
        printf ("rtems-rfs: dir-lookup-ino: block is 0 in ino %" PRIu32 ": %d: %s\n",
                rtems_rfs_inode_ino (inode), rc, strerror (rc));
    }
  }
  
  rtems_rfs_buffer_handle_close (fs, &entries);
  rtems_rfs_block_map_close (fs, &map);
  return rc;
}
예제 #4
0
int
rtems_rfs_dir_read (rtems_rfs_file_system*  fs,
                    rtems_rfs_inode_handle* dir,
                    rtems_rfs_pos_rel       offset,
                    struct dirent*          dirent,
                    size_t*                 length)
{
  rtems_rfs_block_map     map;
  rtems_rfs_buffer_handle buffer;
  rtems_rfs_block_no      block;
  int                     rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_READ))
    printf ("rtems-rfs: dir-read: dir=%" PRId32 " offset=%" PRId64 "\n",
            rtems_rfs_inode_ino (dir), offset);

  *length = 0;
  
  rc = rtems_rfs_block_map_open (fs, dir, &map);
  if (rc > 0)
    return rc;

  if (((rtems_rfs_fs_block_size (fs) -
        (offset % rtems_rfs_fs_block_size (fs))) <= RTEMS_RFS_DIR_ENTRY_SIZE))
    offset = (((offset / rtems_rfs_fs_block_size (fs)) + 1) *
              rtems_rfs_fs_block_size (fs));
  
  rc = rtems_rfs_block_map_seek (fs, &map, offset, &block);
  if (rc > 0)
  {
    if (rc == ENXIO)
      rc = ENOENT;
    rtems_rfs_block_map_close (fs, &map);
    return rc;
  }
  
  rc = rtems_rfs_buffer_handle_open (fs, &buffer);
  if (rc > 0)
  {
    rtems_rfs_block_map_close (fs, &map);
    return rc;
  }

  /*
   * Look for an empty entry and if this is the last block that is the end of
   * the directory.
   */
  while (rc == 0)
  {
    uint8_t*      entry;
    rtems_rfs_ino eino;
    int           elength;    
    int           remaining;
    
    rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, true);
    if (rc > 0)
    {
      rtems_rfs_buffer_handle_close (fs, &buffer);
      rtems_rfs_block_map_close (fs, &map);
      return rc;
    }

    entry  = rtems_rfs_buffer_data (&buffer);
    entry += map.bpos.boff;
    
    elength = rtems_rfs_dir_entry_length (entry);
    eino    = rtems_rfs_dir_entry_ino (entry);

    if (elength != RTEMS_RFS_DIR_ENTRY_EMPTY)
    {
      if (rtems_rfs_dir_entry_valid (fs, elength, eino))
      {
        if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_READ))
          printf ("rtems-rfs: dir-read: "
                  "bad length or ino for ino %" PRIu32 ": %u/%" PRId32 " @ %04" PRIx32 "\n",
                  rtems_rfs_inode_ino (dir), elength, eino, map.bpos.boff);
        rc = EIO;
        break;
      }
        
      memset (dirent, 0, sizeof (struct dirent));
      dirent->d_off = offset;
      dirent->d_reclen = sizeof (struct dirent);

      *length += elength;

      remaining = rtems_rfs_fs_block_size (fs) - (map.bpos.boff + elength);
      
      if (remaining <= RTEMS_RFS_DIR_ENTRY_SIZE)
        *length += remaining;
      
      elength -= RTEMS_RFS_DIR_ENTRY_SIZE;
      if (elength > NAME_MAX)
        elength = NAME_MAX;
      
      memcpy (dirent->d_name, entry + RTEMS_RFS_DIR_ENTRY_SIZE, elength);

      dirent->d_ino = rtems_rfs_dir_entry_ino (entry);
      dirent->d_namlen = elength;
      
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_READ))
        printf ("rtems-rfs: dir-read: found off:%" PRIdoff_t " ino:%ld name=%s\n",
                dirent->d_off, dirent->d_ino, dirent->d_name);
      break;
    }

    *length += rtems_rfs_fs_block_size (fs) - map.bpos.boff;
    
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_READ))
      printf ("rtems-rfs: dir-read: next block: off:%" PRId64 " length:%zd\n",
              offset, *length);
      
    rc = rtems_rfs_block_map_next_block (fs, &map, &block);
    if (rc == ENXIO)
      rc = ENOENT;
  }

  rtems_rfs_buffer_handle_close (fs, &buffer);
  rtems_rfs_block_map_close (fs, &map);
  return rc;
}
예제 #5
0
int
rtems_rfs_dir_del_entry (rtems_rfs_file_system*  fs,
                         rtems_rfs_inode_handle* dir,
                         rtems_rfs_ino           ino,
                         uint32_t                offset)
{  
  rtems_rfs_block_map     map;
  rtems_rfs_block_no      block;
  rtems_rfs_buffer_handle buffer;
  bool                    search;
  int                     rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_DEL_ENTRY))
    printf ("rtems-rfs: dir-del-entry: dir=%" PRId32 ", entry=%" PRId32 " offset=%" PRIu32 "\n",
            rtems_rfs_inode_ino (dir), ino, offset);

  rc = rtems_rfs_block_map_open (fs, dir, &map);
  if (rc > 0)
    return rc;

  rc = rtems_rfs_block_map_seek (fs, &map, offset, &block);
  if (rc > 0)
  {
    if (rc == ENXIO)
      rc = ENOENT;
    rtems_rfs_block_map_close (fs, &map);
    return rc;
  }

  rc = rtems_rfs_buffer_handle_open (fs, &buffer);
  if (rc > 0)
  {
    rtems_rfs_block_map_close (fs, &map);
    return rc;
  }

  /*
   * Only search if the offset is 0 else we are at that position.
   */
  search = offset ? false : true;

  while (rc == 0)
  {
    uint8_t* entry;
    int      eoffset;
    
    rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, true);
    if (rc > 0)
    {
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_DEL_ENTRY))
        printf ("rtems-rfs: dir-del-entry: "
                "block buffer req failed for ino %" PRIu32 ": %d: %s\n",
                rtems_rfs_inode_ino (dir), rc, strerror (rc));
      break;
    }

    /*
     * If we are searching start at the beginning of the block. If not searching
     * skip to the offset in the block.
     */
    if (search)
      eoffset = 0;
    else
      eoffset = offset % rtems_rfs_fs_block_size (fs);
    
    entry = rtems_rfs_buffer_data (&buffer) + eoffset;
    
    while (eoffset < (rtems_rfs_fs_block_size (fs) - RTEMS_RFS_DIR_ENTRY_SIZE))
    {
      rtems_rfs_ino eino;
      int           elength;

      elength = rtems_rfs_dir_entry_length (entry);
      eino    = rtems_rfs_dir_entry_ino (entry);

      if (elength == RTEMS_RFS_DIR_ENTRY_EMPTY)
        break;
      
      if (rtems_rfs_dir_entry_valid (fs, elength, eino))
      {
        if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_DEL_ENTRY))
          printf ("rtems-rfs: dir-del-entry: "
                  "bad length or ino for ino %" PRIu32 ": %u/%" PRId32
                  " @ %" PRIu32 ".%04x\n",
                  rtems_rfs_inode_ino (dir), elength, eino, block, eoffset);
        rc = EIO;
        break;
      }

      if (ino == rtems_rfs_dir_entry_ino (entry))
      {
        uint32_t remaining;
        remaining = rtems_rfs_fs_block_size (fs) - (eoffset + elength);
        memmove (entry, entry + elength, remaining);
        memset (entry + remaining, 0xff, elength);

        /*
         * If the remainder of the block is empty and this is the start of the
         * block and it is the last block in the map shrink the map.
         *
         * @note We could check again to see if the new end block in the map is
         *       also empty. This way we could clean up an empty directory.
         */
        elength = rtems_rfs_dir_entry_length (entry);

        if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_DEL_ENTRY))
          printf ("rtems-rfs: dir-del-entry: "
                  "last block free for ino %" PRIu32 ": elength=%i block=%" PRIu32
                  " offset=%d last=%s\n",
                  ino, elength, block, eoffset,
                  rtems_rfs_block_map_last (&map) ? "yes" : "no");

        if ((elength == RTEMS_RFS_DIR_ENTRY_EMPTY) &&
            (eoffset == 0) && rtems_rfs_block_map_last (&map))
        {
          rc = rtems_rfs_block_map_shrink (fs, &map, 1);
          if (rc > 0)
          {
            if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_DEL_ENTRY))
              printf ("rtems-rfs: dir-del-entry: "
                      "block map shrink failed for ino %" PRIu32 ": %d: %s\n",
                      rtems_rfs_inode_ino (dir), rc, strerror (rc));
          }
        }
        
        rtems_rfs_buffer_mark_dirty (&buffer);
        rtems_rfs_buffer_handle_close (fs, &buffer);
        rtems_rfs_block_map_close (fs, &map);
        return 0;
      }

      if (!search)
      {
        rc = EIO;
        break;
      }
      
      entry   += elength;
      eoffset += elength;
    }

    if (rc == 0)
    {
      rc = rtems_rfs_block_map_next_block (fs, &map, &block);
      if (rc == ENXIO)
        rc = ENOENT;
    }
  }
  
  rtems_rfs_buffer_handle_close (fs, &buffer);
  rtems_rfs_block_map_close (fs, &map);
  return rc;
}
예제 #6
0
int
rtems_rfs_dir_add_entry (rtems_rfs_file_system*  fs,
                         rtems_rfs_inode_handle* dir,
                         const char*             name,
                         size_t                  length,
                         rtems_rfs_ino           ino)
{
  rtems_rfs_block_map     map;
  rtems_rfs_block_pos     bpos;
  rtems_rfs_buffer_handle buffer;
  int                     rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_ADD_ENTRY))
  {
    int c;
    printf ("rtems-rfs: dir-add-entry: dir=%" PRId32 ", name=",
            rtems_rfs_inode_ino (dir));
    for (c = 0; c < length; c++)
      printf ("%c", name[c]);
    printf (", len=%zd\n", length);
  }
        
  rc = rtems_rfs_block_map_open (fs, dir, &map);
  if (rc > 0)
    return rc;

  rc = rtems_rfs_buffer_handle_open (fs, &buffer);
  if (rc > 0)
  {
    rtems_rfs_block_map_close (fs, &map);
    return rc;
  }
  
  /*
   * Search the map from the beginning to find any empty space.
   */
  rtems_rfs_block_set_bpos_zero (&bpos);
  
  while (true)
  {
    rtems_rfs_block_no block;
    uint8_t*           entry;
    int                offset;
    bool               read = true;
    
    /*
     * Locate the first block. If an error the block will be 0. If the map is
     * empty which happens when creating a directory and adding the first entry
     * the seek will return ENXIO. In this case we need to grow the directory.
     */
    rc = rtems_rfs_block_map_find (fs, &map, &bpos, &block);
    if (rc > 0)
    {
      if (rc != ENXIO)
      {
        if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_ADD_ENTRY))
          printf ("rtems-rfs: dir-add-entry: "
                  "block map find failed for ino %" PRIu32 ": %d: %s\n",
                  rtems_rfs_inode_ino (dir), rc, strerror (rc));
        break;
      }

      /*
       * We have reached the end of the directory so add a block.
       */
      rc = rtems_rfs_block_map_grow (fs, &map, 1, &block);
      if (rc > 0)
      {
        if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_ADD_ENTRY))
          printf ("rtems-rfs: dir-add-entry: "
                  "block map grow failed for ino %" PRIu32 ": %d: %s\n",
                  rtems_rfs_inode_ino (dir), rc, strerror (rc));
        break;
      }

      read = false;
    }

    bpos.bno++;
    
    rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, read);
    if (rc > 0)
    {
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_ADD_ENTRY))
        printf ("rtems-rfs: dir-add-entry: "
                "block buffer req failed for ino %" PRIu32 ": %d: %s\n",
                rtems_rfs_inode_ino (dir), rc, strerror (rc));
      break;
    }
    
    entry  = rtems_rfs_buffer_data (&buffer);
    
    if (!read)
      memset (entry, 0xff, rtems_rfs_fs_block_size (fs));

    offset = 0;
    
    while (offset < (rtems_rfs_fs_block_size (fs) - RTEMS_RFS_DIR_ENTRY_SIZE))
    {
      rtems_rfs_ino eino;
      int           elength;

      elength = rtems_rfs_dir_entry_length (entry);
      eino    = rtems_rfs_dir_entry_ino (entry);

      if (elength == RTEMS_RFS_DIR_ENTRY_EMPTY)
      {
        if ((length + RTEMS_RFS_DIR_ENTRY_SIZE) <
            (rtems_rfs_fs_block_size (fs) - offset))
        {
          uint32_t hash;
          hash = rtems_rfs_dir_hash (name, length);
          rtems_rfs_dir_set_entry_hash (entry, hash);
          rtems_rfs_dir_set_entry_ino (entry, ino);
          rtems_rfs_dir_set_entry_length (entry,
                                          RTEMS_RFS_DIR_ENTRY_SIZE + length);
          memcpy (entry + RTEMS_RFS_DIR_ENTRY_SIZE, name, length);
          rtems_rfs_buffer_mark_dirty (&buffer);
          rtems_rfs_buffer_handle_close (fs, &buffer);
          rtems_rfs_block_map_close (fs, &map);
          return 0;
        }

        break;
      }
      
      if (rtems_rfs_dir_entry_valid (fs, elength, eino))
      {
        if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_ADD_ENTRY))
          printf ("rtems-rfs: dir-add-entry: "
                  "bad length or ino for ino %" PRIu32 ": %u/%" PRId32 " @ %04x\n",
                  rtems_rfs_inode_ino (dir), elength, eino, offset);
        rtems_rfs_buffer_handle_close (fs, &buffer);
        rtems_rfs_block_map_close (fs, &map);
        return EIO;
      }
        
      entry  += elength;
      offset += elength;
    }
  }
  
  rtems_rfs_buffer_handle_close (fs, &buffer);
  rtems_rfs_block_map_close (fs, &map);
  return rc;
}
int
rtems_rfs_file_close (rtems_rfs_file_system* fs,
                      rtems_rfs_file_handle* handle)
{
  int rrc;
  int rc;

  rrc = 0;
  
  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_CLOSE))
    printf ("rtems-rfs: file-close: entry: ino=%" PRId32 "\n",
            handle->shared->inode.ino);

  if (handle->shared->references > 0)
    handle->shared->references--;

  if (handle->shared->references == 0)
  {
    if (!rtems_rfs_inode_is_loaded (&handle->shared->inode))
      rrc = rtems_rfs_inode_load (fs, &handle->shared->inode);

    if (rrc == 0)
    {
      /*
       * @todo This could be clever and only update if different.
       */
      rtems_rfs_inode_set_atime (&handle->shared->inode,
                                 handle->shared->atime);
      rtems_rfs_inode_set_mtime (&handle->shared->inode,
                                 handle->shared->mtime);
      rtems_rfs_inode_set_ctime (&handle->shared->inode,
                                 handle->shared->ctime);
      if (!rtems_rfs_block_size_equal (&handle->shared->size,
                                       &handle->shared->map.size))
        rtems_rfs_block_map_set_size (&handle->shared->map,
                                      &handle->shared->size);
    }
    
    rc = rtems_rfs_block_map_close (fs, &handle->shared->map);
    if (rc > 0)
    {
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_CLOSE))
        printf ("rtems-rfs: file-close: map close error: ino=%" PRId32 ": %d: %s\n",
                handle->shared->inode.ino, rc, strerror (rc));
      if (rrc == 0)
        rrc = rc;
    }
    
    rc = rtems_rfs_inode_close (fs, &handle->shared->inode);
    if (rc > 0)
    {
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_CLOSE))
        printf ("rtems-rfs: file-close: inode close error: ino=%" PRId32 ": %d: %s\n",
                handle->shared->inode.ino, rc, strerror (rc));
      if (rrc == 0)
        rrc = rc;
    }
    
    rtems_chain_extract (&handle->shared->link);
    free (handle->shared);
  }

  rc = rtems_rfs_buffer_handle_close (fs, &handle->buffer);
  if ((rrc == 0) && (rc > 0))
    rrc = rc;
  
  if (rrc > 0)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_CLOSE))
      printf ("rtems-rfs: file-close: result: %d: %s\n", rrc, strerror (rrc));
  }

  free (handle);
  
  return rrc;
}
예제 #8
0
int
rtems_rfs_symlink_read (rtems_rfs_file_system* fs,
                        rtems_rfs_ino          link,
                        char*                  path,
                        size_t                 size,
                        size_t*                length)
{
  rtems_rfs_inode_handle inode;
  int                    rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_SYMLINK_READ))
    printf ("rtems-rfs: symlink-read: link:%" PRIu32 "\n", link);

  rc = rtems_rfs_inode_open (fs, link, &inode, true);
  if (rc)
    return rc;

  if (!RTEMS_RFS_S_ISLNK (rtems_rfs_inode_get_mode (&inode)))
  {
    rtems_rfs_inode_close (fs, &inode);
    return EINVAL;
  }

  *length = rtems_rfs_inode_get_block_offset (&inode);

  if (size < *length)
  {
    *length = size;
  }

  if (rtems_rfs_inode_get_block_count (&inode) == 0)
  {
    memcpy (path, inode.node->data.name, *length);
  }
  else
  {
    rtems_rfs_block_map     map;
    rtems_rfs_block_no      block;
    rtems_rfs_buffer_handle buffer;
    char*                   data;

    rc = rtems_rfs_block_map_open (fs, &inode, &map);
    if (rc > 0)
    {
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    rc = rtems_rfs_block_map_seek (fs, &map, 0, &block);
    if (rc > 0)
    {
      rtems_rfs_block_map_close (fs, &map);
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    rc = rtems_rfs_buffer_handle_open (fs, &buffer);
    if (rc > 0)
    {
      rtems_rfs_block_map_close (fs, &map);
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, false);
    if (rc > 0)
    {
      rtems_rfs_block_map_close (fs, &map);
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    data = rtems_rfs_buffer_data (&buffer);
    memcpy (path, data, *length);

    rc = rtems_rfs_buffer_handle_close (fs, &buffer);
    if (rc > 0)
    {
      rtems_rfs_block_map_close (fs, &map);
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    rc = rtems_rfs_block_map_close (fs, &map);
    if (rc > 0)
    {
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }
  }

  rc = rtems_rfs_inode_close (fs, &inode);

  return rc;
}
예제 #9
0
int
rtems_rfs_symlink (rtems_rfs_file_system* fs,
                   const char*            name,
                   int                    length,
                   const char*            link,
                   int                    link_length,
                   uid_t                  uid,
                   gid_t                  gid,
                   rtems_rfs_ino          parent)
{
  rtems_rfs_inode_handle inode;
  rtems_rfs_ino          ino;
  int                    rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_SYMLINK))
  {
    int c;
    printf ("rtems-rfs: symlink: parent:%" PRIu32 " name:", parent);
    for (c = 0; c < length; c++)
      printf ("%c", name[c]);
    printf (" link:");
    for (c = 0; c < link_length; c++)
      printf ("%c", link[c]);
  }

  if (link_length >= rtems_rfs_fs_block_size (fs))
    return ENAMETOOLONG;

  rc = rtems_rfs_inode_create (fs, parent, name, strlen (name),
                               RTEMS_RFS_S_SYMLINK,
                               1, uid, gid, &ino);
  if (rc > 0)
    return rc;

  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
  if (rc > 0)
    return rc;

  /*
   * If the link length is less than the length of data union in the inode
   * place the link into the data area else allocate a block and write the link
   * to that.
   */
  if (link_length < RTEMS_RFS_INODE_DATA_NAME_SIZE)
  {
    memset (inode.node->data.name, 0, RTEMS_RFS_INODE_DATA_NAME_SIZE);
    memcpy (inode.node->data.name, link, link_length);
    rtems_rfs_inode_set_block_count (&inode, 0);
  }
  else
  {
    rtems_rfs_block_map     map;
    rtems_rfs_block_no      block;
    rtems_rfs_buffer_handle buffer;
    uint8_t*                data;

    rc = rtems_rfs_block_map_open (fs, &inode, &map);
    if (rc > 0)
    {
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    rc = rtems_rfs_block_map_grow (fs, &map, 1, &block);
    if (rc > 0)
    {
      rtems_rfs_block_map_close (fs, &map);
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    rc = rtems_rfs_buffer_handle_open (fs, &buffer);
    if (rc > 0)
    {
      rtems_rfs_block_map_close (fs, &map);
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, false);
    if (rc > 0)
    {
      rtems_rfs_block_map_close (fs, &map);
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    data = rtems_rfs_buffer_data (&buffer);

    memset (data, 0xff, rtems_rfs_fs_block_size (fs));
    memcpy (data, link, link_length);

    rc = rtems_rfs_buffer_handle_close (fs, &buffer);
    if (rc > 0)
    {
      rtems_rfs_block_map_close (fs, &map);
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }

    rc = rtems_rfs_block_map_close (fs, &map);
    if (rc > 0)
    {
      rtems_rfs_inode_close (fs, &inode);
      return rc;
    }
  }

  rtems_rfs_inode_set_block_offset (&inode, link_length);

  rc = rtems_rfs_inode_close (fs, &inode);

  return rc;
}