Exemplo n.º 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;
}
Exemplo n.º 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;
}
Exemplo n.º 3
0
int nxffs_wrinode(FAR struct nxffs_volume_s *volume,
                  FAR struct nxffs_entry_s *entry)
{
  FAR struct nxffs_inode_s *inode;
  uint32_t crc;
  int namlen;
  int ret;

  /* Seek to the inode header position and assure that it is in the volume
   * cache.
   */

  nxffs_ioseek(volume, entry->hoffset);
  ret = nxffs_rdcache(volume, volume->ioblock);
  if (ret < 0)
    {
      fdbg("ERROR: Failed to read inode header block %d: %d\n",
           volume->ioblock, -ret);
      goto errout;
    }

  /* Get the length of the inode name */

  namlen = strlen(entry->name);
  DEBUGASSERT(namlen < CONFIG_NXFFS_MAXNAMLEN); /* This was verified earlier */

  /* Initialize the inode header */

  inode = (FAR struct nxffs_inode_s *)&volume->cache[volume->iooffset];
  memcpy(inode->magic, g_inodemagic, NXFFS_MAGICSIZE);

  inode->state  = CONFIG_NXFFS_ERASEDSTATE;
  inode->namlen = namlen;

  nxffs_wrle32(inode->noffs,  entry->noffset);
  nxffs_wrle32(inode->doffs,  entry->doffset);
  nxffs_wrle32(inode->utc,    entry->utc);
  nxffs_wrle32(inode->crc,    0);
  nxffs_wrle32(inode->datlen, entry->datlen);

  /* Calculate the CRC */

  crc = crc32((FAR const uint8_t *)inode, SIZEOF_NXFFS_INODE_HDR);
  crc = crc32part((FAR const uint8_t *)entry->name, namlen, crc);

  /* Finish the inode header */

  inode->state = INODE_STATE_FILE;
  nxffs_wrle32(inode->crc, crc);

  /* Write the block with the inode header */

  ret = nxffs_wrcache(volume);
  if (ret < 0)
    {
      fdbg("ERROR: Failed to write inode header block %d: %d\n",
           volume->ioblock, -ret);
    }

  /* The volume is now available for other writers */

errout:
  sem_post(&volume->wrsem);
  return ret;
}
Exemplo n.º 4
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;
}
int nxffs_wrblkhdr(FAR struct nxffs_volume_s *volume,
                   FAR struct nxffs_wrfile_s *wrfile)
{
  FAR struct nxffs_data_s *dathdr;
  int ret;

  /* Write the data block header to memory */

  nxffs_ioseek(volume, wrfile->doffset);
  dathdr = (FAR struct nxffs_data_s *)&volume->cache[volume->iooffset];
  memcpy(dathdr->magic, g_datamagic, NXFFS_MAGICSIZE);
  nxffs_wrle32(dathdr->crc, 0);
  nxffs_wrle16(dathdr->datlen, wrfile->datlen);

  /* Update the entire data block CRC (including the header) */

  wrfile->crc = crc32(&volume->cache[volume->iooffset], wrfile->datlen + SIZEOF_NXFFS_DATA_HDR);
  nxffs_wrle32(dathdr->crc, wrfile->crc);

  /* And write the data block to FLASH */

  ret = nxffs_wrcache(volume);
  if (ret < 0)
    {
      fdbg("ERROR: nxffs_wrcache failed: %d\n", -ret);
      goto errout;
    }

  /* After the block has been successfully written to flash, update the inode
   * statistics and reset the write state.
   *
   * volume:
   *   froffset - The offset the next free FLASH region.  Set to just after
   *     the inode data block that we just wrote.  This is where we will
   *     begin the search for the next inode header or data block.
   */

  volume->froffset = (wrfile->doffset + wrfile->datlen + SIZEOF_NXFFS_DATA_HDR);

  /* wrfile->file.entry:
   *   datlen:  Total file length accumulated so far.  When the file is
   *     closed, this will hold the file length.
   *   doffset: Offset to the first data block.  Only the offset to the
   *     first data block is saved.
   */

  wrfile->ofile.entry.datlen += wrfile->datlen;
  if (wrfile->ofile.entry.doffset == 0)
    {
      wrfile->ofile.entry.doffset = wrfile->doffset;
    }

  /* Return success */

  ret = OK;

errout:
  wrfile->crc     = 0;
  wrfile->doffset = 0;
  wrfile->datlen  = 0;
  return ret;
}