summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-04-28 21:05:39 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-04-28 21:05:39 +0000
commit7cb2546571c7ac881f4bd0c2c066c974e2174741 (patch)
tree7473c890c43e30659210be6a45b4a6b47749e7b5
parentf5deadfbb2ea797607ce7646c2bca1fdfe74c3c2 (diff)
downloadnuttx-7cb2546571c7ac881f4bd0c2c066c974e2174741.tar.gz
nuttx-7cb2546571c7ac881f4bd0c2c066c974e2174741.tar.bz2
nuttx-7cb2546571c7ac881f4bd0c2c066c974e2174741.zip
More NXFFS logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3537 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--apps/namedapp/binfs.c6
-rw-r--r--nuttx/fs/nxffs/Make.defs3
-rw-r--r--nuttx/fs/nxffs/nxffs.h76
-rw-r--r--nuttx/fs/nxffs/nxffs_cache.c26
-rw-r--r--nuttx/fs/nxffs/nxffs_initialize.c144
-rw-r--r--nuttx/fs/nxffs/nxffs_inode.c6
-rw-r--r--nuttx/fs/nxffs/nxffs_open.c521
-rw-r--r--nuttx/fs/nxffs/nxffs_stat.c186
-rw-r--r--nuttx/fs/nxffs/nxffs_unlink.c184
-rw-r--r--nuttx/fs/nxffs/nxffs_util.c5
-rw-r--r--nuttx/include/sys/statfs.h38
11 files changed, 1144 insertions, 51 deletions
diff --git a/apps/namedapp/binfs.c b/apps/namedapp/binfs.c
index a2f14dd75..106c1444c 100644
--- a/apps/namedapp/binfs.c
+++ b/apps/namedapp/binfs.c
@@ -4,8 +4,6 @@
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
- * References: Linux/Documentation/filesystems/romfs.txt
- *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -388,11 +386,10 @@ static int binfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
index++;
/* Set up the next directory entry offset. NOTE that we could use the
- * standard fr_curroffset instead of our own private fr_curroffset.
+ * standard f_pos instead of our own private fb_index.
*/
dir->u.binfs.fb_index = index;
- dir->u.romfs.fr_curroffset = index;
ret = OK;
}
@@ -423,7 +420,6 @@ static int binfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
binfs_semtake(bm);
dir->u.binfs.fb_index = 0;
- dir->u.romfs.fr_curroffset = 0;
binfs_semgive(bm);
return OK;
diff --git a/nuttx/fs/nxffs/Make.defs b/nuttx/fs/nxffs/Make.defs
index 23e9d3ec2..558fd6be6 100644
--- a/nuttx/fs/nxffs/Make.defs
+++ b/nuttx/fs/nxffs/Make.defs
@@ -36,7 +36,8 @@
ifeq ($(CONFIG_FS_NXFFS),y)
ASRCS +=
CSRCS += nxffs_block.c nxffs_blockstats.c nxffs_cache.c \
- nxffs_initialize.c nxffs_inode.c nxffs_reformat.c nxffs_util.c
+ nxffs_initialize.c nxffs_inode.c nxffs_open.c nxffs_reformat.c \
+ nxffs_stat.c nxffs_unlink.c nxffs_util.c
# Argument for dependency checking
diff --git a/nuttx/fs/nxffs/nxffs.h b/nuttx/fs/nxffs/nxffs.h
index 13f93644e..091260552 100644
--- a/nuttx/fs/nxffs/nxffs.h
+++ b/nuttx/fs/nxffs/nxffs.h
@@ -169,14 +169,6 @@
#define NXFFS_MAGICSIZE 4
/* Internal definitions *****************************************************/
-/* Values for volume flags */
-
-#define VOL_FLAGS_WRITER (1 << 0) /* Only one writer of the volune */
-
-#define VOL_FLAGS_SET(p,f) ((p)->flags &= ~(f))
-#define VOL_FLAGS_CLEAR(p,f) ((p)->flags |= (f))
-#define VOL_FLAGS_TEST(p,f) (((p)->flags & (f)) == 0)
-
/* If we encounter this number of erased bytes, we assume that all of the
* flash beyond this point is erased.
*/
@@ -309,10 +301,6 @@ struct nxffs_blkstats_s
* Public Variables
****************************************************************************/
-/* A singly-linked list of open files */
-
-extern struct nxffs_ofile_s *g_ofiles;
-
/* The magic number that appears that the beginning of each NXFFS (logical)
* block
*/
@@ -420,6 +408,28 @@ extern int nxffs_rdcache(FAR struct nxffs_volume_s *volume, off_t block,
uint8_t nblocks);
/****************************************************************************
+ * Name: nxffs_wrcache
+ *
+ * Description:
+ * Write one or more logical blocks from the volume cache memory.
+ *
+ * Input Parameters:
+ * volume - Describes the current volume
+ * block - The first logical block to write
+ * nblocks - The number of logical blocks to be write.
+ *
+ * Returned Value:
+ * Negated errnos are returned only in the case of MTD reported failures.
+ * Nothing in the volume data itself will generate errors.
+ *
+ * Defined in nxffs_cache.c
+ *
+ ****************************************************************************/
+
+extern int nxffs_wrcache(FAR struct nxffs_volume_s *volume, off_t block,
+ uint8_t nblocks);
+
+/****************************************************************************
* Name: nxffs_ioseek
*
* Description:
@@ -553,7 +563,7 @@ extern int nxffs_nextentry(FAR struct nxffs_volume_s *volume, off_t offset,
extern int nxffs_findinode(FAR struct nxffs_volume_s *volume,
FAR const char *name,
- struct nxffs_entry_s *entry);
+ FAR struct nxffs_entry_s *entry);
/****************************************************************************
* Name: nxffs_verifyblock
@@ -645,6 +655,46 @@ extern int nxffs_blockstats(FAR struct nxffs_volume_s *volume,
extern int nxffs_reformat(FAR struct nxffs_volume_s *volume);
/****************************************************************************
+ * Name: nxffs_findofile
+ *
+ * Description:
+ * Search the list of already opened files to see if the inode of this
+ * name is one of the opened files.
+ *
+ * Input Parameters:
+ * name - The name of the inode to check.
+ *
+ * Returned Value:
+ * If an inode of this name is found in the list of opened inodes, then
+ * a reference to the open file structure is returned. NULL is returned
+ * otherwise.
+ *
+ * Defined in nxffs_open.c
+ *
+ ****************************************************************************/
+
+extern FAR struct nxffs_ofile_s *nxffs_findofile(FAR const char *name);
+
+/****************************************************************************
+ * Name: nxffs_rminode
+ *
+ * Description:
+ * Remove an inode from FLASH. This is the internal implementation of
+ * the file system unlinke operation.
+ *
+ * Input Parameters:
+ * volume - Describes the NXFFS volume.
+ * name - the name of the inode to be deleted.
+ *
+ * Returned Value:
+ * Zero is returned if the inode is successfully deleted. Otherwise, a
+ * negated errno value is returned indicating the nature of the failure.
+ *
+ ****************************************************************************/
+
+extern int nxffs_rminode(FAR struct nxffs_volume_s *volume, FAR const char *name);
+
+/****************************************************************************
* Standard mountpoint operation methods
*
* Description:
diff --git a/nuttx/fs/nxffs/nxffs_cache.c b/nuttx/fs/nxffs/nxffs_cache.c
index 0e7cff256..a2774ddfd 100644
--- a/nuttx/fs/nxffs/nxffs_cache.c
+++ b/nuttx/fs/nxffs/nxffs_cache.c
@@ -116,6 +116,32 @@ int nxffs_rdcache(FAR struct nxffs_volume_s *volume, off_t block,
}
/****************************************************************************
+ * Name: nxffs_wrcache
+ *
+ * Description:
+ * Write one or more logical blocks from the volume cache memory.
+ *
+ * Input Parameters:
+ * volume - Describes the current volume
+ * block - The first logical block to write
+ * nblocks - The number of logical blocks to be write.
+ *
+ * Returned Value:
+ * Negated errnos are returned only in the case of MTD reported failures.
+ * Nothing in the volume data itself will generate errors.
+ *
+ * Defined in nxffs_cache.c
+ *
+ ****************************************************************************/
+
+int nxffs_wrcache(FAR struct nxffs_volume_s *volume, off_t block,
+ uint8_t nblocks)
+{
+#warning "Missing logic"
+ return OK;
+}
+
+/****************************************************************************
* Name: nxffs_ioseek
*
* Description:
diff --git a/nuttx/fs/nxffs/nxffs_initialize.c b/nuttx/fs/nxffs/nxffs_initialize.c
index f473d55c5..8d96ffa15 100644
--- a/nuttx/fs/nxffs/nxffs_initialize.c
+++ b/nuttx/fs/nxffs/nxffs_initialize.c
@@ -103,10 +103,6 @@ const struct mountpt_operations nxffs_operations =
* Public Variables
****************************************************************************/
-/* A singly-linked list of open files */
-
-struct nxffs_ofile_s *g_ofiles;
-
/* The magic number that appears that the beginning of each NXFFS (logical)
* block
*/
@@ -229,9 +225,14 @@ int nxffs_initialize(FAR struct mtd_dev_s *mtd, off_t start, off_t nblocks)
#endif
}
- /* Return success */
+ /* Get the file system limits */
- return OK;
+ ret = nxffs_limits(volume);
+ if (ret == OK)
+ {
+ return OK;
+ }
+ fdbg("Failed to calculate file system limits: %d\n", -ret);
errout_with_iobuffer:
kfree(volume->cache);
@@ -267,6 +268,135 @@ errout:
int nxffs_limits(FAR struct nxffs_volume_s *volume)
{
-#warning "Missing Logic"
+ 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 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.
+ */
+
+ offset = entry.doffset + entry.datlen;
+ 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 (see comments above). */
+
+ offset = entry.doffset + entry.datlen;
+ 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);
+ if (ch < 0)
+ {
+ /* Failed to read the next byte... this could mean that the FLASH
+ * is full?
+ */
+
+ fvdbg("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;
}
diff --git a/nuttx/fs/nxffs/nxffs_inode.c b/nuttx/fs/nxffs/nxffs_inode.c
index a0b2fc0ef..ae61c9d24 100644
--- a/nuttx/fs/nxffs/nxffs_inode.c
+++ b/nuttx/fs/nxffs/nxffs_inode.c
@@ -325,7 +325,7 @@ int nxffs_nextentry(FAR struct nxffs_volume_s *volume, off_t offset,
****************************************************************************/
int nxffs_findinode(FAR struct nxffs_volume_s *volume, FAR const char *name,
- struct nxffs_entry_s *entry)
+ FAR struct nxffs_entry_s *entry)
{
off_t offset;
int ret;
@@ -364,9 +364,9 @@ int nxffs_findinode(FAR struct nxffs_volume_s *volume, FAR const char *name,
/* 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 inclose the
+ * 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 seraching
+ * the correct offset and, hence, better then searching
* byte-for-byte.
*/
diff --git a/nuttx/fs/nxffs/nxffs_open.c b/nuttx/fs/nxffs/nxffs_open.c
new file mode 100644
index 000000000..a7caebca5
--- /dev/null
+++ b/nuttx/fs/nxffs/nxffs_open.c
@@ -0,0 +1,521 @@
+/****************************************************************************
+ * fs/nxffs/nxffs_open.c
+ *
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * References: Linux/Documentation/filesystems/romfs.txt
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <string.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/fs.h>
+#include <nuttx/mtd.h>
+
+#include "nxffs.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+/* A singly-linked list of open files */
+
+static struct nxffs_ofile_s *g_ofiles;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nxffs_create
+ *
+ * Description:
+ * Create a file: Verify the sufficient space exists at the end of the
+ * FLASH. If so, then write then update entry in preparation for writing.
+ *
+ ****************************************************************************/
+
+static inline int nxffs_create(FAR struct nxffs_volume_s *volume,
+ FAR const char *name, mode_t mode,
+ FAR struct nxffs_ofile_s **ppofile)
+{
+#warning "Check if too close to end of block for whole header"
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nxffs_wropen
+ *
+ * Description:
+ * Handle opening for writing. Only a single writer is permitted and only
+ * file creation is supported.
+ *
+ ****************************************************************************/
+
+static inline int nxffs_wropen(FAR struct nxffs_volume_s *volume,
+ FAR const char *name, mode_t mode,
+ FAR struct nxffs_ofile_s **ppofile)
+{
+ FAR struct nxffs_wrfile_s *wrfile;
+ FAR struct nxffs_entry_s entry;
+ int ret;
+
+ /* Limitation: Only a single writer is permitted. Writing may involve
+ * extension of the file system in FLASH. Since files are contiguous
+ * in FLASH, only a single file may be extending the FLASH region.
+ */
+
+ if (volume->wrbusy)
+ {
+ fdbg("There is already a file writer\n");
+ return -ENOSYS;
+ }
+
+ /* Check if the file exists */
+
+ ret = nxffs_findinode(volume, name, &entry);
+ if (ret == OK)
+ {
+ /* It exists. It would be an error if we are asked to create it
+ * exclusively.
+ */
+
+ if ((mode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
+ {
+ fdbg("File exists, can't create O_EXCL\n");
+ return -EEXIST;
+ }
+
+ /* Were we asked to truncate the file? NOTE: Don't truncate the
+ * file if we were not also asked to created it. See below...
+ * we will not re-create the file unless O_CREAT is also specified.
+ */
+
+ else if ((mode & (O_CREAT|O_TRUNC)) == (O_CREAT|O_TRUNC))
+ {
+ /* Just remove the file and fall through to re-create it */
+#warning "Should defer file removal until new file successfully written"
+
+ ret = nxffs_rminode(volume, name);
+ if (ret < 0)
+ {
+ fdbg("nxffs_rminode failed: %d\n", -ret);
+ return ret;
+ }
+ }
+
+ /* The file exists and we were not asked to truncate (and recreate) it.
+ * Limitation: Cannot write to existing files.
+ */
+
+ else
+ {
+ fdbg("File %s exists and we were not asked to truncate it\n");
+ return -ENOSYS;
+ }
+ }
+
+ /* Okay, the file is not open and does not exists (maybe because we deleted
+ * it). Now, make sure that we were asked to created it.
+ */
+
+ if ((mode & O_CREAT) == 0)
+ {
+ fdbg("Not asked to create the file\n");
+ return -ENOENT;
+ }
+
+ /* Yes.. Create a new structure that will describe the state of this open
+ * file. NOTE that a special variant of the open file structure is used
+ * that includes additional information to support the write operation.
+ */
+
+ wrfile = (FAR struct nxffs_wrfile_s *)kzalloc(sizeof(struct nxffs_wrfile_s));
+ if (!wrfile)
+ {
+ return -ENOMEM;
+ }
+
+ /* Initialize the open file state structure */
+
+ wrfile->ofile.crefs = 1;
+
+ /* Allocate FLASH memory for the file and set up for the write */
+
+#warning "Missing Logic"
+
+ /* Add the open file structure to the head of the list of open files */
+
+ wrfile->ofile.flink = g_ofiles;
+ g_ofiles = &wrfile->ofile;
+
+ /* Indicate that the volume is open for writing and return the open file
+ * instance.
+ */
+
+ volume->wrbusy = 1;
+ *ppofile = &wrfile->ofile;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nxffs_rdopen
+ *
+ * Description:
+ * Open an existing file for reading.
+ *
+ ****************************************************************************/
+
+static inline int nxffs_rdopen(FAR struct nxffs_volume_s *volume,
+ FAR const char *name,
+ FAR struct nxffs_ofile_s **ppofile)
+{
+ FAR struct nxffs_ofile_s *ofile;
+ int ret;
+
+ /* Check if the file has already been opened (for reading) */
+
+ ofile = nxffs_findofile(name);
+ if (ofile)
+ {
+ /* The file is already open.
+ * Limitation: Files cannot be open both for reading and writing.
+ */
+
+ if ((ofile->mode & O_WROK) != 0)
+ {
+ fdbg("File is open for writing\n");
+ return -ENOSYS;
+ }
+
+ /* Just increment the reference count on the ofile */
+
+ ofile->crefs++;
+ fdbg("crefs: %d\n", ofile->crefs);
+ }
+
+ /* The file has not yet been opened.
+ * Limitation: The file must exist. We do not support creation of files
+ * read-only.
+ */
+
+ else
+ {
+ /* Not already open.. create a new open structure */
+
+ ofile = (FAR struct nxffs_ofile_s *)kzalloc(sizeof(struct nxffs_ofile_s));
+ if (!ofile)
+ {
+ fdbg("ofile allocation failed\n");
+ return -ENOMEM;
+ }
+
+ /* Initialize the open file state structure */
+
+ ofile->crefs = 1;
+
+ /* Find the file on this volume associated with this file name */
+
+ ret = nxffs_findinode(volume, name, &ofile->entry);
+ if (ret != OK)
+ {
+ fdbg("Inode '%s' not found: %d\n", name, -ret);
+ kfree(ofile);
+ return ret;
+ }
+
+ /* Add the open file structure to the head of the list of open files */
+
+ ofile->flink = g_ofiles;
+ g_ofiles = ofile;
+ }
+
+ /* Return the open file state structure */
+
+ *ppofile = ofile;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nxffs_freeofile
+ ****************************************************************************/
+
+static inline void nxffs_freeofile(FAR struct nxffs_ofile_s *ofile)
+{
+ FAR struct nxffs_ofile_s *prev;
+ FAR struct nxffs_ofile_s *curr;
+
+ /* Find the open file structure to be removed */
+
+ for (prev = NULL, curr = g_ofiles;
+ curr && curr != ofile;
+ prev = curr, curr = curr->flink);
+
+ /* Was it found? */
+
+ if (curr)
+ {
+ /* Yes.. at the head of the list? */
+
+ if (prev)
+ {
+ prev->flink = ofile->flink;
+ }
+ else
+ {
+ g_ofiles = ofile->flink;
+ }
+
+ /* Then free the open file */
+
+ nxffs_freeentry(&ofile->entry);
+ kfree(ofile);
+ }
+ else
+ {
+ fdbg("ERROR: Open inode %p not found\n", ofile);
+ }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nxffs_findofile
+ *
+ * Description:
+ * Search the list of already opened files to see if the inode of this
+ * name is one of the opened files.
+ *
+ * Input Parameters:
+ * name - The name of the inode to check.
+ *
+ * Returned Value:
+ * If an inode of this name is found in the list of opened inodes, then
+ * a reference to the open file structure is returned. NULL is returned
+ * otherwise.
+ *
+ ****************************************************************************/
+
+FAR struct nxffs_ofile_s *nxffs_findofile(FAR const char *name)
+{
+ FAR struct nxffs_ofile_s *ofile;
+
+ /* Check every open file. Note that the volume exclsem protects the
+ * list of open files.
+ */
+
+ for (ofile = g_ofiles; ofile; ofile = ofile->flink)
+ {
+ /* Check for a name match */
+
+ if (strcmp(name, ofile->entry.name) == 0)
+ {
+ return ofile;
+ }
+ }
+
+ return NULL;
+}
+
+/****************************************************************************
+ * Name: nxffs_open
+ *
+ * Description:
+ * This is the standard mountpoint open method.
+ *
+ ****************************************************************************/
+
+int nxffs_open(FAR struct file *filep, FAR const char *relpath,
+ int oflags, mode_t mode)
+{
+ FAR struct nxffs_volume_s *volume;
+ FAR struct nxffs_ofile_s *ofile = NULL;
+ int ret;
+
+ fvdbg("Open '%s'\n", relpath);
+
+ /* Sanity checks */
+
+ DEBUGASSERT(filep->f_priv == NULL && filep->f_inode != NULL);
+
+ /* Get the mountpoint private data from the NuttX inode reference in the
+ * file structure
+ */
+
+ volume = (FAR struct nxffs_volume_s*)filep->f_inode->i_private;
+ DEBUGASSERT(volume != NULL);
+
+ /* Get exclusive access to the volume. Note that the volume exclsem
+ * protects the open file list.
+ */
+
+ ret = sem_wait(&volume->exclsem);
+ if (ret != OK)
+ {
+ ret = -errno;
+ fdbg("sem_wait failed: %d\n", ret);
+ goto errout;
+ }
+
+#ifdef CONFIG_FILE_MODE
+# warning "Missing check for privileges based on inode->i_mode"
+#endif
+
+ /* Limitation: A file must be opened for reading or writing, but not both.
+ * There is no general for extending the size of of a file. Extending the
+ * file size of possible if the file to be extended is the last in the
+ * sequence on FLASH, but since that case is not the general case, no file
+ * extension is supported.
+ */
+
+ switch (mode & (O_WROK|O_RDOK))
+ {
+ case 0:
+ default:
+ fdbg("One of O_WRONLY/O_RDONLY must be provided\n");
+ ret = -EINVAL;
+ goto errout_with_semaphore;
+
+ case O_WROK:
+ ret = nxffs_wropen(volume, relpath, mode, &ofile);
+ break;
+
+ case O_RDOK:
+ ret = nxffs_rdopen(volume, relpath, &ofile);
+ break;
+
+ case O_WROK|O_RDOK:
+ fdbg("O_RDWR is not supported\n");
+ ret = -ENOSYS;
+ goto errout_with_semaphore;
+ }
+
+ /* Save open-specific state in filep->f_priv */
+
+ filep->f_priv = ofile;
+ ret = OK;
+
+errout_with_semaphore:
+ sem_post(&volume->exclsem);
+errout:
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nxffs_close
+ *
+ * Description:
+ * This is the standard mountpoint close method.
+ *
+ ****************************************************************************/
+
+int nxffs_close(FAR struct file *filep)
+{
+ FAR struct nxffs_volume_s *volume;
+ FAR struct nxffs_ofile_s *ofile;
+ int ret = -ENOSYS;
+
+ fvdbg("Closing\n");
+
+ /* Sanity checks */
+
+ DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
+
+ /* Recover the open file state from the struct file instance */
+
+ ofile = (FAR struct nxffs_ofile_s *)filep->f_priv;
+
+ /* Recover the volume state from the open file */
+
+ volume = (FAR struct nxffs_volume_s *)filep->f_inode->i_private;
+ DEBUGASSERT(volume != NULL);
+
+ /* Get exclusive access to the volume. Note that the volume exclsem
+ * protects the open file list.
+ */
+
+ ret = sem_wait(&volume->exclsem);
+ if (ret != OK)
+ {
+ ret = -errno;
+ fdbg("sem_wait failed: %d\n", ret);
+ goto errout;
+ }
+
+ /* Decrement the reference count on the open file */
+
+ if (ofile->crefs == 1)
+ {
+ /* Decrementing the reference count would take it zero. Time to
+ * delete the open file state.
+ */
+
+ nxffs_freeofile(ofile);
+ }
+ else
+ {
+ /* Just decrement the reference count */
+
+ ofile->crefs--;
+ }
+
+ filep->f_priv = NULL;
+ ret = OK;
+
+ sem_post(&volume->exclsem);
+errout:
+ return ret;
+}
diff --git a/nuttx/fs/nxffs/nxffs_stat.c b/nuttx/fs/nxffs/nxffs_stat.c
new file mode 100644
index 000000000..57649dacc
--- /dev/null
+++ b/nuttx/fs/nxffs/nxffs_stat.c
@@ -0,0 +1,186 @@
+/****************************************************************************
+ * fs/nxffs/nxffs_stat.c
+ *
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * References: Linux/Documentation/filesystems/romfs.txt
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/stat.h>
+#include <sys/statfs.h>
+
+#include <string.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/fs.h>
+#include <nuttx/mtd.h>
+
+#include "nxffs.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nxffs_statfs
+ *
+ * Description: Return filesystem statistics
+ *
+ ****************************************************************************/
+
+int nxffs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf)
+{
+ FAR struct nxffs_volume_s *volume;
+ int ret;
+
+ fvdbg("Entry\n");
+
+ /* Sanity checks */
+
+ DEBUGASSERT(mountpt && mountpt->i_private);
+
+ /* Get the mountpoint private data from the NuttX inode structure */
+
+ volume = mountpt->i_private;
+ ret = sem_wait(&volume->exclsem);
+ if (ret != OK)
+ {
+ goto errout;
+ }
+
+ /* Fill in the statfs info */
+#warning "Need f_bfree, f_bavail, f_files, f_ffree calculation"
+
+ memset(buf, 0, sizeof(struct statfs));
+ buf->f_type = NXFFS_MAGIC;
+ buf->f_bsize = volume->geo.blocksize;
+ buf->f_blocks = volume->geo.neraseblocks * volume->blkper;
+ buf->f_namelen = volume->geo.blocksize - SIZEOF_NXFFS_BLOCK_HDR - SIZEOF_NXFFS_INODE_HDR;
+ ret = OK;
+
+ sem_post(&volume->exclsem);
+errout:
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nxffs_stat
+ *
+ * Description: Return information about a file or directory
+ *
+ ****************************************************************************/
+
+int nxffs_stat(FAR struct inode *mountpt, FAR const char *relpath,
+ FAR struct stat *buf)
+{
+ FAR struct nxffs_volume_s *volume;
+ struct nxffs_entry_s entry;
+ int ret;
+
+ fvdbg("Entry\n");
+
+ /* Sanity checks */
+
+ DEBUGASSERT(mountpt && mountpt->i_private && buf);
+
+ /* Get the mountpoint private data from the NuttX inode structure */
+
+ volume = mountpt->i_private;
+ ret = sem_wait(&volume->exclsem);
+ if (ret != OK)
+ {
+ goto errout;
+ }
+
+ /* Initialize the return stat instance */
+
+ memset(buf, 0, sizeof(struct stat));
+ buf->st_blksize = volume->geo.blocksize;
+ buf->st_blocks = entry.datlen / (volume->geo.blocksize - SIZEOF_NXFFS_BLOCK_HDR);
+
+ /* The requested directory must be the volume-relative "root" directory */
+
+ if (relpath && relpath[0] != '\0')
+ {
+ /* Not the top directory.. find the NXFFS inode with this name */
+
+ ret = nxffs_findinode(volume, relpath, &entry);
+ if (ret < 0)
+ {
+ fdbg("Inode '%s' not found: %d\n", -ret);
+ goto errout_with_semaphore;
+ }
+
+ buf->st_mode = S_IFREG|S_IXOTH|S_IXGRP|S_IXUSR;
+ buf->st_size = entry.datlen;
+ buf->st_atime = entry.utc;
+ buf->st_mtime = entry.utc;
+ buf->st_ctime = entry.utc;
+ }
+ else
+ {
+ /* It's a read/execute-only directory name */
+
+ buf->st_mode = S_IFDIR|S_IROTH|S_IRGRP|S_IRUSR|S_IXOTH|S_IXGRP|S_IXUSR;
+ }
+
+ ret = OK;
+
+errout_with_semaphore:
+ sem_post(&volume->exclsem);
+errout:
+ return ret;
+}
diff --git a/nuttx/fs/nxffs/nxffs_unlink.c b/nuttx/fs/nxffs/nxffs_unlink.c
new file mode 100644
index 000000000..46037a1b0
--- /dev/null
+++ b/nuttx/fs/nxffs/nxffs_unlink.c
@@ -0,0 +1,184 @@
+/****************************************************************************
+ * fs/nxffs/nxffs_unlink.c
+ *
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * References: Linux/Documentation/filesystems/romfs.txt
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/fs.h>
+#include <nuttx/mtd.h>
+
+#include "nxffs.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nxffs_rminode
+ *
+ * Description:
+ * Remove an inode from FLASH. This is the internal implementation of
+ * the file system unlinke operation.
+ *
+ * Input Parameters:
+ * volume - Describes the NXFFS volume.
+ * name - the name of the inode to be deleted.
+ *
+ * Returned Value:
+ * Zero is returned if the inode is successfully deleted. Otherwise, a
+ * negated errno value is returned indicating the nature of the failure.
+ *
+ ****************************************************************************/
+
+int nxffs_rminode(FAR struct nxffs_volume_s *volume, FAR const char *name)
+{
+ FAR struct nxffs_ofile_s *ofile;
+ FAR struct nxffs_inode_s *inode;
+ struct nxffs_entry_s entry;
+ int ret;
+
+ /* Check if the file is open */
+
+ ofile = nxffs_findofile(name);
+ if (ofile)
+ {
+ /* We can't remove the inode if it is open */
+
+ fdbg("Inode is open\n");
+ return -EBUSY;
+ }
+
+ /* Find the NXFFS inode */
+
+ ret = nxffs_findinode(volume, name, &entry);
+ if (ret < 0)
+ {
+ fdbg("Inode '%s' not found\n");
+ return ret;
+ }
+
+ /* Set the position to the FLASH offset of the file header (nxffs_findinode
+ * should have left the block in the cache).
+ */
+
+ nxffs_ioseek(volume, entry.hoffset);
+
+ /* Make sure the the block is in the cache */
+
+ ret = nxffs_rdcache(volume, volume->ioblock, 1);
+ if (ret < 0)
+ {
+ fdbg("Failed to read data into cache: %d\n", ret);
+ return ret;
+ }
+
+ /* Change the file status... it is no longer valid */
+
+ inode = (FAR struct nxffs_inode_s *)&volume->cache[volume->iooffset];
+ inode->state = INODE_STATE_DELETED;
+
+ /* Then write the cached block back to FLASH */
+
+ ret = nxffs_wrcache(volume, volume->ioblock, 1);
+ if (ret < 0)
+ {
+ fdbg("Failed to read data into cache: %d\n", ret);
+ return ret;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nxffs_unlink
+ *
+ * Description: Remove a file
+ *
+ ****************************************************************************/
+
+int nxffs_unlink(FAR struct inode *mountpt, FAR const char *relpath)
+{
+ FAR struct nxffs_volume_s *volume;
+ int ret;
+
+ fvdbg("Entry\n");
+
+ /* Sanity checks */
+
+ DEBUGASSERT(mountpt && mountpt->i_private);
+
+ /* Get the mountpoint private data from the NuttX inode structure */
+
+ volume = mountpt->i_private;
+ ret = sem_wait(&volume->exclsem);
+ if (ret != OK)
+ {
+ goto errout;
+ }
+
+ /* Then remove the NXFFS inode */
+
+ ret = nxffs_rminode(volume, relpath);
+
+ sem_post(&volume->exclsem);
+errout:
+ return ret;
+}
diff --git a/nuttx/fs/nxffs/nxffs_util.c b/nuttx/fs/nxffs/nxffs_util.c
index 9eea32243..5217fe09e 100644
--- a/nuttx/fs/nxffs/nxffs_util.c
+++ b/nuttx/fs/nxffs/nxffs_util.c
@@ -42,11 +42,6 @@
#include <nuttx/config.h>
#include <string.h>
-#include <errno.h>
-#include <assert.h>
-#include <debug.h>
-
-#include <nuttx/mtd.h>
#include "nxffs.h"
diff --git a/nuttx/include/sys/statfs.h b/nuttx/include/sys/statfs.h
index 9c7ee26e5..7f80902d6 100644
--- a/nuttx/include/sys/statfs.h
+++ b/nuttx/include/sys/statfs.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/sys/statfs.h
*
- * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Redistribution and use in source and binary forms, with or without
@@ -52,27 +52,27 @@
/* struct statfs file system types. */
#define ADFS_SUPER_MAGIC 0xadf5
-#define AFFS_SUPER_MAGIC 0xADFF
+#define AFFS_SUPER_MAGIC 0xadff
#define BEFS_SUPER_MAGIC 0x42465331
-#define BFS_MAGIC 0x1BADFACE
-#define CIFS_MAGIC_NUMBER 0xFF534D42
+#define BFS_MAGIC 0x1badface
+#define CIFS_MAGIC_NUMBER 0xff534d42
#define CODA_SUPER_MAGIC 0x73757245
-#define COH_SUPER_MAGIC 0x012FF7B7
+#define COH_SUPER_MAGIC 0x012ff7b7
#define CRAMFS_MAGIC 0x28cd3d45
#define DEVFS_SUPER_MAGIC 0x1373
-#define EFS_SUPER_MAGIC 0x00414A53
-#define EXT_SUPER_MAGIC 0x137D
-#define EXT2_OLD_SUPER_MAGIC 0xEF51
-#define EXT2_SUPER_MAGIC 0xEF53
-#define EXT3_SUPER_MAGIC 0xEF53
+#define EFS_SUPER_MAGIC 0x00414a53
+#define EXT_SUPER_MAGIC 0x137d
+#define EXT2_OLD_SUPER_MAGIC 0xef51
+#define EXT2_SUPER_MAGIC 0xef53
+#define EXT3_SUPER_MAGIC 0xef53
#define HFS_SUPER_MAGIC 0x4244
-#define HPFS_SUPER_MAGIC 0xF995E849
+#define HPFS_SUPER_MAGIC 0xf995e849
#define HUGETLBFS_MAGIC 0x958458f6
#define ISOFS_SUPER_MAGIC 0x9660
#define JFFS2_SUPER_MAGIC 0x72b6
#define JFS_SUPER_MAGIC 0x3153464a
-#define MINIX_SUPER_MAGIC 0x137F /* orig. minix */
-#define MINIX_SUPER_MAGIC2 0x138F /* 30 char minix */
+#define MINIX_SUPER_MAGIC 0x137f /* orig. minix */
+#define MINIX_SUPER_MAGIC2 0x138f /* 30 char minix */
#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 */
#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2, 30 char names */
#define MSDOS_SUPER_MAGIC 0x4d44
@@ -85,17 +85,21 @@
#define REISERFS_SUPER_MAGIC 0x52654973
#define ROMFS_MAGIC 0x7275
#define SMB_SUPER_MAGIC 0x517B
-#define SYSV2_SUPER_MAGIC 0x012FF7B6
+#define SYSV2_SUPER_MAGIC 0x012ff7b6
#define SYSV4_SUPER_MAGIC 0x012FF7B5
#define TMPFS_MAGIC 0x01021994
#define UDF_SUPER_MAGIC 0x15013346
#define UFS_MAGIC 0x00011954
#define USBDEVICE_SUPER_MAGIC 0x9fa2
-#define VXFS_SUPER_MAGIC 0xa501FCF5
-#define XENIX_SUPER_MAGIC 0x012FF7B4
+#define VXFS_SUPER_MAGIC 0xa501fcf5
+#define XENIX_SUPER_MAGIC 0x012ff7b4
#define XFS_SUPER_MAGIC 0x58465342
-#define _XIAFS_SUPER_MAGIC 0x012FD16D
+#define _XIAFS_SUPER_MAGIC 0x012fd16d
+
+/* NuttX specific file-systems */
+
#define BINFS_MAGIC 0x4242
+#define NXFFS_MAGIC 0x4747
/****************************************************************************
* Type Definitions