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 * - * 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 */ @@ -419,6 +407,28 @@ extern uint32_t nxffs_rdle32(const uint8_t *val); 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 * @@ -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 @@ -644,6 +654,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 * 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 @@ -115,6 +115,32 @@ int nxffs_rdcache(FAR struct nxffs_volume_s *volume, off_t block, return OK; } +/**************************************************************************** + * 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 * 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 + * + * 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 + +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 + * + * 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 + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#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 + * + * 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 + +#include +#include +#include +#include + +#include +#include + +#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 #include -#include -#include -#include - -#include #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 * * 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