summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/examples/nxffs/nxffs_main.c236
-rw-r--r--nuttx/fs/fs_mount.c161
-rw-r--r--nuttx/fs/nxffs/nxffs.h3
-rw-r--r--nuttx/fs/nxffs/nxffs_initialize.c1
-rw-r--r--nuttx/fs/nxffs/nxffs_inode.c1
-rw-r--r--nuttx/tools/mkconfig.c5
6 files changed, 369 insertions, 38 deletions
diff --git a/apps/examples/nxffs/nxffs_main.c b/apps/examples/nxffs/nxffs_main.c
index 2e046a26f..f4000b6ea 100644
--- a/apps/examples/nxffs/nxffs_main.c
+++ b/apps/examples/nxffs/nxffs_main.c
@@ -39,9 +39,16 @@
#include <nuttx/config.h>
+#include <sys/mount.h>
+
#include <stdint.h>
-#include <stdlib.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <crc32.h>
#include <nuttx/mtd.h>
#include <nuttx/nxffs.h>
@@ -68,19 +75,222 @@
#define CONFIG_EXAMPLES_NXFFS_BUFSIZE \
(CONFIG_RAMMTD_ERASESIZE * CONFIG_EXAMPLES_NXFFS_NEBLOCKS)
+#ifndef CONFIG_EXAMPLES_NXFFS_MAXNAME
+# define CONFIG_EXAMPLES_NXFFS_MAXNAME 128
+#endif
+
+#ifndef CONFIG_EXAMPLES_NXFFS_MAXFILE
+# define CONFIG_EXAMPLES_NXFFS_MAXFILE 8192
+#endif
+
+#ifndef CONFIG_EXAMPLES_NXFFS_GULP
+# define CONFIG_EXAMPLES_NXFFS_GULP 347
+#endif
+
+#ifndef CONFIG_EXAMPLES_NXFFS_MAXOPEN
+# define CONFIG_EXAMPLES_NXFFS_MAXOPEN 512
+#endif
+
+#ifndef CONFIG_EXAMPLES_NXFFS_MOUNTPT
+# define CONFIG_EXAMPLES_NXFFS_MOUNTPT "/mnt/nxffs"
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct nxffs_filedesc_s
+{
+ FAR char *name;
+ size_t len;
+ uint32_t crc;
+};
+
/****************************************************************************
* Private Data
****************************************************************************/
/* Pre-allocated simulated flash */
static uint8_t g_simflash[CONFIG_EXAMPLES_NXFFS_BUFSIZE];
+static uint8_t g_fileimage[CONFIG_EXAMPLES_NXFFS_MAXFILE];
+static struct nxffs_filedesc_s g_files[CONFIG_EXAMPLES_NXFFS_MAXOPEN];
+static const char g_mountdir[] = CONFIG_EXAMPLES_NXFFS_MOUNTPT "/";
+static int g_nfiles;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nxffs_randchar
+ ****************************************************************************/
+
+static inline char nxffs_randchar(void)
+{
+ int value = rand() % 63;
+ if (value == 0)
+ {
+ return '/';
+ }
+ else if (value <= 10)
+ {
+ return value + '0' - 1;
+ }
+ else if (value <= 36)
+ {
+ return value + 'a' - 11;
+ }
+ else /* if (value <= 62) */
+ {
+ return value + 'A' - 37;
+ }
+}
+
+/****************************************************************************
+ * Name: nxffs_randname
+ ****************************************************************************/
+
+static inline void nxffs_randname(FAR struct nxffs_filedesc_s *file)
+{
+ int dirlen;
+ int maxname;
+ int namelen;
+ int alloclen;
+ int i;
+
+ dirlen = strlen(g_mountdir);
+ maxname = CONFIG_EXAMPLES_NXFFS_MAXNAME - dirlen;
+ namelen = (rand() % maxname) + 1;
+ alloclen = namelen + dirlen;
+
+ file->name = (FAR char*)malloc(alloclen + 1);
+ if (!file->name)
+ {
+ fprintf(stderr, "ERROR: Failed to allocate name, length=%d\n", namelen);
+ exit(3);
+ }
+
+ memcpy(file->name, g_mountdir, dirlen);
+ for (i = dirlen; i < alloclen; i++)
+ {
+ file->name[i] = nxffs_randchar();
+ }
+
+ file->name[alloclen] = '\0';
+}
+
+/****************************************************************************
+ * Name: nxffs_randfile
+ ****************************************************************************/
+
+static inline void nxffs_randfile(FAR struct nxffs_filedesc_s *file)
+{
+ int i;
+
+ file->len = (rand() % CONFIG_EXAMPLES_NXFFS_MAXFILE) + 1;
+ for (i = 0; i < file->len; i++)
+ {
+ g_fileimage[i] = nxffs_randchar();
+ }
+ file->crc = crc32(g_fileimage, file->len);
+}
+
+/****************************************************************************
+ * Name: nxffs_freefile
+ ****************************************************************************/
+
+static void nxffs_freefile(FAR struct nxffs_filedesc_s *file)
+{
+ if (file->name)
+ {
+ free(file->name);
+ }
+ memset(file, 0, sizeof(struct nxffs_filedesc_s));
+}
+
+/****************************************************************************
+ * Name: nxffs_wrfile
+ ****************************************************************************/
+
+static inline int nxffs_wrfile(void)
+{
+ struct nxffs_filedesc_s *file = NULL;
+ size_t offset;
+ int fd;
+ int i;
+
+ for (i = 0; i < CONFIG_EXAMPLES_NXFFS_MAXOPEN; i++)
+ {
+ if (g_files[i].name == NULL)
+ {
+ file = &g_files[i];
+ break;
+ }
+ }
+
+ if (!file)
+ {
+ fprintf(stderr, "No available files\n");
+ return ERROR;
+ }
+
+ nxffs_randname(file);
+ nxffs_randfile(file);
+ fd = open(file->name, O_WRONLY, 0666);
+ if (fd < 0)
+ {
+ fprintf(stderr, "Failed to open file: %d\n", errno);
+ fprintf(stderr, " File name: %s\n", file->name);
+ fprintf(stderr, " File size: %d\n", file->len);
+ nxffs_freefile(file);
+ return ERROR;
+ }
+
+ for (offset = 0; offset < file->len; )
+ {
+ size_t nbytestowrite = file->len - offset;
+ ssize_t nbyteswritten;
+
+ if (nbytestowrite > CONFIG_EXAMPLES_NXFFS_GULP)
+ {
+ nbytestowrite = CONFIG_EXAMPLES_NXFFS_GULP;
+ }
+
+ nbyteswritten = write(fd, &g_fileimage[offset], nbytestowrite);
+ if (nbyteswritten < 0)
+ {
+ fprintf(stderr, "Failed to write file: %d\n", errno);
+ fprintf(stderr, " File name: %s\n", file->name);
+ fprintf(stderr, " File size: %d\n", file->len);
+ fprintf(stderr, " Write offset: %d\n", offset);
+ fprintf(stderr, " Write size: %d\n", nbytestowrite);
+ nxffs_freefile(file);
+ close(fd);
+ return ERROR;
+ }
+ else if (nbyteswritten != nbytestowrite)
+ {
+ fprintf(stderr, "Partial write: %d\n");
+ fprintf(stderr, " File name: %s\n", file->name);
+ fprintf(stderr, " File size: %d\n", file->len);
+ fprintf(stderr, " Write offset: %d\n", offset);
+ fprintf(stderr, " Write size: %d\n", nbytestowrite);
+ fprintf(stderr, " Written: %d\n", nbyteswritten);
+ }
+ offset += nbyteswritten;
+ }
+
+ close(fd);
+ g_nfiles++;
+ return OK;
+}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
- * user_start
+ * Name: user_start
****************************************************************************/
int user_start(int argc, char *argv[])
@@ -88,6 +298,10 @@ int user_start(int argc, char *argv[])
FAR struct mtd_dev_s *mtd;
int ret;
+ /* Seed the random number generated */
+
+ srand(0x93846);
+
/* Create and initialize a RAM MTD device instance */
mtd = rammtd_initialize(g_simflash, CONFIG_EXAMPLES_NXFFS_BUFSIZE);
@@ -106,6 +320,24 @@ int user_start(int argc, char *argv[])
exit(2);
}
+ /* Mount the file system */
+
+ ret = mount(NULL, CONFIG_EXAMPLES_NXFFS_MOUNTPT, "nxffs", 0, NULL);
+ if (ret < 0)
+ {
+ fprintf(stderr, "ERROR: Failed to mount the NXFFS volume: %d\n", errno);
+ exit(3);
+ }
+
+ /* Then write a file to the NXFFS file system */
+
+ ret = nxffs_wrfile();
+ if (ret < 0)
+ {
+ fprintf(stderr, "ERROR: Failed to write a file\n");
+ exit(3);
+ }
+
return 0;
}
diff --git a/nuttx/fs/fs_mount.c b/nuttx/fs/fs_mount.c
index 02317ef19..803f4e797 100644
--- a/nuttx/fs/fs_mount.c
+++ b/nuttx/fs/fs_mount.c
@@ -41,8 +41,10 @@
#include <sys/mount.h>
#include <string.h>
-#include <debug.h>
#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
#include <nuttx/fs.h>
#ifdef CONFIG_APPS_BINDIR
@@ -62,6 +64,23 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
+/* Configuration ************************************************************/
+/* In the canonical case, a file system is bound to a block driver. However,
+ * some less typical cases a block driver is not required. Examples are
+ * pseudo file systems (like BINFS) and MTD file systems (like NXFFS).
+ *
+ * These file systems all require block drivers:
+ */
+
+#if defined(CONFIG_FS_FAT) || defined(CONFIG_FS_ROMFS)
+# define BDFS_SUPPORT 1
+#endif
+
+/* These file systems do not require block drivers */
+
+#if defined(CONFIG_FS_NXFFS) || defined(CONFIG_APPS_BINDIR)
+# define NONBDFS_SUPPORT
+#endif
/****************************************************************************
* Private Types
@@ -69,14 +88,15 @@
struct fsmap_t
{
- const char *fs_filesystemtype;
- const struct mountpt_operations *fs_mops;
+ FAR const char *fs_filesystemtype;
+ FAR const struct mountpt_operations *fs_mops;
};
/****************************************************************************
* Private Variables
****************************************************************************/
+#ifdef BDFS_SUPPORT
#ifdef CONFIG_FS_FAT
extern const struct mountpt_operations fat_operations;
#endif
@@ -84,7 +104,7 @@ extern const struct mountpt_operations fat_operations;
extern const struct mountpt_operations romfs_operations;
#endif
-static const struct fsmap_t g_fsmap[] =
+static const struct fsmap_t g_bdfsmap[] =
{
#ifdef CONFIG_FS_FAT
{ "vfat", &fat_operations },
@@ -92,11 +112,26 @@ static const struct fsmap_t g_fsmap[] =
#ifdef CONFIG_FS_ROMFS
{ "romfs", &romfs_operations },
#endif
+ { NULL, NULL },
+};
+#endif /* BDFS_SUPPORT*/
+
+#ifdef NONBDFS_SUPPORT
+#ifdef CONFIG_FS_NXFFS
+extern const struct mountpt_operations nxffs_operations;
+#endif
+
+static const struct fsmap_t g_nonbdfsmap[] =
+{
+#ifdef CONFIG_FS_NXFFS
+ { "nxffs", &nxffs_operations },
+#endif
#ifdef CONFIG_APPS_BINDIR
{ "binfs", &binfs_operations },
#endif
{ NULL, NULL },
};
+#endif /* NONBDFS_SUPPORT */
/****************************************************************************
* Public Variables
@@ -114,10 +149,12 @@ static const struct fsmap_t g_fsmap[] =
*
****************************************************************************/
-static FAR const struct mountpt_operations *mount_findfs(const char *filesystemtype )
+#if defined(BDFS_SUPPORT) || defined(NONBDFS_SUPPORT)
+static FAR const struct mountpt_operations *
+mount_findfs(FAR const struct fsmap_t *fstab, FAR const char *filesystemtype)
{
- const struct fsmap_t *fsmap;
- for (fsmap = g_fsmap; fsmap->fs_filesystemtype; fsmap++)
+ FAR const struct fsmap_t *fsmap;
+ for (fsmap = fstab; fsmap->fs_filesystemtype; fsmap++)
{
if (strcmp(filesystemtype, fsmap->fs_filesystemtype) == 0)
{
@@ -126,6 +163,7 @@ static FAR const struct mountpt_operations *mount_findfs(const char *filesystemt
}
return NULL;
}
+#endif
/****************************************************************************
* Public Functions
@@ -159,7 +197,10 @@ int mount(const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags,
const void *data)
{
- FAR struct inode *blkdrvr_inode;
+#if defined(BDFS_SUPPORT) || defined(NONBDFS_SUPPORT)
+#ifdef BDFS_SUPPORT
+ FAR struct inode *blkdrvr_inode = NULL;
+#endif
FAR struct inode *mountpt_inode;
FAR const struct mountpt_operations *mops;
void *fshandle;
@@ -168,33 +209,42 @@ int mount(const char *source, const char *target,
/* Verify required pointer arguments */
- if (!source || !target || !filesystemtype)
- {
- errcode = EFAULT;
- goto errout;
- }
+ DEBUGASSERT(target && filesystemtype);
- /* Find the specified filesystem */
+ /* Find the specified filesystem. Try the block driver file systems first */
- mops = mount_findfs(filesystemtype);
- if (!mops)
+#ifdef BDFS_SUPPORT
+ if ((mops = mount_findfs(g_bdfsmap, filesystemtype)) != NULL)
{
- fdbg("Failed to find filsystem %s\n", filesystemtype);
- errcode = ENODEV;
- goto errout;
- }
+ /* Make sure that a block driver argument was provided */
- /* Find the inode of the block driver indentified by 'source' */
+ DEBUGASSERT(source);
- status = find_blockdriver(source, mountflags, &blkdrvr_inode);
- if (status < 0)
+ /* Find the block driver */
+
+ status = find_blockdriver(source, mountflags, &blkdrvr_inode);
+ if (status < 0)
+ {
+ fdbg("Failed to find block driver %s\n", source);
+ errcode = -status;
+ goto errout;
+ }
+ }
+ else
+#endif /* BDFS_SUPPORT */
+#ifdef NONBDFS_SUPPORT
+ if ((mops = mount_findfs(g_nonbdfsmap, filesystemtype)) != NULL)
{
- fdbg("Failed to find block driver %s\n", source);
- errcode = -status;
- goto errout;
+ }
+ else
+#endif /* NONBDFS_SUPPORT */
+ {
+ fdbg("Failed to find file system %s\n", filesystemtype);
+ errcode = ENODEV;
+ goto errout;
}
- /* Insert a dummy node -- we need to hold the inode semaphore
+ /* Insert a dummy node -- we need to hold the inode semaphore
* to do this because we will have a momentarily bad structure.
*/
@@ -227,11 +277,22 @@ int mount(const char *source, const char *target,
/* Increment reference count for the reference we pass to the file system */
- blkdrvr_inode->i_crefs++;
+#ifdef BDFS_SUPPORT
+#ifdef NONBDFS_SUPPORT
+ if (blkdrvr_inode)
+#endif
+ {
+ blkdrvr_inode->i_crefs++;
+ }
+#endif
/* On failure, the bind method returns -errorcode */
+#ifdef BDFS_SUPPORT
status = mops->bind(blkdrvr_inode, data, &fshandle);
+#else
+ status = mops->bind(NULL, data, &fshandle);
+#endif
if (status != 0)
{
/* The inode is unhappy with the blkdrvr for some reason. Back out
@@ -240,7 +301,14 @@ int mount(const char *source, const char *target,
*/
fdbg("Bind method failed: %d\n", status);
- blkdrvr_inode->i_crefs--;
+#ifdef BDFS_SUPPORT
+#ifdef NONBDFS_SUPPORT
+ if (blkdrvr_inode)
+#endif
+ {
+ blkdrvr_inode->i_crefs--;
+ }
+#endif
errcode = -status;
goto errout_with_mountpt;
}
@@ -262,7 +330,14 @@ int mount(const char *source, const char *target,
* that will persist until umount() is called.
*/
- inode_release(blkdrvr_inode);
+#ifdef BDFS_SUPPORT
+#ifdef NONBDFS_SUPPORT
+ if (blkdrvr_inode)
+#endif
+ {
+ inode_release(blkdrvr_inode);
+ }
+#endif
return OK;
/* A lot of goto's! But they make the error handling much simpler */
@@ -271,18 +346,38 @@ errout_with_mountpt:
mountpt_inode->i_crefs = 0;
inode_remove(target);
inode_semgive();
- inode_release(blkdrvr_inode);
+#ifdef BDFS_SUPPORT
+#ifdef NONBDFS_SUPPORT
+ if (blkdrvr_inode)
+#endif
+ {
+ inode_release(blkdrvr_inode);
+ }
+#endif
inode_release(mountpt_inode);
goto errout;
errout_with_semaphore:
inode_semgive();
- inode_release(blkdrvr_inode);
+#ifdef BDFS_SUPPORT
+#ifdef NONBDFS_SUPPORT
+ if (blkdrvr_inode)
+#endif
+ {
+ inode_release(blkdrvr_inode);
+ }
+#endif
errout:
errno = errcode;
return ERROR;
+
+#else
+ fdbg("No filesystems enabled\n");
+ ernno = ENOSYS;
+ return error;
+#endif /* BDFS_SUPPORT || NONBDFS_SUPPORT */
}
-#endif /* Need at least one filesystem */
+#endif /* CONFIG_FS_READABLE */
diff --git a/nuttx/fs/nxffs/nxffs.h b/nuttx/fs/nxffs/nxffs.h
index 5b1809ebc..41421c57e 100644
--- a/nuttx/fs/nxffs/nxffs.h
+++ b/nuttx/fs/nxffs/nxffs.h
@@ -157,8 +157,9 @@
*
* INODE_STATE_FILE - The inode is a valid usuable, file
* INODE_STATE_DELETED - The inode has been deleted.
+ * Other values - The inode is bad and has an invalid state.
*
- * Care is taken so that the GOOD to BAD transition only involves burning
+ * Care is taken so that the VALID to DELETED transition only involves burning
* bits from the erased to non-erased state.
*/
diff --git a/nuttx/fs/nxffs/nxffs_initialize.c b/nuttx/fs/nxffs/nxffs_initialize.c
index fc2d97b65..4b4e272a2 100644
--- a/nuttx/fs/nxffs/nxffs_initialize.c
+++ b/nuttx/fs/nxffs/nxffs_initialize.c
@@ -182,6 +182,7 @@ int nxffs_initialize(FAR struct mtd_dev_s *mtd)
/* Initialize the NXFFS volume structure */
volume->mtd = mtd;
+ sem_init(&volume->exclsem, 0, 1);
/* Get the volume geometry. (casting to uintptr_t first eliminates
* complaints on some architectures where the sizeof long is different
diff --git a/nuttx/fs/nxffs/nxffs_inode.c b/nuttx/fs/nxffs/nxffs_inode.c
index ae61c9d24..cf87fdb5b 100644
--- a/nuttx/fs/nxffs/nxffs_inode.c
+++ b/nuttx/fs/nxffs/nxffs_inode.c
@@ -42,6 +42,7 @@
#include <nuttx/config.h>
#include <string.h>
+#include <crc32.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
diff --git a/nuttx/tools/mkconfig.c b/nuttx/tools/mkconfig.c
index a10f359d3..c8a6fb261 100644
--- a/nuttx/tools/mkconfig.c
+++ b/nuttx/tools/mkconfig.c
@@ -198,10 +198,11 @@ int main(int argc, char **argv, char **envp)
printf("/* Check if any readable and writable filesystem (OR USB storage) is supported */\n\n");
printf("#undef CONFIG_FS_READABLE\n");
printf("#undef CONFIG_FS_WRITABLE\n");
- printf("#if defined(CONFIG_FS_FAT) || defined(CONFIG_FS_ROMFS) || defined(CONFIG_USBSTRG)\n");
+ printf("#if defined(CONFIG_FS_FAT) || defined(CONFIG_FS_ROMFS) || defined(CONFIG_USBSTRG) || \\\n");
+ printf(" defined(CONFIG_FS_NXFFS) || defined(CONFIG_APPS_BINDIR)\n");
printf("# define CONFIG_FS_READABLE 1\n");
printf("#endif\n\n");
- printf("#if defined(CONFIG_FS_FAT) || defined(CONFIG_USBSTRG)\n");
+ printf("#if defined(CONFIG_FS_FAT) || defined(CONFIG_USBSTRG) || defined(CONFIG_FS_NXFFS)\n");
printf("# define CONFIG_FS_WRITABLE 1\n");
printf("#endif\n\n");
printf("/* There can be no network support with no socket descriptors */\n\n");