Example #1
0
static inline int nxffs_wrname(FAR struct nxffs_volume_s *volume,
                               FAR struct nxffs_entry_s *entry,
                               int namlen)
{
  int ret;

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

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

  /* Copy the inode name to the volume cache and write the inode name block */

  memcpy(&volume->cache[volume->iooffset], entry->name, namlen);
  ret = nxffs_wrcache(volume);
  if (ret < 0)
    {
      fdbg("ERROR: Failed to write inode header block %d: %d\n",
           volume->ioblock, -ret);
    }

  return ret;
}
Example #2
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;
}
Example #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;
}
Example #4
0
int nxffs_rminode(FAR struct nxffs_volume_s *volume, FAR const char *name)
{
  FAR struct nxffs_ofile_s *ofile;
  FAR struct nxffs_inode_s *inode;
  struct nxffs_entry_s entry;
  int ret;

  /* Check if the file is open */

  ofile = nxffs_findofile(volume, name);
  if (ofile)
    {
      /* We can't remove the inode if it is open */

      fdbg("Inode '%s' is open\n", name);
      ret = -EBUSY;
      goto errout;
    }

  /* Find the NXFFS inode */

  ret = nxffs_findinode(volume, name, &entry);
  if (ret < 0)
    {
      fdbg("Inode '%s' not found\n", name);
      goto errout;
    }

  /* Set the position to the FLASH offset of the file header (nxffs_findinode
   * should have left the block in the cache).
   */

  nxffs_ioseek(volume, entry.hoffset);

  /* Make sure that the block is in the cache */

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

  /* Change the file status... it is no longer valid */

  inode = (FAR struct nxffs_inode_s *)&volume->cache[volume->iooffset];
  inode->state = INODE_STATE_DELETED;

  /* Then write the cached block back to FLASH */

  ret = nxffs_wrcache(volume);
  if (ret < 0)
    {
      fdbg("Failed to read data into cache: %d\n", ret);
    }

errout_with_entry:
  nxffs_freeentry(&entry);
errout:
  return ret;
}
int nxffs_wrverify(FAR struct nxffs_volume_s *volume, size_t size)
{
  uint16_t iooffset;
  int nerased;
  int ret;
  int i;

  /* Search to the very last block in the volume if we have to */

  while (volume->ioblock < volume->nblocks)
    {
      /* Make sure that the block is in memory */

      ret = nxffs_rdcache(volume, volume->ioblock);
      if (ret < 0)
        {
          /* Ignore the error... just skip to the next block.  This should
           * never happen with normal FLASH, but could occur with NAND if
           * the block has uncorrectable bit errors.
           */

          fdbg("ERROR: Failed to read block %d: %d\n",
               volume->ioblock, -ret);
        }

      /* Search to the very end of this block if we have to */

      else
        {
          iooffset = volume->iooffset;
          nerased  = 0;

          for (i = volume->iooffset; i < volume->geo.blocksize; i++)
            {
              /* Is this byte erased? */

              if (volume->cache[i] == CONFIG_NXFFS_ERASEDSTATE)
                {
                  /* Yes.. increment the count of contiguous, erased bytes */

                  nerased++;

                  /* Is the whole header memory erased? */

                  if (nerased >= size)
                    {
                       /* Yes.. this this is where we will put the object */

                       off_t offset =
                         volume->ioblock * volume->geo.blocksize + iooffset;

                       /* Update the free flash offset and return success */

                       volume->froffset = offset + size;
                       return OK;
                    }
                }

              /* This byte is not erased!  (It should be unless the block is
               * bad)
               */

              else
                {
                  nerased  = 0;
                  iooffset = i + 1;
                }
            }
        }

      /* If we get here, then either (1) this block is not read-able, or
       * (2) we have looked at every byte in the block and did not find
       * any sequence of erased bytes long enough to hold the object.
       * Skip to the next, valid block.
       */

      volume->ioblock++;
      ret = nxffs_validblock(volume, &volume->ioblock);
      if (ret < 0)
        {
          fdbg("ERROR: No more valid blocks\n");
          return ret;
        }

      volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR;
      volume->froffset = volume->ioblock * volume->geo.blocksize + SIZEOF_NXFFS_BLOCK_HDR;
    }

  /* Return -ENOSPC if there is no erased memory left in the volume for
   * the object.
   */

  fdbg("ERROR: Not enough memory left to hold the file header\n");
  return -ENOSPC;
}
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;
}