int nxffs_findinode(FAR struct nxffs_volume_s *volume, FAR const char *name, FAR struct nxffs_entry_s *entry) { off_t offset; int ret; /* Start with the first valid inode that was discovered when the volume * was created (or modified after the last file system re-packing). */ offset = volume->inoffset; /* Loop, checking each NXFFS inode until either: (1) we find the NXFFS inode * with the matching name, or (2) we reach the end of data written on the * media. */ for (;;) { /* Get the next, valid NXFFS inode entry */ ret = nxffs_nextentry(volume, offset, entry); if (ret < 0) { fvdbg("No inode found: %d\n", -ret); return ret; } /* Is this the NXFFS inode we are looking for? */ else if (strcmp(name, entry->name) == 0) { /* Yes, return success with the entry data in 'entry' */ return OK; } /* Discard this entry and try the next one. Here we set the * next offset using the raw data length as the offset * increment. This is, of course, not accurate because it * does not account for the data headers that enclose the * data. But it is guaranteed to be less than or equal to * the correct offset and, hence, better then searching * byte-for-byte. */ offset = nxffs_inodeend(volume, entry); nxffs_freeentry(entry); } /* We won't get here, but for some compilers: */ return -ENOENT; }
int nxffs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir) { FAR struct nxffs_volume_s *volume; FAR struct nxffs_entry_s entry; off_t offset; int ret; /* Sanity checks */ DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); /* Recover the file system state from the NuttX inode instance */ volume = mountpt->i_private; ret = sem_wait(&volume->exclsem); if (ret != OK) { goto errout; } /* Read the next inode header from the offset */ offset = dir->u.nxffs.nx_offset; ret = nxffs_nextentry(volume, offset, &entry); /* If the read was successful, then handle the reported inode. Note * that when the last inode has been reported, the value -ENOENT will * be returned.. which is correct for the readdir() method. */ if (ret == OK) { /* Return the filename and file type */ fvdbg("Offset %d: \"%s\"\n", entry.hoffset, entry.name); dir->fd_dir.d_type = DTYPE_FILE; strncpy(dir->fd_dir.d_name, entry.name, NAME_MAX+1); /* Discard this entry and set the next offset. */ dir->u.nxffs.nx_offset = nxffs_inodeend(volume, &entry); nxffs_freeentry(&entry); ret = OK; } sem_post(&volume->exclsem); errout: return ret; }
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; }