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; }
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; }