diff --git a/ChangeLog b/ChangeLog index 81188709c1..b207e4ab1f 100644 --- a/ChangeLog +++ b/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/Documentation/NuttX.html b/Documentation/NuttX.html index fa3dbdd071..dd73585c12 100644 --- a/Documentation/NuttX.html +++ b/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/examples/README.txt b/examples/README.txt index 3d595dd193..ed89b6133f 100644 --- a/examples/README.txt +++ b/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/examples/nsh/nsh.h b/examples/nsh/nsh.h index 09f58e8bb5..521a935fe6 100644 --- a/examples/nsh/nsh.h +++ b/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/examples/nsh/nsh_fscmds.c b/examples/nsh/nsh_fscmds.c index c95b3e121d..f8f95d39c9 100644 --- a/examples/nsh/nsh_fscmds.c +++ b/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/examples/nsh/nsh_main.c b/examples/nsh/nsh_main.c index 4ddb91ece6..774a7d3686 100644 --- a/examples/nsh/nsh_main.c +++ b/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/examples/ostest/main.c b/examples/ostest/main.c index 889eeaefa4..b7f0afbf38 100644 --- a/examples/ostest/main.c +++ b/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/include/libgen.h b/include/libgen.h index e0d95c8adf..531a2cc449 100644 --- a/include/libgen.h +++ b/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