Esempio n. 1
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;
}
Esempio n. 2
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;
}
Esempio n. 3
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;
}
Esempio n. 4
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;
}
Esempio n. 5
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;
}
Esempio n. 6
0
static int
rtems_rfs_shell_dir (rtems_rfs_file_system* fs, int argc, char *argv[])
{
  rtems_rfs_buffer_handle buffer;
  rtems_rfs_block_no      block;
  uint8_t*                data;
  bool                    state;
  int                     entry;
  int                     b;
  int                     rc;
  
  if (argc <= 1)
  {
    printf ("error: no block number provided\n");
    return 1;
  }

  block = strtoul (argv[1], 0, 0);

  rtems_rfs_shell_lock_rfs (fs);
  
  rc = rtems_rfs_group_bitmap_test (fs, false, block, &state);
  if (rc > 0)
  {
    rtems_rfs_shell_unlock_rfs (fs);
    printf ("error: testing block state: block=%" PRIu32 ": (%d) %s\n",
            block, rc, strerror (rc));
    return 1;
  }

  printf (" %5" PRIu32 ": block %s\n", block, state ? "allocated" : "free");

  rc = rtems_rfs_buffer_handle_open (fs, &buffer);
  if (rc > 0)
  {
    rtems_rfs_shell_unlock_rfs (fs);
    printf ("error: opening buffer handle: block=%" PRIu32 ": (%d) %s\n",
            block, rc, strerror (rc));
    return 1;
  }

  rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, true);
  if (rc > 0)
  {
    rtems_rfs_buffer_handle_close (fs, &buffer);
    rtems_rfs_shell_unlock_rfs (fs);
    printf ("error: requesting buffer handle: block=%" PRIu32 ": (%d) %s\n",
            block, rc, strerror (rc));
    return 1;
  }

  b = 0;
  entry = 1;
  data = rtems_rfs_buffer_data (&buffer);
  
  while (b < (rtems_rfs_fs_block_size (fs) - RTEMS_RFS_DIR_ENTRY_SIZE - 1))
  {
    rtems_rfs_ino eino;
    int           elength;
    int           length;
    int           c;

    eino    = rtems_rfs_dir_entry_ino (data);
    elength = rtems_rfs_dir_entry_length (data);
    
    if (elength == RTEMS_RFS_DIR_ENTRY_EMPTY)
      break;

    if ((elength < RTEMS_RFS_DIR_ENTRY_SIZE) ||
        (elength >= rtems_rfs_fs_max_name (fs)))
    {
      printf (" %5d: entry length appears corrupt: %d\n", entry, elength);
      break;
    }
    
    if ((eino < RTEMS_RFS_ROOT_INO) || (eino >= rtems_rfs_fs_inodes (fs)))
    {
      printf (" %5d: entry ino appears corrupt: ino=%" PRId32 "\n", entry, eino);
      break;
    }
    
    length = elength - RTEMS_RFS_DIR_ENTRY_SIZE;
    
    printf (" %5d: %04x inode=%-6" PRIu32 " hash=%08" PRIx32 " name[%03u]=",
            entry, b,
            rtems_rfs_dir_entry_ino (data),
            rtems_rfs_dir_entry_hash (data),
            length);

    if (length > 50)
      length = 50;
    
    for (c = 0; c < length; c++)
      printf ("%c", data[RTEMS_RFS_DIR_ENTRY_SIZE + c]);
    if (length < elength - RTEMS_RFS_DIR_ENTRY_SIZE)
      printf ("...");
    printf ("\n");

    b += elength;
    data += elength;
    entry++;
  }
  
  rc = rtems_rfs_buffer_handle_close (fs, &buffer);
  if (rc > 0)
  {
    rtems_rfs_shell_unlock_rfs (fs);
    printf ("error: closing buffer handle: block=%" PRIu32 ": (%d) %s\n",
            block, rc, strerror (rc));
    return 1;
  }
  
  rtems_rfs_shell_unlock_rfs (fs);
  
  return 0;
}