summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/examples/nxffs/nxffs_main.c45
-rw-r--r--nuttx/fs/nxffs/nxffs.h28
-rw-r--r--nuttx/fs/nxffs/nxffs_dirent.c11
-rw-r--r--nuttx/fs/nxffs/nxffs_initialize.c13
-rw-r--r--nuttx/fs/nxffs/nxffs_inode.c64
-rw-r--r--nuttx/fs/nxffs/nxffs_pack.c169
-rw-r--r--nuttx/fs/nxffs/nxffs_read.c6
7 files changed, 224 insertions, 112 deletions
diff --git a/apps/examples/nxffs/nxffs_main.c b/apps/examples/nxffs/nxffs_main.c
index 12383071a..b2a6846c0 100644
--- a/apps/examples/nxffs/nxffs_main.c
+++ b/apps/examples/nxffs/nxffs_main.c
@@ -251,9 +251,16 @@ static inline int nxffs_wrfile(FAR struct nxffs_filedesc_s *file)
fd = open(file->name, O_WRONLY | O_CREAT | O_EXCL, 0666);
if (fd < 0)
{
- message("ERROR: Failed to open file for writing: %d\n", errno);
- message(" File name: %s\n", file->name);
- message(" File size: %d\n", file->len);
+ /* If it failed because there is no space on the device, then don't
+ * complain.
+ */
+
+ if (errno != ENOSPC)
+ {
+ message("ERROR: Failed to open file for writing: %d\n", errno);
+ message(" File name: %s\n", file->name);
+ message(" File size: %d\n", file->len);
+ }
nxffs_freefile(file);
return ERROR;
}
@@ -274,11 +281,21 @@ static inline int nxffs_wrfile(FAR struct nxffs_filedesc_s *file)
nbyteswritten = write(fd, &g_fileimage[offset], nbytestowrite);
if (nbyteswritten < 0)
{
- message("ERROR: Failed to write file: %d\n", errno);
- message(" File name: %s\n", file->name);
- message(" File size: %d\n", file->len);
- message(" Write offset: %d\n", offset);
- message(" Write size: %d\n", nbytestowrite);
+ int err = errno;
+
+ /* If the write failed because there is no space on the device,
+ * then don't complain.
+ */
+
+ if (err != ENOSPC)
+ {
+ message("ERROR: Failed to write file: %d\n", err);
+ message(" File name: %s\n", file->name);
+ message(" File size: %d\n", file->len);
+ message(" Write offset: %d\n", offset);
+ message(" Write size: %d\n", nbytestowrite);
+ ret = ERROR;
+ }
close(fd);
/* Remove any garbage file that might have been left behind */
@@ -286,11 +303,13 @@ static inline int nxffs_wrfile(FAR struct nxffs_filedesc_s *file)
ret = unlink(file->name);
if (ret < 0)
{
- message(" Failed to remove corrupted file\n");
+ message(" Failed to remove partial file\n");
}
else
{
- message(" Successfully removed corrupted file\n");
+#if CONFIG_EXAMPLES_NXFFS_VERBOSE != 0
+ message(" Successfully removed partial file\n");
+#endif
}
nxffs_freefile(file);
@@ -332,7 +351,9 @@ static int nxffs_fillfs(void)
ret = nxffs_wrfile(file);
if (ret < 0)
{
+#if CONFIG_EXAMPLES_NXFFS_VERBOSE != 0
message("ERROR: Failed to write file %d\n", i);
+#endif
return ERROR;
}
@@ -645,8 +666,8 @@ static int nxffs_directory(void)
int user_start(int argc, char *argv[])
{
FAR struct mtd_dev_s *mtd;
+ unsigned int i;
int ret;
- int i;
/* Seed the random number generated */
@@ -688,7 +709,7 @@ int user_start(int argc, char *argv[])
*/
#if CONFIG_EXAMPLES_NXFFS_NLOOPS == 0
- for (;;)
+ for (i = 0; ; i++)
#else
for (i = 1; i <= CONFIG_EXAMPLES_NXFFS_NLOOPS; i++)
#endif
diff --git a/nuttx/fs/nxffs/nxffs.h b/nuttx/fs/nxffs/nxffs.h
index 735e4fc0a..262c8577e 100644
--- a/nuttx/fs/nxffs/nxffs.h
+++ b/nuttx/fs/nxffs/nxffs.h
@@ -177,7 +177,6 @@
#define NXFFS_MINDATA 16
-
/* Internal definitions *****************************************************/
/* If we encounter this number of erased bytes, we assume that all of the
* flash beyond this point is erased.
@@ -641,6 +640,33 @@ extern int nxffs_findinode(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_entry_s *entry);
/****************************************************************************
+ * Name: nxffs_inodeend
+ *
+ * Description:
+ * Return an *approximiate* FLASH offset to end of the inode data. The
+ * returned value is guaranteed to be be less then or equal to the offset
+ * of the thing-of-interest in FLASH. Parsing for interesting things
+ * can begin at that point.
+ *
+ * Assumption: The inode header has been verified by the caller and is
+ * known to contain valid data.
+ *
+ * Input Parameters:
+ * volume - Describes the NXFFS volume
+ * entry - Describes the inode.
+ *
+ * Returned Value:
+ * A FLASH offset to the (approximate) end of the inode data. No errors
+ * are detected.
+ *
+ * Defined in nxffs_inode.c
+ *
+ ****************************************************************************/
+
+extern off_t nxffs_inodeend(FAR struct nxffs_volume_s *volume,
+ FAR struct nxffs_entry_s *entry);
+
+/****************************************************************************
* Name: nxffs_verifyblock
*
* Description:
diff --git a/nuttx/fs/nxffs/nxffs_dirent.c b/nuttx/fs/nxffs/nxffs_dirent.c
index bd53ffe0c..40ae8662f 100644
--- a/nuttx/fs/nxffs/nxffs_dirent.c
+++ b/nuttx/fs/nxffs/nxffs_dirent.c
@@ -166,14 +166,9 @@ int nxffs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir)
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 using the rw 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.
- */
-
- dir->u.nxffs.nx_offset = entry.doffset + entry.datlen;
+ /* Discard this entry and set the next offset. */
+
+ dir->u.nxffs.nx_offset = nxffs_inodeend(volume, &entry);
nxffs_freeentry(&entry);
ret = OK;
}
diff --git a/nuttx/fs/nxffs/nxffs_initialize.c b/nuttx/fs/nxffs/nxffs_initialize.c
index c040fa649..7fd1d51fc 100644
--- a/nuttx/fs/nxffs/nxffs_initialize.c
+++ b/nuttx/fs/nxffs/nxffs_initialize.c
@@ -361,14 +361,9 @@ int nxffs_limits(FAR struct nxffs_volume_s *volume)
volume->inoffset = entry.hoffset;
fvdbg("First inode at offset %d\n", volume->inoffset);
- /* Discard this entry and set the next offset using the rw 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.
- */
+ /* Discard this entry and set the next offset. */
- offset = entry.doffset + entry.datlen;
+ offset = nxffs_inodeend(volume, &entry);
nxffs_freeentry(&entry);
}
@@ -378,9 +373,9 @@ int nxffs_limits(FAR struct nxffs_volume_s *volume)
{
while ((ret = nxffs_nextentry(volume, offset, &entry)) == OK)
{
- /* Discard the entry and guess the next offset (see comments above). */
+ /* Discard the entry and guess the next offset. */
- offset = entry.doffset + entry.datlen;
+ offset = nxffs_inodeend(volume, &entry);
nxffs_freeentry(&entry);
}
fvdbg("Last inode before offset %d\n", offset);
diff --git a/nuttx/fs/nxffs/nxffs_inode.c b/nuttx/fs/nxffs/nxffs_inode.c
index 361b5df7e..121c1f6db 100644
--- a/nuttx/fs/nxffs/nxffs_inode.c
+++ b/nuttx/fs/nxffs/nxffs_inode.c
@@ -181,11 +181,11 @@ static int nxffs_rdentry(FAR struct nxffs_volume_s *volume, off_t offset,
if (state != INODE_STATE_FILE)
{
/* It is a deleted file. But still, the data offset and the
- * start size is good so we can use this information to advance
+ * start size are good so we can use this information to advance
* further in FLASH memory and reduce the search time.
*/
- offset = entry->doffset + entry->datlen + SIZEOF_NXFFS_DATA_HDR;
+ offset = nxffs_inodeend(volume, entry);
nxffs_freeentry(entry);
ret = -ENOENT;
goto errout;
@@ -432,7 +432,7 @@ int nxffs_findinode(FAR struct nxffs_volume_s *volume, FAR const char *name,
* byte-for-byte.
*/
- offset = entry->doffset + entry->datlen;
+ offset = nxffs_inodeend(volume, entry);
nxffs_freeentry(entry);
}
@@ -440,3 +440,61 @@ int nxffs_findinode(FAR struct nxffs_volume_s *volume, FAR const char *name,
return -ENOENT;
}
+
+/****************************************************************************
+ * Name: nxffs_inodeend
+ *
+ * Description:
+ * Return an *approximiate* FLASH offset to end of the inode data. The
+ * returned value is guaranteed to be be less then or equal to the offset
+ * of the thing-of-interest in FLASH. Parsing for interesting things
+ * can begin at that point.
+ *
+ * Assumption: The inode header has been verified by the caller and is
+ * known to contain valid data.
+ *
+ * Input Parameters:
+ * volume - Describes the NXFFS volume
+ * entry - Describes the inode.
+ *
+ * Returned Value:
+ * A FLASH offset to the (approximate) end of the inode data. No errors
+ * are detected.
+ *
+ ****************************************************************************/
+
+off_t nxffs_inodeend(FAR struct nxffs_volume_s *volume,
+ FAR struct nxffs_entry_s *entry)
+{
+ /* A zero length file will have no data blocks */
+
+ if (entry->doffset)
+ {
+ /* This is the maximum size of one data block */
+
+ uint16_t maxsize = volume->geo.blocksize - SIZEOF_NXFFS_DATA_HDR;
+
+ /* This is the minimum number of blocks require to span all of the
+ * inode data. One additional block could possibly be required -- we
+ * could make this accurate by looking at the size of the first, perhaps
+ * partial, data block.
+ */
+
+ off_t minblocks = (entry->datlen + maxsize - 1) / maxsize;
+
+ /* And this is our best, simple guess at the end of the inode data */
+
+ return entry->doffset + entry->datlen + minblocks * SIZEOF_NXFFS_DATA_HDR;
+ }
+
+ /* Otherwise, return an offset that accounts only for the inode header and
+ * the inode name.
+ */
+
+ /* All valid inodes will have a name associated with them */
+
+ DEBUGASSERT(entry->noffset);
+ return entry->noffset + strlen(entry->name);
+}
+
+
diff --git a/nuttx/fs/nxffs/nxffs_pack.c b/nuttx/fs/nxffs/nxffs_pack.c
index d4a7d5f39..212d2b429 100644
--- a/nuttx/fs/nxffs/nxffs_pack.c
+++ b/nuttx/fs/nxffs/nxffs_pack.c
@@ -399,7 +399,8 @@ static inline int nxffs_startpos(FAR struct nxffs_volume_s *volume,
* Input Parameters:
* volume - The volume to be packed
* pack - The volume packing state structure.
- * offset - FLASH offset to the data block header
+ * offset - FLASH offset to the data block header (will be zero for zero-
+ * files.
*
* Returned Values:
* Zero on success; Otherwise, a negated errno value is returned to
@@ -410,22 +411,27 @@ static inline int nxffs_startpos(FAR struct nxffs_volume_s *volume,
static int nxffs_srcsetup(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_pack_s *pack, off_t offset)
{
- int ret;
-
- /* No, start with the first data block */
+ /* Start with the first data block */
pack->src.blkoffset = offset;
pack->src.blkpos = 0;
- /* Seek to the data block header, read and verify the block header */
+ /* Zero-length files have no valid data block offset */
- ret = nxffs_rdblkhdr(volume, offset, &pack->src.blklen);
- if (ret < 0)
+ if (offset > 0)
{
- fdbg("Failed to verify the data block header: %d\n", -ret);
+ /* Seek to the data block header, read and verify the block header */
+
+ int ret = nxffs_rdblkhdr(volume, offset, &pack->src.blklen);
+ if (ret < 0)
+ {
+ fdbg("Failed to verify the data block header: %d\n", -ret);
+ }
+ return ret;
}
- return ret;
+ DEBUGASSERT(pack->src.entry.datlen == 0);
+ return OK;
}
/****************************************************************************
@@ -449,6 +455,7 @@ static int nxffs_destsetup(FAR struct nxffs_volume_s *volume,
{
size_t mindata;
int namlen;
+ int ret;
/* The destination can be in one of three of states:
*
@@ -516,66 +523,77 @@ static int nxffs_destsetup(FAR struct nxffs_volume_s *volume,
/* State 3: Inode header not-written, inode name written. Still need the position
* of the first data block.
+ *
+ * Deal with the special case where the source inode is a zero length file
+ * with no data blocks to be transferred.
*/
- if (pack->dest.entry.doffset == 0)
+ if (pack->src.entry.doffset > 0)
{
- /* Will the data block header plus a minimal amount of data fit in this
- * block? (or the whole file if the file is very small).
- */
-
- mindata = MIN(NXFFS_MINDATA, pack->dest.entry.datlen);
- if (pack->iooffset + SIZEOF_NXFFS_DATA_HDR + mindata > volume->geo.blocksize)
+ if (pack->dest.entry.doffset == 0)
{
- /* No.. return an indication that we are at the end of the block
- * and try again later.
+ /* Will the data block header plus a minimal amount of data fit in this
+ * block? (or the whole file if the file is very small).
*/
- return -ENOSPC;
- }
+ mindata = MIN(NXFFS_MINDATA, pack->dest.entry.datlen);
+ if (pack->iooffset + SIZEOF_NXFFS_DATA_HDR + mindata > volume->geo.blocksize)
+ {
+ /* No.. return an indication that we are at the end of the block
+ * and try again later.
+ */
- /* Yes.. reserve space for the data block header */
+ ret = -ENOSPC;
+ goto errout;
+ }
- pack->dest.entry.doffset = nxffs_packtell(volume, pack);
- pack->iooffset += SIZEOF_NXFFS_DATA_HDR;
+ /* Yes.. reserve space for the data block header */
- /* Initialize the output data stream to start with the first data block */
+ pack->dest.entry.doffset = nxffs_packtell(volume, pack);
+ pack->iooffset += SIZEOF_NXFFS_DATA_HDR;
- pack->dest.blkoffset = pack->dest.entry.doffset;
- pack->dest.blklen = 0;
- pack->dest.blkpos = 0;
- }
+ /* Initialize the output data stream to start with the first data block */
- /* State 4: Starting a new block. Verify that there is space in the current
- * block for another (minimal sized) block
- */
+ pack->dest.blkoffset = pack->dest.entry.doffset;
+ pack->dest.blklen = 0;
+ pack->dest.blkpos = 0;
+ }
- if (pack->dest.blkoffset == 0)
- {
- /* Will the data block header plus a minimal amount of data fit in this
- * block? (or the whole file if the file is very small).
+ /* State 4: Starting a new block. Verify that there is space in the current
+ * block for another (minimal sized) block
*/
- mindata = MIN(NXFFS_MINDATA, pack->dest.entry.datlen);
- if (pack->iooffset + SIZEOF_NXFFS_DATA_HDR + mindata > volume->geo.blocksize)
+ if (pack->dest.blkoffset == 0)
{
- /* No.. return an indication that we are at the end of the block
- * and try again later.
+ /* Will the data block header plus a minimal amount of data fit in this
+ * block? (or the whole file if the file is very small).
*/
- return -ENOSPC;
- }
+ mindata = MIN(NXFFS_MINDATA, pack->dest.entry.datlen);
+ if (pack->iooffset + SIZEOF_NXFFS_DATA_HDR + mindata > volume->geo.blocksize)
+ {
+ /* No.. return an indication that we are at the end of the block
+ * and try again later.
+ */
+
+ ret = -ENOSPC;
+ goto errout;
+ }
- /* Yes.. reserve space for the data block header */
+ /* Yes.. reserve space for the data block header */
- pack->dest.blkoffset = nxffs_packtell(volume, pack);
- pack->iooffset += SIZEOF_NXFFS_DATA_HDR;
- pack->dest.blklen = 0;
- pack->dest.blkpos = 0;
+ pack->dest.blkoffset = nxffs_packtell(volume, pack);
+ pack->iooffset += SIZEOF_NXFFS_DATA_HDR;
+ pack->dest.blklen = 0;
+ pack->dest.blkpos = 0;
+ }
}
+ ret = OK;
+
+errout:
volume->froffset = nxffs_packtell(volume, pack);
- return OK;
+ return ret;
}
/****************************************************************************
@@ -806,19 +824,22 @@ static inline int nxffs_packblock(FAR struct nxffs_volume_s *volume,
/* Transfer the smaller of the two amounts data */
uint16_t xfrlen = MIN(srclen, destlen);
- nxffs_ioseek(volume, pack->src.blkoffset + SIZEOF_NXFFS_DATA_HDR + pack->src.blkpos);
- memcpy(&pack->iobuffer[pack->iooffset], &volume->cache[volume->iooffset], xfrlen);
-
- /* Increment counts and offset for this data transfer */
-
- pack->src.fpos += xfrlen; /* Source data offsets */
- pack->src.blkpos += xfrlen;
- pack->dest.fpos += xfrlen; /* Destination data offsets */
- pack->dest.blkpos += xfrlen;
- pack->dest.blklen += xfrlen; /* Destination data block size */
- pack->iooffset += xfrlen; /* Destination I/O block offset */
- volume->iooffset += xfrlen; /* Source I/O block offset */
- volume->froffset += xfrlen; /* Free FLASH offset */
+ if (xfrlen > 0)
+ {
+ nxffs_ioseek(volume, pack->src.blkoffset + SIZEOF_NXFFS_DATA_HDR + pack->src.blkpos);
+ memcpy(&pack->iobuffer[pack->iooffset], &volume->cache[volume->iooffset], xfrlen);
+
+ /* Increment counts and offset for this data transfer */
+
+ pack->src.fpos += xfrlen; /* Source data offsets */
+ pack->src.blkpos += xfrlen;
+ pack->dest.fpos += xfrlen; /* Destination data offsets */
+ pack->dest.blkpos += xfrlen;
+ pack->dest.blklen += xfrlen; /* Destination data block size */
+ pack->iooffset += xfrlen; /* Destination I/O block offset */
+ volume->iooffset += xfrlen; /* Source I/O block offset */
+ volume->froffset += xfrlen; /* Free FLASH offset */
+ }
/* Now, either the (1) src block has been fully transferred, (2) all
* of the source data has been transferred, or (3) the the destination
@@ -839,7 +860,9 @@ static inline int nxffs_packblock(FAR struct nxffs_volume_s *volume,
/* Find the next valid source inode */
offset = pack->src.blkoffset + pack->src.blklen;
- ret = nxffs_nextentry(volume, offset, &pack->src.entry);
+ memset(&pack->src, 0, sizeof(struct nxffs_packstream_s));
+
+ ret = nxffs_nextentry(volume, offset, &pack->src.entry);
if (ret < 0)
{
/* No more valid inode entries. Just return an end-of-flash error
@@ -859,16 +882,11 @@ static inline int nxffs_packblock(FAR struct nxffs_volume_s *volume,
/* Setup the dest stream */
- pack->dest.entry.hoffset = 0;
- pack->dest.entry.noffset = 0;
- pack->dest.entry.doffset = 0;
- pack->dest.entry.name = pack->src.entry.name;
- pack->dest.entry.utc = pack->src.entry.utc;
- pack->dest.entry.datlen = pack->src.entry.datlen;
- pack->dest.blkoffset = 0;
- pack->dest.blklen = 0;
- pack->dest.blkpos = 0;
- pack->src.entry.name = NULL;
+ memset(&pack->dest, 0, sizeof(struct nxffs_packstream_s));
+ pack->dest.entry.name = pack->src.entry.name;
+ pack->dest.entry.utc = pack->src.entry.utc;
+ pack->dest.entry.datlen = pack->src.entry.datlen;
+ pack->src.entry.name = NULL;
/* Is there sufficient space at the end of the I/O block to hold
* the inode header?
@@ -883,14 +901,7 @@ static inline int nxffs_packblock(FAR struct nxffs_volume_s *volume,
return OK;
}
- /* Set the current inode header off to the current position and reserve
- * the memory.
- */
-
- pack->dest.entry.hoffset = nxffs_packtell(volume, pack);
- pack->iooffset += SIZEOF_NXFFS_INODE_HDR;
-
- /* Then configure the destination stream */
+ /* Configure the destination stream */
ret = nxffs_destsetup(volume, pack);
if (ret < 0)
diff --git a/nuttx/fs/nxffs/nxffs_read.c b/nuttx/fs/nxffs/nxffs_read.c
index f52e21859..cf9bf78e0 100644
--- a/nuttx/fs/nxffs/nxffs_read.c
+++ b/nuttx/fs/nxffs/nxffs_read.c
@@ -101,6 +101,12 @@ static ssize_t nxffs_rdseek(FAR struct nxffs_volume_s *volume,
*/
offset = entry->doffset;
+ if (offset == 0)
+ {
+ /* Zero length files will have no data blocks */
+
+ return -ENOSPC;
+ }
/* Loop until we read the data block containing the desired position */