mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 00:14:22 +08:00
More NXFFS bugfixes
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3551 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
+1
-26
@@ -247,7 +247,7 @@ struct nxffs_ofile_s
|
|||||||
{
|
{
|
||||||
struct nxffs_ofile_s *flink; /* Supports a singly linked list */
|
struct nxffs_ofile_s *flink; /* Supports a singly linked list */
|
||||||
int16_t crefs; /* Reference count */
|
int16_t crefs; /* Reference count */
|
||||||
mode_t mode; /* Open mode */
|
mode_t oflags; /* Open mode */
|
||||||
struct nxffs_entry_s entry; /* Describes the NXFFS inode entry */
|
struct nxffs_entry_s entry; /* Describes the NXFFS inode entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -551,31 +551,6 @@ extern off_t nxffs_iotell(FAR struct nxffs_volume_s *volume);
|
|||||||
|
|
||||||
extern int nxffs_getc(FAR struct nxffs_volume_s *volume);
|
extern int nxffs_getc(FAR struct nxffs_volume_s *volume);
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: nxffs_rddata
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Read a sequence of data bytes from the FLASH memory. This function
|
|
||||||
* allows the data in the formatted FLASH blocks to be read as a continuous
|
|
||||||
* byte stream, skipping over bad blocks and block headers as necessary.
|
|
||||||
*
|
|
||||||
* Input Parameters:
|
|
||||||
* volume - Describes the NXFFS volume. The paramters ioblock and iooffset
|
|
||||||
* in the volume structure determine the behavior of nxffs_getc().
|
|
||||||
* buffer - A pointer to memory to receive the data read from FLASH.
|
|
||||||
* buflen - The maximum number of bytes to read from FLASH.
|
|
||||||
*
|
|
||||||
* Returned Value:
|
|
||||||
* The number of bytes read is returned on success. Otherwise, a negated
|
|
||||||
* errno indicating the nature of the failure.
|
|
||||||
*
|
|
||||||
* Defined in nxffs_cache.c
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
extern ssize_t nxffs_rddata(FAR struct nxffs_volume_s *volume,
|
|
||||||
FAR uint8_t *buffer, size_t buflen);
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nxffs_freeentry
|
* Name: nxffs_freeentry
|
||||||
*
|
*
|
||||||
|
|||||||
+15
-47
@@ -234,7 +234,20 @@ int nxffs_getc(FAR struct nxffs_volume_s *volume)
|
|||||||
|
|
||||||
if (volume->iooffset >= volume->geo.blocksize)
|
if (volume->iooffset >= volume->geo.blocksize)
|
||||||
{
|
{
|
||||||
volume->ioblock++;
|
/* Check for attempt to read past the end of FLASH */
|
||||||
|
|
||||||
|
off_t nextblock = volume->ioblock + 1;
|
||||||
|
if (nextblock >= volume->nblocks)
|
||||||
|
{
|
||||||
|
fdbg("End of FLASH encountered\n");
|
||||||
|
return -ENOSPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up the seek to the data just after the header in the
|
||||||
|
* next block.
|
||||||
|
*/
|
||||||
|
|
||||||
|
volume->ioblock = nextblock;
|
||||||
volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR;
|
volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,7 +264,7 @@ int nxffs_getc(FAR struct nxffs_volume_s *volume)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (ret == -ENOENT);
|
while (ret != OK);
|
||||||
|
|
||||||
/* Return the the character at this offset. Note that on return,
|
/* Return the the character at this offset. Note that on return,
|
||||||
* iooffset could point to the byte outside of the current block.
|
* iooffset could point to the byte outside of the current block.
|
||||||
@@ -261,48 +274,3 @@ int nxffs_getc(FAR struct nxffs_volume_s *volume)
|
|||||||
volume->iooffset++;
|
volume->iooffset++;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: nxffs_rddata
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Read a sequence of data bytes from the FLASH memory. This function
|
|
||||||
* allows the data in the formatted FLASH blocks to be read as a continuous
|
|
||||||
* byte stream, skipping over bad blocks and block headers as necessary.
|
|
||||||
*
|
|
||||||
* Input Parameters:
|
|
||||||
* volume - Describes the NXFFS volume. The paramters ioblock and iooffset
|
|
||||||
* in the volume structure determine the behavior of nxffs_getc().
|
|
||||||
* buffer - A pointer to memory to receive the data read from FLASH.
|
|
||||||
* buflen - The maximum number of bytes to read from FLASH.
|
|
||||||
*
|
|
||||||
* Returned Value:
|
|
||||||
* The number of bytes read is returned on success. Otherwise, a negated
|
|
||||||
* errno indicating the nature of the failure.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
ssize_t nxffs_rddata(FAR struct nxffs_volume_s *volume,
|
|
||||||
FAR uint8_t *buffer, size_t buflen)
|
|
||||||
{
|
|
||||||
size_t nbytes;
|
|
||||||
int ch;
|
|
||||||
|
|
||||||
for (nbytes = buflen; nbytes > 0; nbytes--)
|
|
||||||
{
|
|
||||||
/* Read the next character (which could be in the next block) */
|
|
||||||
|
|
||||||
ch = nxffs_getc(volume);
|
|
||||||
if (ch < 0)
|
|
||||||
{
|
|
||||||
fdbg("Failed to read byte: %d\n", -ch);
|
|
||||||
return ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add the next character to the user buffer */
|
|
||||||
|
|
||||||
*buffer++ = (uint8_t)ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buflen;
|
|
||||||
}
|
|
||||||
|
|||||||
+15
-11
@@ -102,12 +102,7 @@ static int nxffs_rdentry(FAR struct nxffs_volume_s *volume, off_t offset,
|
|||||||
/* Read the header at the FLASH offset */
|
/* Read the header at the FLASH offset */
|
||||||
|
|
||||||
nxffs_ioseek(volume, offset);
|
nxffs_ioseek(volume, offset);
|
||||||
ret = nxffs_rddata(volume, (FAR uint8_t *)&inode, SIZEOF_NXFFS_INODE_HDR);
|
memcpy(&inode, &volume->cache[volume->iooffset], SIZEOF_NXFFS_INODE_HDR);
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
fdbg("Failed to read inode, offset %d: %d\n", offset, -ret);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if the file is marked as deleted. */
|
/* Check if the file is marked as deleted. */
|
||||||
|
|
||||||
@@ -141,15 +136,24 @@ static int nxffs_rdentry(FAR struct nxffs_volume_s *volume, off_t offset,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the file name from the expected offset in FLASH */
|
/* Seek to the expected location of the name in FLASH */
|
||||||
|
|
||||||
nxffs_ioseek(volume, entry->noffset);
|
nxffs_ioseek(volume, entry->noffset);
|
||||||
ret = nxffs_rddata(volume, (FAR uint8_t*)entry->name, namlen);
|
|
||||||
|
/* 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, 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fdbg("Failed to read inode, offset %d: %d\n", offset, -ret);
|
fdbg("nxffsx_rdcache failed: %d\n", -ret);
|
||||||
return -EIO;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read the file name from the expected offset in FLASH */
|
||||||
|
|
||||||
|
memcpy(entry->name, &volume->cache[volume->iooffset], namlen);
|
||||||
entry->name[namlen] = '\0';
|
entry->name[namlen] = '\0';
|
||||||
|
|
||||||
/* Finish the CRC calculation and verify the entry */
|
/* Finish the CRC calculation and verify the entry */
|
||||||
@@ -350,7 +354,7 @@ int nxffs_findinode(FAR struct nxffs_volume_s *volume, FAR const char *name,
|
|||||||
ret = nxffs_nextentry(volume, offset, entry);
|
ret = nxffs_nextentry(volume, offset, entry);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fdbg("No inode found: %d\n", -ret);
|
fvdbg("No inode found: %d\n", -ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ static inline int nxffs_namerased(FAR struct nxffs_volume_s *volume,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline int nxffs_wropen(FAR struct nxffs_volume_s *volume,
|
static inline int nxffs_wropen(FAR struct nxffs_volume_s *volume,
|
||||||
FAR const char *name, mode_t mode,
|
FAR const char *name, mode_t oflags,
|
||||||
FAR struct nxffs_ofile_s **ppofile)
|
FAR struct nxffs_ofile_s **ppofile)
|
||||||
{
|
{
|
||||||
FAR struct nxffs_wrfile_s *wrfile;
|
FAR struct nxffs_wrfile_s *wrfile;
|
||||||
@@ -370,7 +370,7 @@ static inline int nxffs_wropen(FAR struct nxffs_volume_s *volume,
|
|||||||
* exclusively.
|
* exclusively.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((mode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
|
if ((oflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
|
||||||
{
|
{
|
||||||
fdbg("File exists, can't create O_EXCL\n");
|
fdbg("File exists, can't create O_EXCL\n");
|
||||||
ret = -EEXIST;
|
ret = -EEXIST;
|
||||||
@@ -382,7 +382,7 @@ static inline int nxffs_wropen(FAR struct nxffs_volume_s *volume,
|
|||||||
* we will not re-create the file unless O_CREAT is also specified.
|
* we will not re-create the file unless O_CREAT is also specified.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
else if ((mode & (O_CREAT|O_TRUNC)) == (O_CREAT|O_TRUNC))
|
else if ((oflags & (O_CREAT|O_TRUNC)) == (O_CREAT|O_TRUNC))
|
||||||
{
|
{
|
||||||
/* Just schedule the removal the file and fall through to re-create it.
|
/* Just schedule the removal the file and fall through to re-create it.
|
||||||
* Note that the old file of the same name will not actually be removed
|
* Note that the old file of the same name will not actually be removed
|
||||||
@@ -408,7 +408,7 @@ static inline int nxffs_wropen(FAR struct nxffs_volume_s *volume,
|
|||||||
* it). Now, make sure that we were asked to created it.
|
* it). Now, make sure that we were asked to created it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((mode & O_CREAT) == 0)
|
if ((oflags & O_CREAT) == 0)
|
||||||
{
|
{
|
||||||
fdbg("Not asked to create the file\n");
|
fdbg("Not asked to create the file\n");
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
@@ -445,7 +445,7 @@ static inline int nxffs_wropen(FAR struct nxffs_volume_s *volume,
|
|||||||
/* Initialize the open file state structure */
|
/* Initialize the open file state structure */
|
||||||
|
|
||||||
wrfile->ofile.crefs = 1;
|
wrfile->ofile.crefs = 1;
|
||||||
wrfile->ofile.mode = O_WROK;
|
wrfile->ofile.oflags = oflags;
|
||||||
wrfile->ofile.entry.utc = time(NULL);
|
wrfile->ofile.entry.utc = time(NULL);
|
||||||
wrfile->truncate = truncate;
|
wrfile->truncate = truncate;
|
||||||
|
|
||||||
@@ -637,7 +637,7 @@ static inline int nxffs_rdopen(FAR struct nxffs_volume_s *volume,
|
|||||||
* Limitation: Files cannot be open both for reading and writing.
|
* Limitation: Files cannot be open both for reading and writing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((ofile->mode & O_WROK) != 0)
|
if ((ofile->oflags & O_WROK) != 0)
|
||||||
{
|
{
|
||||||
fdbg("File is open for writing\n");
|
fdbg("File is open for writing\n");
|
||||||
ret = -ENOSYS;
|
ret = -ENOSYS;
|
||||||
@@ -670,7 +670,7 @@ static inline int nxffs_rdopen(FAR struct nxffs_volume_s *volume,
|
|||||||
/* Initialize the open file state structure */
|
/* Initialize the open file state structure */
|
||||||
|
|
||||||
ofile->crefs = 1;
|
ofile->crefs = 1;
|
||||||
ofile->mode = O_RDOK;
|
ofile->oflags = O_RDOK;
|
||||||
|
|
||||||
/* Find the file on this volume associated with this file name */
|
/* Find the file on this volume associated with this file name */
|
||||||
|
|
||||||
@@ -1011,7 +1011,7 @@ int nxffs_open(FAR struct file *filep, FAR const char *relpath,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
case O_WROK:
|
case O_WROK:
|
||||||
ret = nxffs_wropen(volume, relpath, mode, &ofile);
|
ret = nxffs_wropen(volume, relpath, oflags, &ofile);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case O_RDOK:
|
case O_RDOK:
|
||||||
@@ -1088,7 +1088,7 @@ int nxffs_close(FAR struct file *filep)
|
|||||||
|
|
||||||
/* Handle special finalization of the write operation. */
|
/* Handle special finalization of the write operation. */
|
||||||
|
|
||||||
if (ofile->mode == O_WROK)
|
if ((ofile->oflags & O_WROK) != 0)
|
||||||
{
|
{
|
||||||
ret = nxffs_wrclose(volume, (FAR struct nxffs_wrfile_s *)ofile);
|
ret = nxffs_wrclose(volume, (FAR struct nxffs_wrfile_s *)ofile);
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-17
@@ -102,22 +102,23 @@ static int nxffs_rdblkhdr(FAR struct nxffs_volume_s *volume, off_t offset,
|
|||||||
uint32_t crc;
|
uint32_t crc;
|
||||||
uint16_t doffset;
|
uint16_t doffset;
|
||||||
uint16_t dlen;
|
uint16_t dlen;
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* Read the header at the FLASH offset */
|
/* Read the header at the FLASH offset */
|
||||||
|
|
||||||
nxffs_ioseek(volume, offset);
|
nxffs_ioseek(volume, offset);
|
||||||
ret = nxffs_rddata(volume, (FAR uint8_t *)&blkhdr, SIZEOF_NXFFS_DATA_HDR);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
fdbg("Failed to read data block header, offset %d: %d\n", offset, -ret);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
doffset = volume->iooffset;
|
doffset = volume->iooffset;
|
||||||
|
memcpy(&blkhdr, &volume->cache[doffset], SIZEOF_NXFFS_DATA_HDR);
|
||||||
|
|
||||||
/* Extract the data length */
|
/* Extract the data length */
|
||||||
|
|
||||||
dlen = nxffs_rdle16(blkhdr.datlen);
|
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)
|
if ((uint32_t)doffset + (uint32_t)dlen > (uint32_t)volume->geo.blocksize)
|
||||||
{
|
{
|
||||||
fdbg("Data length=%d is unreasonable at offset=%d\n", dlen, doffset);
|
fdbg("Data length=%d is unreasonable at offset=%d\n", dlen, doffset);
|
||||||
@@ -131,6 +132,7 @@ static int nxffs_rdblkhdr(FAR struct nxffs_volume_s *volume, off_t offset,
|
|||||||
nxffs_wrle32(blkhdr.crc, 0);
|
nxffs_wrle32(blkhdr.crc, 0);
|
||||||
crc = crc32((FAR const uint8_t *)&blkhdr, SIZEOF_NXFFS_DATA_HDR);
|
crc = crc32((FAR const uint8_t *)&blkhdr, SIZEOF_NXFFS_DATA_HDR);
|
||||||
crc = crc32part(&volume->cache[doffset], dlen, crc);
|
crc = crc32part(&volume->cache[doffset], dlen, crc);
|
||||||
|
|
||||||
if (crc != ecrc)
|
if (crc != ecrc)
|
||||||
{
|
{
|
||||||
fdbg("CRC failure\n");
|
fdbg("CRC failure\n");
|
||||||
@@ -349,7 +351,6 @@ ssize_t nxffs_read(FAR struct file *filep, FAR char *buffer, size_t buflen)
|
|||||||
ssize_t total;
|
ssize_t total;
|
||||||
size_t available;
|
size_t available;
|
||||||
size_t readsize;
|
size_t readsize;
|
||||||
ssize_t nread;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
fvdbg("Read %d bytes from offset %d\n", buflen, filep->f_pos);
|
fvdbg("Read %d bytes from offset %d\n", buflen, filep->f_pos);
|
||||||
@@ -381,7 +382,7 @@ ssize_t nxffs_read(FAR struct file *filep, FAR char *buffer, size_t buflen)
|
|||||||
|
|
||||||
/* Check if the file was opened with read access */
|
/* Check if the file was opened with read access */
|
||||||
|
|
||||||
if ((ofile->mode & O_RDOK) == 0)
|
if ((ofile->oflags & O_RDOK) == 0)
|
||||||
{
|
{
|
||||||
fdbg("File not open for read access\n");
|
fdbg("File not open for read access\n");
|
||||||
ret = -EACCES;
|
ret = -EACCES;
|
||||||
@@ -426,17 +427,12 @@ ssize_t nxffs_read(FAR struct file *filep, FAR char *buffer, size_t buflen)
|
|||||||
|
|
||||||
/* Read data from that file offset */
|
/* Read data from that file offset */
|
||||||
|
|
||||||
nread = nxffs_rddata(volume, (FAR uint8_t *)&buffer[total], readsize);
|
memcpy(&buffer[total], &volume->cache[volume->iooffset], readsize);
|
||||||
if (nread < 0)
|
|
||||||
{
|
|
||||||
ret = nread;
|
|
||||||
goto errout_with_semaphore;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update the file offset */
|
/* Update the file offset */
|
||||||
|
|
||||||
filep->f_pos += nread;
|
filep->f_pos += readsize;
|
||||||
total += nread;
|
total += readsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
sem_post(&volume->exclsem);
|
sem_post(&volume->exclsem);
|
||||||
|
|||||||
@@ -482,7 +482,7 @@ ssize_t nxffs_write(FAR struct file *filep, FAR const char *buffer, size_t bufle
|
|||||||
|
|
||||||
/* Check if the file was opened with write access */
|
/* Check if the file was opened with write access */
|
||||||
|
|
||||||
if ((wrfile->ofile.mode & O_WROK) == 0)
|
if ((wrfile->ofile.oflags & O_WROK) == 0)
|
||||||
{
|
{
|
||||||
fdbg("File not open for write access\n");
|
fdbg("File not open for write access\n");
|
||||||
ret = -EACCES;
|
ret = -EACCES;
|
||||||
@@ -620,7 +620,7 @@ int nxffs_wrreserve(FAR struct nxffs_volume_s *volume, size_t size)
|
|||||||
* already at the final block.
|
* already at the final block.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (volume->ioblock + 1 >= volume->geo.neraseblocks)
|
if (volume->ioblock + 1 >= volume->nblocks)
|
||||||
{
|
{
|
||||||
/* Return -ENOSPC to indicate that the volume is full */
|
/* Return -ENOSPC to indicate that the volume is full */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user