Mercurial > ecos
view 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 source
//========================================================================== // // fileio.c // // RedBoot fileio support // //========================================================================== //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // 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 // Software Foundation; either version 2 or (at your option) any later version. // // eCos is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License along // with eCos; if not, write to the Free Software Foundation, Inc., // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. // // As a special exception, if other files instantiate templates or use macros // or inline functions from this file, or you compile this file and link it // with other works to produce a work based on this file, this file does not // by itself cause the resulting work to be covered by the GNU General Public // License. However the source code for this file must still be made available // in accordance with section (3) of the GNU General Public License. // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. // // ------------------------------------------- //####ECOSGPLCOPYRIGHTEND#### //========================================================================== //#####DESCRIPTIONBEGIN#### // // Author(s): nickg // Contributors: dwmw2, msalter // Date: 2004-11-21 // Purpose: // Description: // // This code is part of RedBoot (tm). // //####DESCRIPTIONEND#### // //========================================================================== // Shoot me. But I don't want struct timeval because redboot provides it. #define _POSIX_SOURCE #include <time.h> #undef _POSIX_SOURCE #include <redboot.h> #include <errno.h> #include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #ifdef CYGPKG_IO_FLASH #include <cyg/io/io.h> #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_LEGACY #define FLASHPART "[-f <partition>] " #else #define FLASHPART #endif local_cmd_entry("mount", "Mount file system", FLASHPART "[-d <device>] -t <fstype> [<mountpoint>]", do_mount, FS_cmds ); local_cmd_entry("umount", "Unmount file system", "<mountpoint>", do_umount, FS_cmds ); //========================================================================== // Mount disk/filesystem static void do_mount(int argc, char *argv[]) { 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_LEGACY init_opts(&opts[2], 'f', true, OPTION_ARG_TYPE_STR, (void *)&part_str, &part_set, "partition"); num_opts++; #endif CYG_ASSERT(num_opts <= NUM_ELEMS(opts), "Too many options"); if (!scan_opts(argc, argv, 1, opts, num_opts, &mp_str, OPTION_ARG_TYPE_STR, "mountpoint")) return; if (!type_set) { err_printf("fs mount: Must specify file system type\n"); return; } 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_LEGACY if (part_set) { int len; cyg_io_handle_t h; if (dev_set && strcmp(dev_str, CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1)) { err_printf("fs mount: May only set one of <device> or <partition>\n"); return; } dev_str = CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1; len = strlen(part_str); err = cyg_io_lookup(dev_str, &h); if (err < 0) { 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("fs mount: FIS partition \"%s\" not found\n", part_str); return; } } #endif 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; } 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[]) { 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; } 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( "/" ); } } //========================================================================== #include <dirent.h> static char rwx[8][4] = { "---", "r--", "-w-", "rw-", "--x", "r-x", "-wx", "rwx" }; static void do_list(int argc, char * argv[]) { char * dir_str; DIR *dirp; char filename[PATH_MAX]; char cwd[PATH_MAX]; struct stat sbuf; 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 == 0 ) { dir_str = getcwd(cwd, sizeof(cwd)); } dirp = opendir(dir_str); if (dirp==NULL) { err_printf("fs list: no such directory %s\n",dir_str); return; } for (;;) { struct dirent *entry = readdir(dirp); if( entry == NULL ) break; strcpy(filename, dir_str); strcat(filename, "/"); strcat(filename, entry->d_name); err = stat(filename, &sbuf); if (err < 0) { diag_printf("Unable to stat file %s\n", filename); continue; } diag_printf("%4d ", sbuf.st_ino); if (S_ISDIR(sbuf.st_mode)) diag_printf("d"); if (S_ISCHR(sbuf.st_mode)) diag_printf("c"); if (S_ISBLK(sbuf.st_mode)) diag_printf("b"); if (S_ISREG(sbuf.st_mode)) diag_printf("-"); if (S_ISLNK(sbuf.st_mode)) diag_printf("l"); diag_printf("%s%s%s", // Ho, humm, have to hard code the shifts rwx[(sbuf.st_mode & S_IRWXU) >> 16], rwx[(sbuf.st_mode & S_IRWXG) >> 19], rwx[(sbuf.st_mode & S_IRWXO) >> 22]); diag_printf(" %2d size %6d %s\n", sbuf.st_nlink,sbuf.st_size, entry->d_name); } closedir(dirp); return; } 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 ); //========================================================================== 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 fileio_stream_open(connection_info_t *info, int *err) { char *filename = info->filename; if( mount_count == 0 ) { diag_printf("fs: No filesystems mounted\n"); return -1; } fd = open(filename, O_RDONLY); if (fd < 0) { diag_printf("fs: Open failed, error %d\n", errno); return -1; } return 0; } externC int fileio_stream_read(char *buf, int size, int *err) { int nread; if ((nread = read(fd, buf, size)) < 0) { *err = errno; return -1; } return nread; } externC void fileio_stream_close(int *err) { close(fd); } externC char * fileio_error(int err) { static char myerr[10]; diag_sprintf(myerr, "error %d", err); return myerr; } // // RedBoot interface // GETC_IO_FUNCS(fileio_io, fileio_stream_open, fileio_stream_close, 0, fileio_stream_read, fileio_error); RedBoot_load(file, fileio_io, true, true, 0); //========================================================================== // End of fileio.c
