Ejemplo n.º 1
0
int nxffs_limits(FAR struct nxffs_volume_s *volume)
{
  FAR struct nxffs_entry_s entry;
  off_t block;
  off_t offset;
  bool noinodes = false;
  int nerased;
  int ret;

  /* Get the offset to the first valid block on the FLASH */

  block = 0;
  ret = nxffs_validblock(volume, &block);
  if (ret < 0)
    {
      fdbg("Failed to find a valid block: %d\n", -ret);
      return ret;
    }

  /* Then find the first valid inode in or beyond the first valid block */

  offset = block * volume->geo.blocksize;
  ret = nxffs_nextentry(volume, offset, &entry);
  if (ret < 0)
    {
      /* The value -ENOENT is special.  This simply means that the FLASH
       * was searched to the end and no valid inode was found... the file
       * system is empty (or, in more perverse cases, all inodes are
       * deleted or corrupted).
       */

      if (ret != -ENOENT)
        {
          fdbg("nxffs_nextentry failed: %d\n", -ret);
          return ret;
        }

      /* Set a flag the just indicates that no inodes were found.  Later,
       * we will set the location of the first inode to be the same as
       * the location of the free FLASH region.
       */

      fvdbg("No inodes found\n");
      noinodes = true;
    }
  else
    {
      /* Save the offset to the first inode */

      volume->inoffset = entry.hoffset;
      fvdbg("First inode at offset %d\n", volume->inoffset);

      /* Discard this entry and set the next offset. */

      offset = nxffs_inodeend(volume, &entry);
      nxffs_freeentry(&entry);
    }

  /* Now, search for the last valid entry */

  if (!noinodes)
    {
      while ((ret = nxffs_nextentry(volume, offset, &entry)) == OK)
        {
          /* Discard the entry and guess the next offset. */

          offset = nxffs_inodeend(volume, &entry);
          nxffs_freeentry(&entry);    
        }
      fvdbg("Last inode before offset %d\n", offset);
    }

  /* No inodes were found after this offset.  Now search for a block of
   * erased flash.
   */

  nxffs_ioseek(volume, offset);
  nerased = 0;
  for (;;)
    {
      int ch = nxffs_getc(volume, 1);
      if (ch < 0)
        {
          /* Failed to read the next byte... this could mean that the FLASH
           * is full?
           */

          if (volume->ioblock + 1 >= volume->nblocks &&
              volume->iooffset + 1 >= volume->geo.blocksize)
            {
              /* Yes.. the FLASH is full.  Force the offsets to the end of FLASH */

              volume->froffset = volume->nblocks * volume->geo.blocksize;
              fvdbg("Assume no free FLASH, froffset: %d\n", volume->froffset);
              if (noinodes)
                {
                  volume->inoffset = volume->froffset;
                  fvdbg("No inodes, inoffset: %d\n", volume->inoffset);
                }
              return OK;
            }

          // No?  Then it is some other failure that we do not know how to handle

          fdbg("nxffs_getc failed: %d\n", -ch);
          return ch;
        }

      /* Check for another erased byte */

      else if (ch == CONFIG_NXFFS_ERASEDSTATE)
        {
          /* If we have encountered NXFFS_NERASED number of consecutive
           * erased bytes, then presume we have reached the end of valid
           * data.
           */

          if (++nerased >= NXFFS_NERASED)
            {
              /* Okay.. we have a long stretch of erased FLASH in a valid
               * FLASH block.  Let's say that this is the beginning of
               * the free FLASH region.
               */

              volume->froffset = offset;
              fvdbg("Free FLASH region begins at offset: %d\n", volume->froffset);
              if (noinodes)
                {
                  volume->inoffset = offset;
                  fvdbg("First inode at offset %d\n", volume->inoffset);
                }
              return OK;
            }
        }
      else
        {
          offset += nerased + 1;
          nerased = 0;
        }
    }

  /* Won't get here */

  return OK;
}
Ejemplo n.º 2
0
int nxffs_nextblock(FAR struct nxffs_volume_s *volume, off_t offset,
                    FAR struct nxffs_blkentry_s *blkentry)
{
  int nmagic;
  int ch;
  int nerased;
  int ret;

  /* Seek to the first FLASH offset provided by the caller. */

  nxffs_ioseek(volume, offset);

  /* Skip the block header */

  if (volume->iooffset < SIZEOF_NXFFS_BLOCK_HDR)
    {
      volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR;
    }

  /* Then begin searching */

  nerased = 0;
  nmagic  = 0;

  for (;;)
    {
      /* Read the next character */

      ch = nxffs_getc(volume, SIZEOF_NXFFS_DATA_HDR - nmagic);
      if (ch < 0)
        {
          fdbg("ERROR: nxffs_getc failed: %d\n", -ch);
          return ch;
        }

      /* Check for another erased byte */

      else if (ch == CONFIG_NXFFS_ERASEDSTATE)
        {
          /* If we have encountered NXFFS_NERASED number of consecutive
           * erased bytes, then presume we have reached the end of valid
           * data.
           */

          if (++nerased >= NXFFS_NERASED)
            {
              fvdbg("No entry found\n");
              return -ENOENT;
            }
        }
      else
        {
          nerased = 0;

          /* Check for the magic sequence indicating the start of an NXFFS
           * data block or start of the next inode. There is the possibility
           * of this magic sequnce occurring in FLASH data.  However, the
           * data block CRC should distinguish between real NXFFS data blocks
           * headers and such false alarms.
           */

          if (ch != g_datamagic[nmagic])
            {
              /* Ooops... this is the not the right character for the magic
               * Sequence.  Check if we need to restart or to cancel the sequence:
               */

              if (ch == g_datamagic[0])
                {
                  nmagic = 1;
                }
              else
                {
                  nmagic = 0;
                }
            }
          else if (nmagic < NXFFS_MAGICSIZE - 1)
            {
              /* We have one more character in the magic sequence */

              nmagic++;
            }

          /* We have found the magic sequence in the FLASH data that may
           * indicate the beginning of an NXFFS data block.
           */

          else
            {
              /* The offset to the header must be 4 bytes before the current
               * FLASH seek location.
               */

              blkentry->hoffset = nxffs_iotell(volume) - NXFFS_MAGICSIZE;

              /* Read the block header and verify the block at that address */

              ret = nxffs_rdblkhdr(volume, blkentry->hoffset, &blkentry->datlen);
              if (ret == OK)
                {
                  fvdbg("Found a valid data block, offset: %d datlen: %d\n",
                        blkentry->hoffset, blkentry->datlen);
                  return OK;
                }

              /* False alarm.. Restore the volume cache position (that was
               * destroyed by nxfs_rdblkhdr()) and keep looking.
               */

              nxffs_ioseek(volume, blkentry->hoffset + NXFFS_MAGICSIZE);
              nmagic = 0;
            }
        }
    }

  /* We won't get here, but to keep some compilers happy: */

  return -ENOENT;
}
int nxffs_nextentry(FAR struct nxffs_volume_s *volume, off_t offset,
                    FAR struct nxffs_entry_s *entry)
{
  int nmagic;
  int ch;
  int nerased;
  int ret;

  /* Seek to the first FLASH offset provided by the caller. */

  nxffs_ioseek(volume, offset);

  /* Then begin searching */

  nerased = 0;
  nmagic  = 0;
  for (;;)
    {
      /* Read the next character */

      ch = nxffs_getc(volume, SIZEOF_NXFFS_INODE_HDR - nmagic);
      if (ch < 0)
        {
          fdbg("ERROR: nxffs_getc failed: %d\n", -ch);
          return ch;
        }

      /* Check for another erased byte */

      else if (ch == CONFIG_NXFFS_ERASEDSTATE)
        {
          /* If we have encountered NXFFS_NERASED number of consecutive
           * erased bytes, then presume we have reached the end of valid
           * data.
           */

          if (++nerased >= NXFFS_NERASED)
            {
              fvdbg("No entry found\n");
              return -ENOENT;
            }
        }
      else
        {
          nerased = 0;

          /* Check for the magic sequence indicating the start of an NXFFS
           * inode. There is the possibility of this magic sequnce occurring
           * in FLASH data.  However, the header CRC should distinguish
           * between real NXFFS inode headers and such false alarms.
           */

          if (ch != g_inodemagic[nmagic])
            {
              /* Ooops... this is the not the right character for the magic
               * Sequence.  Check if we need to restart or to cancel the sequence:
               */

              if (ch == g_inodemagic[0])
                {
                  nmagic = 1;
                }
              else
                {
                  nmagic = 0;
                }
            }
          else if (nmagic < NXFFS_MAGICSIZE - 1)
            {
              /* We have one more character in the magic sequence */

              nmagic++;
            }

          /* We have found the magic sequence in the FLASH data that may
           * indicate the beginning of an NXFFS inode.
           */

          else
            {
              /* The the FLASH offset where we found the matching magic number */

              offset = nxffs_iotell(volume) - NXFFS_MAGICSIZE;

              /* Try to extract the inode header from that position */

              ret = nxffs_rdentry(volume, offset, entry);
              if (ret == OK)
                {
                  fvdbg("Found a valid fileheader, offset: %d\n", offset);
                  return OK;
                }

              /* False alarm.. keep looking */

              nmagic = 0;
            }
        }
    }

  /* We won't get here, but to keep some compilers happy: */

  return -ENOENT;
}