diff packages/redboot/current/src/fs/fileio.c @ 2257:467fd46113f3

* src/fs/fileio.c (do_list): Use getcwd for current directory, rather than "." which may not be implemented in the FS. * src/parse.c (redboot_exec): Conditionalise use of __mem_fault_handler to only be when stubs are included. (error_handler): Ditto for this function. * src/main.c (cyg_start): Conditionalise use of __mem_fault_handler to only be when stubs are included. (do_go): Ditto. (error_handler): Ditto for this function. * src/fs/fileio.c (do_mkdir, do_deldir, do_del, do_write): Added some extra argument checking to these functions. * src/fs/fileio.c (do_mount): Only support -f with "legacy" flash block devices. Clear mount table on failure. (do_move): Silence rename undefined warning. (do_write): Silence warnings. (do_info): Support longer device names. * src/decompress.c (ZLIB_COMPRESSION_OVERHEAD): Increase substantially if jffs2 is present. * src/fs/fileio.c: Fixed some bugs in handling of mounts. The strings used in the mount table must be copied, otherwise the mount table is corrupted by later commands. Also toughened up some error testing. * doc/redboot_cmds.sgml: Added file mode documentation to load command. * doc/redboot_cmds.sgml: Added documentation of filesystem access commands. * src/fs/fileio.c (do_write): Added O_TRUNC to the open call to ensure that the file is resized to fit the new data. * src/fs/fileio.c: Significantly reorganized to present an interface similar to the fis commands. Added a variety of command to manipulate files and directories in a filesystem. * src/parse.c: Added redboot_exec() to provide an internal interface for executing RedBoot commands. Added err_printf() which allows an error message to be printed before longjumping out to an enclosing call to redboot_exec(). Where redboot_exec() is not involved, it just behaves like diag_printf(). * src/main.c: Removed unnecessary delay during startup. Changed diag_printf() in do_go() into err_printf(). * src/load.c: Changed some calls to diag_printf() to err_printf(). * src/net/net_io.c: Changed init priority to RedBoot_INIT_NET. * include/redboot.h: Added some extra initialization priorities. Added prototypes for redboot_exec() and err_printf().
author jlarmour
date Thu, 20 Jul 2006 20:27:47 +0000
parents a0d4c606e72d
children 09f5e65f57b1
line wrap: on
line diff
--- a/packages/redboot/current/src/fs/fileio.c
+++ b/packages/redboot/current/src/fs/fileio.c
@@ -10,6 +10,7 @@
 // This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
 // Copyright (C) 2002, 2003, 2004 Gary Thomas
+// Copyright (C) 2004, 2005, 2006 eCosCentric Limited.
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
@@ -34,15 +35,14 @@
 // This exception does not invalidate any other reasons why a work based on
 // this file might be covered by the GNU General Public License.
 //
-// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
-// at http://sources.redhat.com/ecos/ecos-license/
 // -------------------------------------------
 //####ECOSGPLCOPYRIGHTEND####
 //==========================================================================
 //#####DESCRIPTIONBEGIN####
 //
-// Author(s):    dwmw2, msalter
-// Date:         2003-11-27
+// Author(s):    nickg
+// Contributors: dwmw2, msalter
+// Date:         2004-11-21
 // Purpose:      
 // Description:  
 //              
@@ -68,45 +68,86 @@
 #include <cyg/io/flash.h>
 #include <cyg/io/config_keys.h>
 #endif
+#include <cyg/io/devtab.h>
 #include <cyg/fileio/fileio.h>
 #include <cyg/infra/cyg_ass.h>         // assertion macros
 
+//==========================================================================
+
+// Define table boundaries
+CYG_HAL_TABLE_BEGIN( __FS_cmds_TAB__, FS_cmds);
+CYG_HAL_TABLE_END( __FS_cmds_TAB_END__, FS_cmds);
+
+extern struct cmd __FS_cmds_TAB__[], __FS_cmds_TAB_END__;
+
+//==========================================================================
+
+static void
+fs_usage(char *why)
+{
+    diag_printf("*** invalid 'fs' command: %s\n", why);
+    cmd_usage(__FS_cmds_TAB__, &__FS_cmds_TAB_END__, "fs ");
+}
+
+
+//==========================================================================
+
+#define MAX_MOUNTS      4
+
+static int mount_count = 0;
+
+static struct
+{
+    char dev_str[PATH_MAX];
+    char mp_str[PATH_MAX];
+    char type_str[PATH_MAX];
+} mounts[MAX_MOUNTS];
+
+//==========================================================================
+
 static void do_mount(int argc, char *argv[]);
 static void do_umount(int argc, char *argv[]);
 
-#ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE
+#ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY
 #define FLASHPART "[-f <partition>] "
 #else
 #define FLASHPART
 #endif
 
-RedBoot_cmd("mount", 
-            "Mount file system",
-	    FLASHPART "[-d <device>] -t fstype",
-            do_mount
+local_cmd_entry("mount", 
+                "Mount file system",
+                FLASHPART "[-d <device>] -t <fstype> [<mountpoint>]",
+                do_mount,
+                FS_cmds
     );
-RedBoot_cmd("umount", 
-            "Unmount file system",
-            "",
-            do_umount
+local_cmd_entry("umount", 
+                "Unmount file system",
+                "<mountpoint>",
+                do_umount,
+                FS_cmds
     );
 
-int fileio_mounted = 0;
+//==========================================================================
 
 // Mount disk/filesystem
 static void
 do_mount(int argc, char *argv[])
 {
-    char *part_str, *dev_str, *type_str;
-    bool part_set = false, dev_set = false, type_set = false;
+    char *dev_str = "<undefined>", *type_str, *mp_str;
+    bool dev_set = false, type_set = false;
     struct option_info opts[3];
     int err, num_opts = 2;
+    int i,m=0; /* Set to 0 to silence warning */
+#ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY
+    char *part_str;
+    bool part_set = false;
+#endif
 
     init_opts(&opts[0], 'd', true, OPTION_ARG_TYPE_STR,
               (void *)&dev_str, &dev_set, "device");
     init_opts(&opts[1], 't', true, OPTION_ARG_TYPE_STR,
               (void *)&type_str, &type_set, "fstype");
-#ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE
+#ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY
     init_opts(&opts[2], 'f', true, OPTION_ARG_TYPE_STR,
               (void *)&part_str, &part_set, "partition");
     num_opts++;
@@ -114,24 +155,30 @@ do_mount(int argc, char *argv[])
 
     CYG_ASSERT(num_opts <= NUM_ELEMS(opts), "Too many options");
 
-    if (!scan_opts(argc, argv, 1, opts, num_opts, NULL, 0, NULL))
+    if (!scan_opts(argc, argv, 1, opts, num_opts, &mp_str, OPTION_ARG_TYPE_STR, "mountpoint"))
         return;
 
     if (!type_set) {
-        diag_printf("Must specify file system type\n");
+        err_printf("fs mount: Must specify file system type\n");
         return;
     }
-    if (fileio_mounted) {
-        diag_printf("A file system is already mounted\n");
+
+    if( mp_str == 0 )
+        mp_str = "/";
+
+    if( mount_count >= MAX_MOUNTS )
+    {
+        err_printf("fs mount: Maximum number of mounts exceeded\n");
         return;
     }
-#ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE
+    
+#ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY
     if (part_set) {
         int len;
         cyg_io_handle_t h;
 
         if (dev_set && strcmp(dev_str, CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1)) {
-            diag_printf("May only set one of <device> or <partition>\n");
+            err_printf("fs mount: May only set one of <device> or <partition>\n");
             return;
         }
 
@@ -140,78 +187,132 @@ do_mount(int argc, char *argv[])
 
         err = cyg_io_lookup(dev_str, &h);
         if (err < 0) {
-            diag_printf("cyg_io_lookup of \"%s\" returned %d\n", err);
+            err_printf("fs mount: cyg_io_lookup of \"%s\" returned %d\n", err);
             return;
         }
         err = cyg_io_set_config(h, CYG_IO_SET_CONFIG_FLASH_FIS_NAME,
                                 part_str, &len);
         if (err < 0) {
-            diag_printf("FIS partition \"%s\" not found\n",
+            diag_printf("fs mount: FIS partition \"%s\" not found\n",
                         part_str);
             return;
         }
     }
 #endif
-    err = mount(dev_str, "/", type_str);
+
+    for( i = 0; i < MAX_MOUNTS; i++ )
+    {
+        if( mounts[i].mp_str[0] != '\0' )
+        {
+            if( strcmp(mounts[i].dev_str, dev_str ) == 0 )
+            {
+                err_printf("fs mount: Device %s already mounted\n",dev_str);
+                return;
+            }
+        }
+        else
+            m = i;
+    }
 
-    if (err) {
-        diag_printf("Mount failed %d\n", err);
-    } else {
-//        diag_printf("Mount %s file system succeeded\n", type_str);
-        fileio_mounted = 1;
-#ifdef CYGBLD_REDBOOT_FILEIO_WITH_LS
-        chdir("/");
-#endif        
+    strcpy( mounts[m].mp_str, mp_str );
+    strcpy( mounts[m].dev_str, dev_str );
+    strcpy( mounts[m].type_str, type_str );
+    
+    err = mount(mounts[m].dev_str, mounts[m].mp_str, mounts[m].type_str);
+
+    if (err)
+    {
+        err_printf("fs mount: mount(%s,%s,%s) failed %d\n", dev_str, mp_str, type_str, errno);
+        mounts[m].mp_str[0] = '\0'; // mount failed so don't let it appear mounted
+    }
+    else
+    {
+        if( mount_count == 0 )
+            chdir( "/" );
+        mount_count++;
     }
 }
 
+//==========================================================================
+
 static void
 do_umount(int argc, char *argv[])
 {
-    if (!fileio_mounted) {
+    char *dir_str;
+    int err;
+    int i;
+    
+     if( mount_count == 0 )
+     {
+         err_printf("fs: No filesystems mounted\n");
+         return;
+     }
+     
+    if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "mountpoint"))
+        return;
+
+    if( dir_str == 0 )
+        dir_str = "/";
+
+    for( i = 0; i < MAX_MOUNTS; i++ )
+    {
+        if( strcmp(mounts[i].mp_str, dir_str ) == 0 )
+            break;
+    }
+
+    if( i == MAX_MOUNTS )
+    {
+        err_printf("fs unmount: unknown mountpoint %s\n",dir_str);
         return;
     }
-    umount ("/");
-    fileio_mounted = 0;
+    
+    err = umount (dir_str);
+
+    if (err)
+        err_printf("fs umount: unmount failed %d\n", errno);
+    else
+    {
+        mounts[i].mp_str[0] = '\0';
+        mount_count--;
+        if( mount_count == 0 )
+            chdir( "/" );
+    }
+    
 }
 
-#ifdef CYGBLD_REDBOOT_FILEIO_WITH_LS
+//==========================================================================
+
 #include <dirent.h>
 
 static char rwx[8][4] = { "---", "r--", "-w-", "rw-", "--x", "r-x", "-wx", "rwx" }; 
 
 static void 
-do_ls(int argc, char * argv[])
+do_list(int argc, char * argv[])
 {
      char * dir_str;
-     struct option_info opts[1];
-     bool dir_set = false;
      DIR *dirp;
+     char filename[PATH_MAX];
      char cwd[PATH_MAX];
-     char filename[PATH_MAX];
      struct stat sbuf;
      int err;
-     
-     init_opts(&opts[0], 'd', true, OPTION_ARG_TYPE_STR,
-               (void *)&dir_str, &dir_set, "directory");
-     
-     if (!fileio_mounted) {
-          diag_printf("No filesystem mounted\n");
-          return;
+
+     if( mount_count == 0 )
+     {
+         err_printf("fs: No filesystems mounted\n");
+         return;
      }
      
-     if (!scan_opts(argc, argv, 1, opts, 1, NULL, 0, NULL))
+     if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "directory"))
           return;
 
-     if (!dir_set) {
-          getcwd(cwd,sizeof(cwd));
-          dir_str = cwd;
+     if( dir_str == 0 )
+     {
+         dir_str = getcwd(cwd, sizeof(cwd));
      }
      
-     diag_printf("directory %s\n",dir_str);
      dirp = opendir(dir_str);
      if (dirp==NULL) {
-          diag_printf("no such directory %s\n",dir_str);
+          err_printf("fs list: no such directory %s\n",dir_str);
           return;
      }
      
@@ -249,13 +350,350 @@ do_ls(int argc, char * argv[])
      return;
 }
 
-RedBoot_cmd("ls", 
-            "list directory contents",
-            "[-d directory]",
-            do_ls
+local_cmd_entry("list", 
+                "list directory contents",
+                "[<directory>]",
+                do_list,
+                FS_cmds
+    );
+
+
+//==========================================================================
+
+
+static void 
+do_mkdir(int argc, char * argv[])
+{
+    char *dir_str;
+    int err;
+    
+     if( mount_count == 0 )
+     {
+         err_printf("fs: No filesystems mounted\n");
+         return;
+     }
+     
+    if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "directory") ||
+        dir_str == NULL)
+    {
+        fs_usage("invalid arguments");
+        return;
+    }
+
+    err = mkdir( dir_str, 0 );
+
+    if( err != 0 )
+        err_printf("fs mkdir: failed to create directory %s\n",dir_str);
+}
+
+local_cmd_entry("mkdir", 
+                "create directory",
+                "<directory>",
+                do_mkdir,
+                FS_cmds
+    );
+
+//==========================================================================
+
+static void 
+do_deldir(int argc, char * argv[])
+{
+    char *dir_str;
+    int err;
+    
+     if( mount_count == 0 )
+     {
+         err_printf("fs: No filesystems mounted\n");
+         return;
+     }
+     
+    if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "directory") ||
+        dir_str == NULL)
+    {
+        fs_usage("invalid arguments");
+        return;
+    }
+
+    err = rmdir( dir_str );
+
+    if( err != 0 )
+        err_printf("fs deldir: failed to remove directory %s\n",dir_str);
+}
+
+local_cmd_entry("deldir", 
+                "delete directory",
+                "<directory>",
+                do_deldir,
+                FS_cmds
+    );
+
+//==========================================================================
+
+static void 
+do_del(int argc, char * argv[])
+{
+    char *name_str = NULL;
+    int err;
+    
+     if( mount_count == 0 )
+     {
+         err_printf("fs: No filesystems mounted\n");
+         return;
+     }
+     
+    if (!scan_opts(argc, argv, 1, NULL, 0, &name_str, OPTION_ARG_TYPE_STR, "file") ||
+        name_str == NULL)
+    {
+        fs_usage("invalid arguments");
+        return;
+    }
+
+    err = unlink( name_str );
+
+    if( err != 0 )
+        err_printf("fs del: failed to delete file %s\n",name_str);
+}
+
+local_cmd_entry("del", 
+                "delete file",
+                "<file>",
+                do_del,
+                FS_cmds
+    );
+
+//==========================================================================
+
+static void 
+do_move(int argc, char * argv[])
+{
+    int err;
+    __externC int rename( const char *oldname, const char *newname );
+    if( mount_count == 0 )
+    {
+        err_printf("fs: No filesystems mounted\n");
+        return;
+    }
+
+    if( argc != 3 )
+        fs_usage("bad arguments to move command\n");
+
+    err = rename( argv[1], argv[2] );
+
+    if( err != 0 )
+        err_printf("fs move: failed to move file %s to %s\n",argv[1],argv[2]);
+}
+
+local_cmd_entry("move", 
+                "move file",
+                "<from> <to>",
+                do_move,
+                FS_cmds
     );
 
-#endif // CYGBLD_REDBOOT_FILEIO_WITH_LS
+//==========================================================================
+
+static void 
+do_cd(int argc, char * argv[])
+{
+    char *dir_str;
+    int err;
+    
+     if( mount_count == 0 )
+     {
+         err_printf("fs: No filesystems mounted\n");
+         return;
+     }
+     
+    if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "directory"))
+        return;
+
+    if( dir_str == NULL )
+        dir_str = "/";
+    
+    err = chdir( dir_str );
+
+    if( err != 0 )
+        err_printf("fs cd: failed to change directory %s\n",dir_str);
+}
+
+local_cmd_entry("cd", 
+                "change directory",
+                "[<directory>]",
+                do_cd,
+                FS_cmds
+    );
+
+//==========================================================================
+
+static void 
+do_write(int argc, char * argv[])
+{
+    char *name_str = NULL;
+    int err;
+    struct option_info opts[2];    
+    CYG_ADDRESS mem_addr = 0;
+    unsigned long length = 0;
+    bool mem_addr_set = false;
+    bool length_set = false;
+    int fd;
+    
+     if( mount_count == 0 )
+     {
+         err_printf("fs: No filesystems mounted\n");
+         return;
+     }
+
+     init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, 
+               (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address");
+     init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, 
+               (void *)&length, (bool *)&length_set, "image length");
+     
+    if (!scan_opts(argc, argv, 1, opts, 2, &name_str, OPTION_ARG_TYPE_STR, "file name") ||
+        name_str == NULL)
+    {
+        fs_usage("invalid arguments");
+        return;
+    }
+
+//    diag_printf("load_address %08x %08x\n",load_address,load_address_end);
+//    diag_printf("ram %08x %08x\n",ram_start, ram_end);
+//    diag_printf("file name %08x >%s<\n",name_str,name_str);
+    
+    if (!mem_addr_set &&
+        (load_address >= (CYG_ADDRESS)ram_start) &&
+	((load_address_end) < (CYG_ADDRESS)ram_end))
+    {
+	mem_addr = load_address;
+	mem_addr_set = true;
+	if (!length_set)
+        {
+	    length = load_address_end - load_address;
+	    length_set = true;
+            // maybe get length from existing file size if no loaded
+            // image?
+        }
+    }
+    
+    fd = open( name_str, O_WRONLY|O_CREAT|O_TRUNC );
+
+    if( fd < 0 )
+    {
+        err_printf("fs write: Cannot open %s\n", name_str );
+        return;
+    }
+
+//    diag_printf("write %08x %08x\n",mem_addr, length );
+    
+    err = write( fd, (void *)mem_addr, length );
+
+    if( err != length )
+    {
+        err_printf("fs write: failed to write to file %d(%d) %d\n",err,length,errno);
+    }
+
+    err = close( fd );
+
+    if( err != 0 )
+        err_printf("fs write: close failed\n");
+}
+
+local_cmd_entry("write",
+                "write data to file",
+                "-b <mem_base> -l <image_length> <file_name>",
+                do_write,
+                FS_cmds
+    );
+
+//==========================================================================
+
+__externC cyg_fstab_entry cyg_fstab[];
+__externC cyg_fstab_entry cyg_fstab_end;
+__externC cyg_mtab_entry cyg_mtab[];
+__externC cyg_mtab_entry cyg_mtab_end;
+
+static void 
+do_info(int argc, char * argv[])
+{
+    cyg_bool found = false;
+    cyg_fstab_entry *f;
+    cyg_devtab_entry_t *t;
+
+    for( f = &cyg_fstab[0] ; f != &cyg_fstab_end; f++ )
+    {
+        if( !found )
+        {
+            diag_printf("Filesystems available:\n");
+            found = true;
+        }
+        diag_printf("%s\n",f->name);
+    }
+
+    found = false;
+    for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++)
+    {
+        if( (t->status & CYG_DEVTAB_STATUS_BLOCK) == 0 ||
+            (t->status & CYG_DEVTAB_STATUS_AVAIL) == 0 )
+            continue;
+        
+        if( !found )
+        {
+            diag_printf("\nDevices available:\n");
+            found = true;
+        }
+        diag_printf("%s\n",t->name);
+    }
+
+    if( mount_count != 0 )
+    {
+        int i;
+
+        diag_printf("\nMounted filesystems:\n");
+        diag_printf("            Device               Filesystem Mounted on\n");
+
+        for( i = 0; i < MAX_MOUNTS; i++ )
+        {
+            if( mounts[i].mp_str[0] != '\0' )
+                diag_printf("%32s %10s %s\n", mounts[i].dev_str, mounts[i].type_str, mounts[i].mp_str);
+        }
+    }
+}
+
+local_cmd_entry("info", 
+                "filesystem info",
+                "",
+                do_info,
+                FS_cmds
+    );
+
+//==========================================================================
+
+static void
+do_fs(int argc, char *argv[])
+{
+    struct cmd *cmd;
+
+    if (argc < 2) {
+        fs_usage("too few arguments");
+        return;
+    }
+    if ((cmd = cmd_search(__FS_cmds_TAB__, &__FS_cmds_TAB_END__, 
+                          argv[1])) != (struct cmd *)0) {
+        (cmd->fun)(argc-1, argv+1);
+        return;
+    }
+    fs_usage("unrecognized command");
+}
+
+RedBoot_nested_cmd("fs", 
+            "Manage Filesystem files", 
+            "{cmds}",
+            do_fs,
+            __FS_cmds_TAB__, &__FS_cmds_TAB_END__
+    );
+
+
+//==========================================================================
+
 static int fd;
 
 externC int 
@@ -263,13 +701,15 @@ fileio_stream_open(connection_info_t *in
 {
     char *filename = info->filename;
 
-    if (!fileio_mounted) {
-        diag_printf("No file system mounted\n");
-        return -1;
-    }
+     if( mount_count == 0 )
+     {
+         diag_printf("fs: No filesystems mounted\n");
+         return -1;
+     }
+    
     fd = open(filename, O_RDONLY);
     if (fd < 0) {
-        diag_printf("Open failed, error %d\n", errno);
+        diag_printf("fs: Open failed, error %d\n", errno);
         return -1;
     }
     return 0;
@@ -298,7 +738,7 @@ fileio_error(int err)
 {
     static char myerr[10];
 
-    diag_sprintf(myerr, "error %d\n", err);
+    diag_sprintf(myerr, "error %d", err);
     return myerr;
 }
 
@@ -309,3 +749,6 @@ GETC_IO_FUNCS(fileio_io, fileio_stream_o
               0, fileio_stream_read, fileio_error);
 RedBoot_load(file, fileio_io, true, true, 0);
 
+//==========================================================================
+// End of fileio.c
+