From 616b1199075618d8f7fadd7c85d602c3651defad Mon Sep 17 00:00:00 2001 From: patacongo Date: Sun, 1 Jul 2007 18:23:03 +0000 Subject: [PATCH] Added cp command git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@303 7fd9a85b-ad96-42d3-883c-3090e2eb8679 --- nuttx/ChangeLog | 7 +- nuttx/Documentation/NuttX.html | 5 +- nuttx/examples/README.txt | 46 +++++++-- nuttx/examples/nsh/nsh.h | 2 + nuttx/examples/nsh/nsh_fscmds.c | 166 +++++++++++++++++++++++++++++--- nuttx/examples/nsh/nsh_main.c | 16 +-- nuttx/examples/ostest/main.c | 8 +- nuttx/include/libgen.h | 2 +- 8 files changed, 218 insertions(+), 34 deletions(-) diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 81188709c..b207e4ab1 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -183,7 +183,7 @@ * tools/zipme.sh: Force directory name to be nuttx-xx.yy.zz * fs/fs_opendir.c: Correct errors in semaphore usage that can cause deadlock. * lib/lib_getopt.c: Added getopt() support - * examples/nsh: NSH now supports cat, mount, umount, and mkdir. ls supports + * examples/nsh/: NSH now supports cat, mount, umount, and mkdir. ls supports -l -s, and -R * Added basic OS support to manage environment variables: environment storage, cloning on task creation, sharing on pthread creation, destruction @@ -193,6 +193,9 @@ * Correct an error in realloc() when the block is extended "down" in memory. In this case, the old memory contents need to be copied to the new location and an allocated bit was not being set. - * examples/ostest: Added an environment variable test. + * examples/ostest/: Added an environment variable test. + * examples/nsh/: Break into several files. + * lib/: Added strrchr, basename, dirname + * examples/nsh/: Add cp command * Started m68322 diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html index fa3dbdd07..dd73585c1 100644 --- a/nuttx/Documentation/NuttX.html +++ b/nuttx/Documentation/NuttX.html @@ -614,7 +614,7 @@ Other memory: 0.2.8 2007-xx-xx Gregory Nutt * tools/Makefile.mkconfig: Under Cygwin, executable has a different name - * tools/mkdeps.sh & arch/arm/src/Makefile: Corrected a problem makeing dependencies + * tools/mkdeps.sh & arch/arm/src/Makefile: Corrected a problem making dependencies * tools/zipme.sh: Force directory name to be nuttx-xx.yy.zz * fs/fs_opendir.c: Correct errors in semaphore usage that can cause deadlock. * lib/lib_getopt.c: Added getopt() support @@ -631,6 +631,9 @@ Other memory: In this case, the old memory contents need to be copied to the new location and an allocated bit was not being set. * examples/ostest: Added an environment variable test. + * examples/nsh/: Break into several files. + * lib/: Added strrchr, basename, dirname + * examples/nsh/: Add cp command * Started m68322 diff --git a/nuttx/examples/README.txt b/nuttx/examples/README.txt index 3d595dd19..ed89b6133 100644 --- a/nuttx/examples/README.txt +++ b/nuttx/examples/README.txt @@ -1,23 +1,49 @@ examples ^^^^^^^^ -examples/ostest + The examples directory contains several sample applications that + can be linked with nuttx. The specific example is selected in the + configs//defconfig file via the CONFIG_EXAMPLE setting. + For example, - This is the NuttX 'qualification' suite. It attempts to exercise - a broad set of OS functionality. Its coverage is not very extensive - as of this writing, but it is used to qualify each NuttX release. + CONFIG_EXAMPLE=ostest + + Selects the examples/ostest example. + +examples/ostest +^^^^^^^^^^^^^^^ + + This is the NuttX 'qualification' suite. It attempts to exercise + a broad set of OS functionality. Its coverage is not very extensive + as of this writing, but it is used to qualify each NuttX release. + + The behavior of the ostest can be modified with the following + settings in the configs//defconfig file: + + * CONFIG_OSTEST_STACKSIZE + Used to create the ostest task. Default is 8192. examples/nsh +^^^^^^^^^^^^ - This directory containst the NuttShell (NSH). This is a primitive - shell-like application. With some additional development, NSH will - someday be a great NuttX application debugger. + This directory containst the NuttShell (NSH). This is a primitive + shell-like application. With some additional development, NSH will + someday be a great NuttX application debugger. + + The behavior of NSH can be modified with the following settings in + the configs//defconfig file: + + * CONFIG_NSH_IOBUFFERSIZE + Size of a static I/O buffer used for file access (ignored if + there is no filesystem). examples/mount +^^^^^^^^^^^^^^ - This contains a simple test of filesystem mountpoints. + This contains a simple test of filesystem mountpoints. examples/null +^^^^^^^^^^^^^ - This is the do nothing application. It is only used for bringing - up new NuttX architectures + This is the do nothing application. It is only used for bringing + up new NuttX architectures diff --git a/nuttx/examples/nsh/nsh.h b/nuttx/examples/nsh/nsh.h index 09f58e8bb..521a935fe 100644 --- a/nuttx/examples/nsh/nsh.h +++ b/nuttx/examples/nsh/nsh.h @@ -65,6 +65,7 @@ extern const char g_fmtcmdnotimpl[]; extern const char g_fmtnosuch[]; extern const char g_fmttoomanyargs[]; extern const char g_fmtcmdfailed[]; +extern const char g_fmtcmdoutofmemory[]; /**************************************************************************** * Public Function Prototypes @@ -72,6 +73,7 @@ extern const char g_fmtcmdfailed[]; #if CONFIG_NFILE_DESCRIPTORS > 0 void cmd_cat(int argc, char **argv); +void cmd_cp(int argc, char **argv); #endif void cmd_exec(int argc, char **argv); #if CONFIG_NFILE_DESCRIPTORS > 0 diff --git a/nuttx/examples/nsh/nsh_fscmds.c b/nuttx/examples/nsh/nsh_fscmds.c index c95b3e121..f8f95d39c 100644 --- a/nuttx/examples/nsh/nsh_fscmds.c +++ b/nuttx/examples/nsh/nsh_fscmds.c @@ -53,11 +53,9 @@ #include #include #include -#include -#if 0 #include -#include -#endif +#include +#include #include "nsh.h" @@ -69,6 +67,25 @@ #define LSFLAGS_LONG 2 #define LSFLAGS_RECURSIVE 4 +/* The size of the I/O buffer may be specified in the + * configs/defconfig file -- provided that it is at least as + * large as PATH_MAX. + */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +# ifdef CONFIG_NSH_IOBUFFERSIZE +# if CONFIG_NSH_IOBUFFERSIZE > (PATH_MAX + 1) +# define IOBUFFERSIZE CONFIG_NSH_IOBUFFERSIZE +# else +# define IOBUFFERSIZE (PATH_MAX + 1) +# endif +# else +# define IOBUFFERSIZE 1024 +# endif +# else +# define IOBUFFERSIZE (PATH_MAX + 1) +#endif + /**************************************************************************** * Private Types ****************************************************************************/ @@ -83,6 +100,8 @@ typedef int (*direntry_handler_t)(const char *, struct dirent *, void *); * Private Data ****************************************************************************/ +static char g_iobuffer[IOBUFFERSIZE]; + /**************************************************************************** * Public Data ****************************************************************************/ @@ -95,10 +114,9 @@ typedef int (*direntry_handler_t)(const char *, struct dirent *, void *); * Name: trim_dir ****************************************************************************/ -#ifdef CONFIG_FULL_PATH static void trim_dir(char *arg) { - /* Skip any '/' characters white space */ + /* Skip any trailing '/' characters (unless it is also the leading '/') */ int len = strlen(arg) - 1; while (len > 0 && arg[len] == '/') @@ -107,7 +125,6 @@ static void trim_dir(char *arg) len--; } } -#endif /**************************************************************************** * Name: getdirpath @@ -115,18 +132,19 @@ static void trim_dir(char *arg) static char *getdirpath(const char *path, const char *file) { - char buffer[PATH_MAX+1]; + /* Handle the case where all that is left is '/' */ + if (strcmp(path, "/") == 0) { - sprintf(buffer, "/%s", file); + sprintf(g_iobuffer, "/%s", file); } else { - sprintf(buffer, "%s/%s", path, file); + sprintf(g_iobuffer, "%s/%s", path, file); } - buffer[PATH_MAX] = '\0'; - return strdup(buffer); + g_iobuffer[PATH_MAX] = '\0'; + return strdup(g_iobuffer); } /**************************************************************************** @@ -410,6 +428,130 @@ void cmd_cat(int argc, char **argv) } #endif +/**************************************************************************** + * Name: cmd_cp + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +void cmd_cp(int argc, char **argv) +{ + struct stat buf; + char *fullpath = NULL; + const char *wrpath = argv[2]; + int oflags = O_WRONLY|O_CREAT|O_TRUNC; + int rdfd; + int wrfd; + int ret; + + /* Open the source file for reading */ + + rdfd = open(argv[1], O_RDONLY); + if (rdfd < 0) + { + printf(g_fmtcmdfailed, argv[0], "open", strerror(errno)); + return; + } + + /* Check if the destination is a directory */ + + ret = stat(wrpath, &buf); + if (ret == 0) + { + /* Something exists here... is it a directory? */ + + if (S_ISDIR(buf.st_mode)) + { + /* Yes, it is a directory. Remove any trailing '/' characters from the path */ + + trim_dir(argv[2]); + + /* Construct the full path to the new file */ + + fullpath = getdirpath(argv[2], basename(argv[1]) ); + if (!fullpath) + { + printf(g_fmtcmdoutofmemory, argv[0]); + goto out_with_rdfd; + } + + /* Open then fullpath for writing */ + wrpath = fullpath; + } + else if (!S_ISREG(buf.st_mode)) + { + /* Maybe it is a driver? */ + + oflags = O_WRONLY; + } + } + + /* Now open the destination */ + + wrfd = open(wrpath, oflags, 0666); + if (wrfd < 0) + { + printf(g_fmtcmdfailed, argv[0], "open", strerror(errno)); + goto out_with_fullpath; + } + + /* Now copy the file */ + + for (;;) + { + int nbytesread; + int nbyteswritten; + + do + { + nbytesread = read(rdfd, g_iobuffer, IOBUFFERSIZE); + if (nbytesread == 0) + { + /* End of file */ + + goto out_with_wrfd; + } + else if (nbytesread < 0 && errno != EINTR) + { + /* Read error */ + + printf(g_fmtcmdfailed, argv[0], "read", strerror(errno)); + goto out_with_wrfd; + } + } + while (nbytesread <= 0); + + do + { + nbyteswritten = write(wrfd, g_iobuffer, nbytesread); + if (nbyteswritten >= 0) + { + nbytesread -= nbyteswritten; + } + else if (errno != EINTR) + { + /* Read error */ + + printf(g_fmtcmdfailed, argv[0], "write", strerror(errno)); + goto out_with_wrfd; + } + } + while (nbytesread > 0); + } + +out_with_wrfd: + close(wrfd); + +out_with_fullpath: + if (fullpath) + { + free(fullpath); + } + +out_with_rdfd: + close(rdfd); +} +#endif + /**************************************************************************** * Name: cmd_ls ****************************************************************************/ diff --git a/nuttx/examples/nsh/nsh_main.c b/nuttx/examples/nsh/nsh_main.c index 4ddb91ece..774a7d368 100644 --- a/nuttx/examples/nsh/nsh_main.c +++ b/nuttx/examples/nsh/nsh_main.c @@ -85,6 +85,7 @@ static const struct cmdmap_s g_cmdmap[] = { #if CONFIG_NFILE_DESCRIPTORS > 0 { "cat", cmd_cat, 2, 2, "" }, + { "cp", cmd_cp, 3, 3, " " }, #endif { "echo", cmd_echo, 2, 2, "" }, { "exec", cmd_exec, 2, 3, "" }, @@ -107,13 +108,14 @@ static const struct cmdmap_s g_cmdmap[] = * Public Data ****************************************************************************/ -const char g_fmtargrequired[] = "nsh: %s: missing required argument(s)\n"; -const char g_fmtarginvalid[] = "nsh: %s: argument invalid\n"; -const char g_fmtcmdnotfound[] = "nsh: %s: command not found\n"; -const char g_fmtcmdnotimpl[] = "nsh: %s: command not implemented\n"; -const char g_fmtnosuch[] = "nsh: %s: no such %s: %s\n"; -const char g_fmttoomanyargs[] = "nsh: %s: too many arguments\n"; -const char g_fmtcmdfailed[] = "nsh: %s: %s failed: %s\n"; +const char g_fmtargrequired[] = "nsh: %s: missing required argument(s)\n"; +const char g_fmtarginvalid[] = "nsh: %s: argument invalid\n"; +const char g_fmtcmdnotfound[] = "nsh: %s: command not found\n"; +const char g_fmtcmdnotimpl[] = "nsh: %s: command not implemented\n"; +const char g_fmtnosuch[] = "nsh: %s: no such %s: %s\n"; +const char g_fmttoomanyargs[] = "nsh: %s: too many arguments\n"; +const char g_fmtcmdfailed[] = "nsh: %s: %s failed: %s\n"; +const char g_fmtcmdoutofmemory[] = "nsh: %s: out of memory\n"; /**************************************************************************** * Private Functions diff --git a/nuttx/examples/ostest/main.c b/nuttx/examples/ostest/main.c index 889eeaefa..b7f0afbf3 100644 --- a/nuttx/examples/ostest/main.c +++ b/nuttx/examples/ostest/main.c @@ -55,9 +55,15 @@ ************************************************************/ #define PRIORITY 100 -#define STACKSIZE 8192 #define NARGS 4 +/* The task_create task size can be specified in the defconfig file */ +#ifdef CONFIG_OSTEST_STACKSIZE +# define STACKSIZE CONFIG_OSTEST_STACKSIZE +#else +# define STACKSIZE 8192 +#endif + /************************************************************ * Private Data ************************************************************/ diff --git a/nuttx/include/libgen.h b/nuttx/include/libgen.h index e0d95c8ad..531a2cc44 100644 --- a/nuttx/include/libgen.h +++ b/nuttx/include/libgen.h @@ -55,7 +55,7 @@ extern "C" { #define EXTERN extern #endif -EXTERN char *dirname(char *path); +EXTERN char *basename(char *path); EXTERN char *dirname(char *path); #undef EXTERN