예제 #1
0
int nxffs_rdblkhdr(FAR struct nxffs_volume_s *volume, off_t offset,
                   FAR uint16_t *datlen)
{
  struct nxffs_data_s blkhdr;
  uint32_t ecrc;
  uint32_t crc;
  uint16_t doffset;
  uint16_t dlen;
  int ret;

  /* Make sure that the block containing the data block header is in the cache */

  nxffs_ioseek(volume, offset);
  ret = nxffs_rdcache(volume, volume->ioblock);
  if (ret < 0)
    {
      fdbg("ERROR: Failed to read data into cache: %d\n", ret);
      return ret;
    }

  /* Read the header at the FLASH offset */

  doffset = volume->iooffset;
  memcpy(&blkhdr, &volume->cache[doffset], SIZEOF_NXFFS_DATA_HDR);

  /* Extract the data length */

  dlen = nxffs_rdle16(blkhdr.datlen);

  /* Get the offset to the beginning of the data */

  doffset += SIZEOF_NXFFS_DATA_HDR;

  /* Make sure that all of the data fits within the block */

  if ((uint32_t)doffset + (uint32_t)dlen > (uint32_t)volume->geo.blocksize)
    {
      fdbg("ERROR: Data length=%d is unreasonable at offset=%d\n", dlen, doffset);
      return -EIO;
    }

  /* Extract the expected CRC and calculate the CRC of the data block */

  ecrc = nxffs_rdle32(blkhdr.crc);

  nxffs_wrle32(blkhdr.crc, 0);
  crc = crc32((FAR const uint8_t *)&blkhdr, SIZEOF_NXFFS_DATA_HDR);
  crc = crc32part(&volume->cache[doffset], dlen, crc);

  if (crc != ecrc)
    {
      fdbg("ERROR: CRC failure\n");
      return -EIO;
    }

  /* Looks good! Return the data length and success */

  *datlen = dlen;
  return OK;
}
예제 #2
0
static inline ssize_t nxffs_analyzedata(FAR struct nxffs_blkinfo_s *blkinfo,
                                        int offset)
{
  struct nxffs_data_s dathdr;
  uint32_t ecrc;
  uint16_t datlen;
  uint32_t crc;

  /* Copy and unpack the data block header */

  memcpy(&dathdr, &blkinfo->buffer[offset], SIZEOF_NXFFS_DATA_HDR);
  ecrc   = nxffs_rdle32(dathdr.crc);
  datlen = nxffs_rdle16(dathdr.datlen);

  /* Sanity checks */

  if (offset + SIZEOF_NXFFS_DATA_HDR + datlen > blkinfo->geo.blocksize)
    {
      /* Data does not fit in within the block, this can't be a data block */

      return ERROR;
    }

  /* Calculate the CRC */

  nxffs_wrle32(dathdr.crc, 0);

  crc = crc32((FAR const uint8_t *)&dathdr, SIZEOF_NXFFS_DATA_HDR);
  crc = crc32part(&blkinfo->buffer[offset + SIZEOF_NXFFS_DATA_HDR], datlen, crc);

  if (crc != ecrc)
   {
      syslog(LOG_NOTICE, g_format,
             blkinfo->block, offset, "DATA ", "CRC BAD", datlen);
      return ERROR;
   }

  /* If must be a good header */

  if (blkinfo->verbose)
    {
      syslog(LOG_NOTICE, g_format,
             blkinfo->block, offset, "DATA ", "OK     ", datlen);
    }

  return SIZEOF_NXFFS_DATA_HDR + datlen;
}
예제 #3
0
static inline ssize_t nxffs_analyzeinode(FAR struct nxffs_blkinfo_s *blkinfo,
                                         int offset)
{
  FAR struct nxffs_inode_s inode;
  off_t nextblock;
  uint8_t  state;
  uint32_t noffs;
  uint32_t doffs;
  uint32_t utc;
  uint32_t ecrc;
  uint32_t datlen;
  uint32_t crc;
  size_t   spaceleft;

  /* Verify that there is space for an inode header remaining in the block */

  if (offset + SIZEOF_NXFFS_INODE_HDR > blkinfo->geo.blocksize)
    {
      /* No.. then this can't be an inode header */

      return ERROR;
    }

  /* Unpack the header */

  memcpy(&inode, &blkinfo->buffer[offset], SIZEOF_NXFFS_INODE_HDR);
  noffs  = nxffs_rdle32(inode.noffs);
  doffs  = nxffs_rdle32(inode.doffs);
  utc    = nxffs_rdle32(inode.utc);
  ecrc   = nxffs_rdle32(inode.crc);
  datlen = nxffs_rdle32(inode.datlen);

  /* Misc. sanity checks */

  if (noffs < blkinfo->offset + offset + SIZEOF_NXFFS_BLOCK_HDR)
    {
      /* The name begins before the inode header.  This can't can't be
       * a real inode header (or it is a corrupted one).
       */

      return ERROR;
    }
  

  /* Can we verify the inode?  We need to have the inode name in the same
   * block to do that (or get access to the next block)
   */

  if (doffs < blkinfo->offset + offset + SIZEOF_NXFFS_BLOCK_HDR)
    {
      /* The first data block begins before the inode header.  This can't can't
       * be a real inode header (or it is a corrupted one).
       */

      return ERROR;
    }

   spaceleft = (blkinfo->nblocks - blkinfo->block) * blkinfo->geo.blocksize;
   spaceleft -= (offset + SIZEOF_NXFFS_BLOCK_HDR);
   if (datlen > spaceleft)
     {
       /* The data length is greater than what would fit in the rest of FLASH
        * (even ignoring block and data header sizes.
        */

       return ERROR;
     }

  /* The name begins after the inode header.  Does it begin in this block? */

  nextblock = blkinfo->offset + blkinfo->geo.blocksize;
  if (noffs > nextblock)
    {
      /* Not than we cannot verify the inode header */

      if (blkinfo->verbose)
        {
          fdbg(g_format, blkinfo->block, offset, "INODE", "UNVERFD", datlen);
        }
      return ERROR;
    }

  /* The name begins in this block.  Does it also end in this block? */

  if (noffs + inode.namlen > nextblock)
    {
      /* No..  Assume that this is not an inode. */

       return ERROR;
    }

  /* Calculate the CRC */

  state       = inode.state;
  inode.state = CONFIG_NXFFS_ERASEDSTATE;
  nxffs_wrle32(inode.crc, 0);

  crc = crc32((FAR const uint8_t *)&inode, SIZEOF_NXFFS_INODE_HDR);
  crc = crc32part(&blkinfo->buffer[noffs - blkinfo->offset], inode.namlen, crc);

  if (crc != ecrc)
   {
      fdbg(g_format, blkinfo->block, offset, "INODE", "CRC BAD", datlen);
      return ERROR;
   }

  /* If must be a good header */

  if (state == INODE_STATE_FILE)
    {
      if (blkinfo->verbose)
        {
          fdbg(g_format, blkinfo->block, offset, "INODE", "OK     ", datlen);
        }
    }
  else if (state == INODE_STATE_DELETED)
    {
      if (blkinfo->verbose)
        {
          fdbg(g_format, blkinfo->block, offset, "INODE", "DELETED", datlen);
        }
    }
  else
    {
      fdbg(g_format, blkinfo->block, offset, "INODE", "CORRUPT", datlen);
    }

  /* Return the block-relative offset to the next byte after the inode name */

  return noffs + inode.namlen - offset - blkinfo->offset;
}
static int nxffs_rdentry(FAR struct nxffs_volume_s *volume, off_t offset,
                         FAR struct nxffs_entry_s *entry)
{
  struct nxffs_inode_s inode;
  uint32_t ecrc;
  uint32_t crc;
  uint8_t state;
  int namlen;
  int ret;

  DEBUGASSERT(volume && entry);
  memset(entry, 0, sizeof(struct nxffs_entry_s));

  /* Read the header at the FLASH offset */

  nxffs_ioseek(volume, offset);
  memcpy(&inode, &volume->cache[volume->iooffset], SIZEOF_NXFFS_INODE_HDR);

  /* Check if the file state is recognized. */

  state = inode.state;
  if (state != INODE_STATE_FILE && state != INODE_STATE_DELETED)
    {
      /* This can't be a valid inode.. don't bother with the rest */

      ret = -ENOENT;
      goto errout_no_offset;
    }

  /* Copy the packed header into the user-friendly buffer */

  entry->hoffset = offset;
  entry->noffset = nxffs_rdle32(inode.noffs);
  entry->doffset = nxffs_rdle32(inode.doffs);
  entry->utc     = nxffs_rdle32(inode.utc);
  entry->datlen  = nxffs_rdle32(inode.datlen);

  /* Modify the packed header and perform the (partial) CRC calculation */

  ecrc           = nxffs_rdle32(inode.crc);
  inode.state    = CONFIG_NXFFS_ERASEDSTATE;
  memset(inode.crc, 0, 4);
  crc            = crc32((FAR const uint8_t *)&inode, SIZEOF_NXFFS_INODE_HDR);

  /* Allocate memory to hold the variable-length file name */

  namlen = inode.namlen;
  entry->name = (FAR char *)kmalloc(namlen + 1);
  if (!entry->name)
    {
      fdbg("ERROR: Failed to allocate name, namlen: %d\n", namlen);
      ret = -ENOMEM;
      goto errout_no_offset;
    }

  /* Seek to the expected location of the name in FLASH */

  nxffs_ioseek(volume, entry->noffset);

  /* Make sure that the block is in memory (the name may not be in the
   * same block as the inode header.
   */

  ret = nxffs_rdcache(volume, volume->ioblock);
  if (ret < 0)
    {
      fdbg("ERROR: nxffsx_rdcache failed: %d\n", -ret);
      goto errout_with_name;
    }

  /* Read the file name from the expected offset in FLASH */

  memcpy(entry->name, &volume->cache[volume->iooffset], namlen);
  entry->name[namlen] = '\0';

  /* Finish the CRC calculation and verify the entry */

  crc = crc32part((FAR const uint8_t *)entry->name, namlen, crc);
  if (crc != ecrc)
    {
      fdbg("ERROR: CRC entry: %08x CRC calculated: %08x\n", ecrc, crc);
      ret = -EIO;
      goto errout_with_name;
    }

  /* We have a good inode header.. but it still could a deleted file.
   * Check the file state.
   */

  if (state != INODE_STATE_FILE)
    {
      /* It is a deleted file.  But still, the data offset and the
       * start size are good so we can use this information to advance
       * further in FLASH memory and reduce the search time.
       */

      offset = nxffs_inodeend(volume, entry);
      nxffs_freeentry(entry);
      ret = -ENOENT;
      goto errout;
    }

  /* Everything is good.. leave the offset pointing to the valid inode
   * header.
   */

  return OK;

  /* On errors where we are suspicious of the validity of the inode header,
   * we need to increment the file position to just after the "good" magic
   * word.
   */

errout_with_name:
  nxffs_freeentry(entry);
errout_no_offset:
  offset += NXFFS_MAGICSIZE;
errout:
  nxffs_ioseek(volume, offset);
  return ret;
}