diff options
-rw-r--r-- | apps/ChangeLog.txt | 2 | ||||
-rw-r--r-- | apps/nshlib/Kconfig | 11 | ||||
-rw-r--r-- | apps/nshlib/nsh.h | 4 | ||||
-rw-r--r-- | apps/nshlib/nsh_parse.c | 2 | ||||
-rwxr-xr-x | nuttx/ChangeLog | 8 | ||||
-rw-r--r-- | nuttx/Documentation/NuttxUserGuide.html | 45 | ||||
-rw-r--r-- | nuttx/include/stdio.h | 22 | ||||
-rw-r--r-- | nuttx/include/stdlib.h | 4 | ||||
-rw-r--r-- | nuttx/libc/Kconfig | 21 | ||||
-rw-r--r-- | nuttx/libc/stdio/Make.defs | 4 | ||||
-rw-r--r-- | nuttx/libc/stdio/lib_tempnam.c | 105 | ||||
-rw-r--r-- | nuttx/libc/stdio/lib_tmpnam.c | 95 | ||||
-rw-r--r-- | nuttx/libc/stdlib/Make.defs | 4 | ||||
-rw-r--r-- | nuttx/libc/stdlib/lib_mkstemp.c | 297 | ||||
-rw-r--r-- | nuttx/libc/stdlib/lib_mktemp.c | 81 |
15 files changed, 673 insertions, 32 deletions
diff --git a/apps/ChangeLog.txt b/apps/ChangeLog.txt index a246f462c0..df7295df27 100644 --- a/apps/ChangeLog.txt +++ b/apps/ChangeLog.txt @@ -1095,3 +1095,5 @@ issues. From Radoslaw Adamczyk (2014-10-23). * apps/examples/keypadtest/keypadtest_main.c: Fixes to keypadtest from Pierre-Noel Bouteville (2014-10-23). + * apps/nshlib/nsh_parse.c, nsh.h, and Kconfig: Move CONFIG_NSH_TMPDIR + to CONFIG_LIBC_TMPDIR (2014-11-05). diff --git a/apps/nshlib/Kconfig b/apps/nshlib/Kconfig index ba9c718b4a..3e212e7462 100644 --- a/apps/nshlib/Kconfig +++ b/apps/nshlib/Kconfig @@ -77,17 +77,6 @@ config NSH_CMDPARMS Because this feature commits significant resources, it is disabled by default. -config NSH_TMPDIR - string "Temporary file directory" - default "/tmp" - depends on NSH_CMDPARMS - ---help--- - If NSH_CMDPARMS is selected, then function output will be retained - in a temporary file. In that case, this string must be provided to - specify the full path to a directory where temporary files can be - created. This would be a good application of RAM disk: To provide - temporary storage for function output. - config NSH_MAXARGUMENTS int "Maximum number of command arguments" default 6 diff --git a/apps/nshlib/nsh.h b/apps/nshlib/nsh.h index dc13e3753a..d726b5253e 100644 --- a/apps/nshlib/nsh.h +++ b/apps/nshlib/nsh.h @@ -100,8 +100,8 @@ * hold temporary files must be provided. */ -#if defined(CONFIG_NSH_CMDPARMS) && !defined(CONFIG_NSH_TMPDIR) -# define CONFIG_NSH_TMPDIR "/tmp" +#if defined(CONFIG_NSH_CMDPARMS) && !defined(CONFIG_LIBC_TMPDIR) +# define CONFIG_LIBC_TMPDIR "/tmp" #endif /* Networking support. Make sure that all non-boolean configuration diff --git a/apps/nshlib/nsh_parse.c b/apps/nshlib/nsh_parse.c index 2ed9452cf6..a7a35e8f21 100644 --- a/apps/nshlib/nsh_parse.c +++ b/apps/nshlib/nsh_parse.c @@ -874,7 +874,7 @@ static FAR char *nsh_cmdparm(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline, /* Create a unique file name using the task ID */ tmpfile = NULL; - ret = asprintf(&tmpfile, "%s/TMP%d.dat", CONFIG_NSH_TMPDIR, getpid()); + ret = asprintf(&tmpfile, "%s/TMP%d.dat", CONFIG_LIBC_TMPDIR, getpid()); if (ret < 0 || !tmpfile) { nsh_output(vtbl, g_fmtcmdoutofmemory, "``"); diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 509d45adfc..538954973f 100755 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -8904,5 +8904,9 @@ (2014-10-29). * configs/efm32gg-stk3700: Board support for the SiLbas EFM32GG Giant Gecko Starter kit. Current with basic NSH configuration only. - Testing is on hold until I receive hardware (20145-11-03). - + Testing is on hold until I receive hardware (2014-11-03). + * libc/Kconfig: Move CONFIG_NSH_TMPDIR to CONFIG_LIBC_TMPDIR (2014-11-05). + * libc/stdlib/lib_mkstemp.c, lib_mktemp.c, Make.defs and include/stdlib.h: + Add mktemp() and mkstemp() (2014-11-05). + * libc/stdio/lib_tempnam.c, lib_tmpnam.c, Kconfig, Make.defs and + include/stdio.h: Add tmpnam() and tempnam() (2014-11-05). diff --git a/nuttx/Documentation/NuttxUserGuide.html b/nuttx/Documentation/NuttxUserGuide.html index fc51da5920..44445e8ce0 100644 --- a/nuttx/Documentation/NuttxUserGuide.html +++ b/nuttx/Documentation/NuttxUserGuide.html @@ -13,7 +13,7 @@ <h1><big><font color="#3c34ec"><i>NuttX Operating System<p>User's Manual</i></font></big></h1> <p><small>by</small></p> <p>Gregory Nutt<p> - <p>Last Updated: October 4, 2014</p> + <p>Last Updated: November 5, 2014</p> </td> </tr> </table> @@ -7629,11 +7629,12 @@ interface of the same name. <li><a href="#directoryoperations">2.10.3 Directory Operations</a></li> <li><a href="#dirunistdops">2.10.4 UNIX Standard Operations</a></li> <li><a href="#standardio">2.10.5 Standard I/O</a></li> - <li><a href="#aio">2.10.6 Asynchronous I/O</a></li> - <li><a href="#stdstrings">2.10.7 Standard String Operations</a></li> - <li><a href="#PipesNFifos">2.10.8 Pipes and FIFOs</a></li> - <li><a href="#fatsupport">2.10.9 FAT File System Support</a></li> - <li><a href="#mmapxip">2.10.10 <code>mmap()</code> and eXecute In Place (XIP)</a></li> + <li><a href="#standardlib">2.10.6 Standard Library</a></li> + <li><a href="#aio">2.10.7 Asynchronous I/O</a></li> + <li><a href="#stdstrings">2.10.8 Standard String Operations</a></li> + <li><a href="#PipesNFifos">2.10.9 Pipes and FIFOs</a></li> + <li><a href="#fatsupport">2.10.10 FAT File System Support</a></li> + <li><a href="#mmapxip">2.10.11 <code>mmap()</code> and eXecute In Place (XIP)</a></li> </ul> <h3><a name="FileSystemOverview">2.10.1 NuttX File System Overview</a></h3> @@ -7953,6 +7954,8 @@ int dprintf(int fd, FAR const char *fmt, ...); int vdprintf(int fd, FAR const char *fmt, va_list ap); int statfs(FAR const char *path, FAR struct statfs *buf); +FAR char *tmpnam(FAR char *s); +FAR char *tempnam(FAR const char *dir, FAR const char *pfx); #include <sys/stat.h> @@ -7967,7 +7970,19 @@ int statfs(const char *path, struct statfs *buf); int fstatfs(int fd, struct statfs *buf); </pre></ul> -<h3><a name="aio">2.10.6 Asynchronous I/O</a></h3> +<h3><a name="standardlib">2.10.6 Standard Library</a></h3> +<p> + <code>stdlib.h</code> generally addresses other operating system interfaces. + However, the following may also be considered as file system interfaces: +</p> +<ul><pre> +#include <stdlib.h> + +int mktemp(FAR char *template); +int mkstemp(FAR char *template); +</pre></ul> + +<h3><a name="aio">2.10.7 Asynchronous I/O</a></h3> <ul><pre> #include <aio.h> @@ -7983,7 +7998,7 @@ int lio_listio(int mode, FAR struct aiocb *const list[], int nent, FAR struct sigevent *sig); </pre></ul> -<h3><a name="stdstrings">2.10.7 Standard String Operations</a></h3> +<h3><a name="stdstrings">2.10.8 Standard String Operations</a></h3> <ul><pre> #include <string.h> @@ -8017,9 +8032,9 @@ void *memmove(void *dest, const void *src, size_t count); # define bzero(s,n) (void)memset(s,0,n) </pre></ul> -<h3><a name="PipesNFifos">2.10.8 Pipes and FIFOs</a></h3> +<h3><a name="PipesNFifos">2.10.9 Pipes and FIFOs</a></h3> -<h3>2.10.8.1 <a name="pipe"><code>pipe</code></a></h3> +<h3>2.10.9.1 <a name="pipe"><code>pipe</code></a></h3> <p> <b>Function Prototype:</b> </p> @@ -8053,7 +8068,7 @@ int pipe(int fd[2]); </ul> </p> -<h3>2.10.8.2 <a name="mkfifo"><code>mkfifo</code></a></h3> +<h3>2.10.9.2 <a name="mkfifo"><code>mkfifo</code></a></h3> <p> <b>Function Prototype:</b> </p> @@ -8100,8 +8115,8 @@ int mkfifo(FAR const char *pathname, mode_t mode); </ul> </p> -<h3><a name="fatsupport">2.10.9 FAT File System Support</a></h3> -<h3>2.10.9.1 <a name="mkfatfs"><code>mkfatfs</code></a></h3> +<h3><a name="fatsupport">2.10.10 FAT File System Support</a></h3> +<h3>2.10.10.1 <a name="mkfatfs"><code>mkfatfs</code></a></h3> <p> <b>Function Prototype:</b> </p> @@ -8178,7 +8193,7 @@ struct fat_format_s </ul> </p> -<h3><a name="mmapxip">2.10.10 <code>mmap()</code> and eXecute In Place (XIP)</a></h3> +<h3><a name="mmapxip">2.10.11 <code>mmap()</code> and eXecute In Place (XIP)</a></h3> <p> NuttX operates in a flat open address space and is focused on MCUs that do support Memory Management Units (MMUs). Therefore, NuttX generally does not @@ -8307,7 +8322,7 @@ struct fat_format_s </li> </ol> -<h3><a name="mmap">2.10.10.1 <code>mmap</code></a></h3> +<h3><a name="mmap">2.10.11.1 <code>mmap</code></a></h3> <p> <b>Function Prototype:</b> </p> diff --git a/nuttx/include/stdio.h b/nuttx/include/stdio.h index bc0164aa48..cb1636679e 100644 --- a/nuttx/include/stdio.h +++ b/nuttx/include/stdio.h @@ -78,6 +78,26 @@ #define getchar() fgetc(stdin) #define rewind(s) ((void)fseek((s),0,SEEK_SET)) +/* Path to the directory where temporary files can be created */ + +#ifndef CONFIG_LIBC_TMPDIR +# define CONFIG_LIBC_TMPDIR "/tmp" +#endif + +#define P_tmpdir CONFIG_LIBC_TMPDIR + +/* Maximum size of character array to hold tmpnam() output. */ + +#ifndef CONFIG_LIBC_MAX_TMPFILE +# define CONFIG_LIBC_MAX_TMPFILE 32 +#endif + +#define L_tmpnam CONFIG_LIBC_MAX_TMPFILE + +/* the maximum number of unique temporary file names that can be generated */ + +#define TMP_MAX 56800235584ull + /**************************************************************************** * Public Type Definitions ****************************************************************************/ @@ -161,6 +181,8 @@ int vdprintf(int fd, FAR const char *fmt, va_list ap); /* Operations on paths */ int statfs(FAR const char *path, FAR struct statfs *buf); +FAR char *tmpnam(FAR char *s); +FAR char *tempnam(FAR const char *dir, FAR const char *pfx); #undef EXTERN #if defined(__cplusplus) diff --git a/nuttx/include/stdlib.h b/nuttx/include/stdlib.h index 127b35163d..c149e0ac11 100644 --- a/nuttx/include/stdlib.h +++ b/nuttx/include/stdlib.h @@ -1,7 +1,7 @@ /**************************************************************************** * include/stdlib.h * - * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2014 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -182,6 +182,8 @@ long int labs(long int j); #ifdef CONFIG_HAVE_LONG_LONG long long int llabs(long long int j); #endif +int mktemp(FAR char *template); +int mkstemp(FAR char *template); /* Sorting */ diff --git a/nuttx/libc/Kconfig b/nuttx/libc/Kconfig index 8f9569bde0..138793aadc 100644 --- a/nuttx/libc/Kconfig +++ b/nuttx/libc/Kconfig @@ -192,6 +192,27 @@ config LIBC_PERROR_STDOUT be defined, however, to provide perror() output that is serialized with other stdout messages. +config LIBC_TMPDIR + string "Temporary file directory" + default "/tmp" + depends on FS_WRITABLE + ---help--- + If a write-able file system is selected, this string will be + provided to specify the full path to a directory where temporary + files can be created. This would be a good application of RAM disk: + To provide temporary storage for application data. + +config LIBC_MAX_TMPFILE + int "Maximum size of a temporary file path" + default 32 + depends on FS_WRITABLE + ---help--- + If a write-able file system is selected, then temporary file may be + supported at the path provided by LIBC_TMPDIR. The tmpnam() interface + keeps a static copy of this last filename produced; this value is the + maximum size of that last filename. This size is the size of the full + file path. + config ARCH_LOWPUTC bool "Low-level console output" default "y" diff --git a/nuttx/libc/stdio/Make.defs b/nuttx/libc/stdio/Make.defs index 284c725c4b..66914b30f2 100644 --- a/nuttx/libc/stdio/Make.defs +++ b/nuttx/libc/stdio/Make.defs @@ -66,6 +66,10 @@ CSRCS += lib_stdoutstream.c lib_stdsistream.c lib_stdsostream.c lib_perror.c CSRCS += lib_feof.c lib_ferror.c lib_clearerr.c endif + +ifeq ($(CONFIG_FS_WRITABLE),y) +CSRCS += lib_tempnam.c lib_tmpnam.c +endif endif # Other support that depends on specific, configured features. diff --git a/nuttx/libc/stdio/lib_tempnam.c b/nuttx/libc/stdio/lib_tempnam.c new file mode 100644 index 0000000000..cf480cdff9 --- /dev/null +++ b/nuttx/libc/stdio/lib_tempnam.c @@ -0,0 +1,105 @@ +/**************************************************************************** + * libc/stdio/lib_tempnam.c + * + * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tempnam + * + * Description: + * The tempnam() function generates a pathname that may be used for a + * temporary file. + * + * The tempnam() function allows the user to control the choice of a + * directory. The dir argument points to the name of the directory in which + * the file is to be created. If dir is a null pointer or points to a + * string which is not a name for an appropriate directory, the path prefix + * defined as P_tmpdir in the <stdio.h> header will be used. If that + * directory is not accessible, an implementation-defined directory may be + * used. + * + * Many applications prefer their temporary files to have certain initial + * letter sequences in their names. The pfx argument should be used for + * this. This argument may be a null pointer or point to a string of up + * to five bytes to be used as the beginning of the filename. + * + * Returned Value: + * Upon successful completion, tempnam() will allocate space for a string + * put the generated pathname in that space, and return a pointer to it. + * The pointer will be suitable for use in a subsequent call to free(). + * Otherwise, it will return a null pointer and set errno to indicate the + * error. + * + * The tempnam() function will fail if: + * ENOMEM - Insufficient storage space is available. + * + ****************************************************************************/ + +FAR char *tempnam(FAR const char *dir, FAR const char *pfx) +{ + FAR char *path; + int ret; + + (void)asprintf(&path, "%s/%s-XXXXXX.tmp", dir, pfx); + if (path) + { + ret = mktemp(path); + if (ret == OK) + { + return path; + } + + free(path); + } + + set_errno(ENOMEM); + return NULL; +} diff --git a/nuttx/libc/stdio/lib_tmpnam.c b/nuttx/libc/stdio/lib_tmpnam.c new file mode 100644 index 0000000000..a11080e749 --- /dev/null +++ b/nuttx/libc/stdio/lib_tmpnam.c @@ -0,0 +1,95 @@ +/**************************************************************************** + * libc/stdio/lib_tmpnam.c + * + * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tmpnam + * + * Description: + * The tmpnam() function generates a string that is a valid filename and + * that is not the same as the name of an existing file. The function is + * potentially capable of generating TMP_MAX different strings, but any or + * all of them may already be in use by existing files and thus not be + * suitable return values. + * + * The tmpnam() function generates a different string each time it is + * called from the same process, up to {TMP_MAX} times. If it is called + * more than {TMP_MAX} times, the behavior is implementation-defined. + * + * Returned Value: + * Upon successful completion, tmpnam() returns a pointer to a string. I + * no suitable string can be generated, the tmpnam() function will + * return a null pointer. + * + * If the argument s is a null pointer, tmpnam() will leave its result + * in an internal static object and return a pointer to that object. + * Subsequent calls to tmpnam() may modify the same object. If the + * argument s is not a null pointer, it is presumed to point to an + * array of at least L_tmpnam chars; tmpnam() will write its result in + * that array and will return the argument as its value. + * + ****************************************************************************/ + +FAR char *tmpnam(FAR char *s) +{ + static char path[L_tmpnam]; + int ret; + + if (s == NULL) + { + s = path; + } + + (void)snprintf(s, L_tmpnam, "%s/XXXXXX.tmp", P_tmpdir); + ret = mktemp(s); + return (ret == OK) ? s : NULL; +} diff --git a/nuttx/libc/stdlib/Make.defs b/nuttx/libc/stdlib/Make.defs index 5501ef0c16..6a0d8ad7d8 100644 --- a/nuttx/libc/stdlib/Make.defs +++ b/nuttx/libc/stdlib/Make.defs @@ -40,6 +40,10 @@ CSRCS += lib_llabs.c lib_rand.c lib_qsort.c CSRCS += lib_strtol.c lib_strtoll.c lib_strtoul.c lib_strtoull.c CSRCS += lib_strtod.c lib_checkbase.c +ifeq ($(CONFIG_FS_WRITABLE),y) +CSRCS += lib_mktemp.c lib_mkstemp.c +endif + # Add the stdlib directory to the build DEPPATH += --dep-path stdlib diff --git a/nuttx/libc/stdlib/lib_mkstemp.c b/nuttx/libc/stdlib/lib_mkstemp.c new file mode 100644 index 0000000000..3269463f5f --- /dev/null +++ b/nuttx/libc/stdlib/lib_mkstemp.c @@ -0,0 +1,297 @@ +/**************************************************************************** + * libc/stdlib/lib_mkstemp.c + * + * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <nuttx/compiler.h> + +#include <stdint.h> +#include <stdio.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <semaphore.h> +#include <errno.h> + +#ifdef CONFIG_FS_WRITABLE + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + + #ifndef CONFIG_LIBC_TMPDIR +# define CONFIG_LIBC_TMPDIR "/tmp" +#endif + +#define MAX_XS 6 +#define MIN_NUMERIC 0 /* 0-9: Numeric */ +#define MAX_NUMERIC 9 +#define MIN_UPPERCASE 10 /* 10-35: Upper case */ +#define MAX_UPPERCASE 35 +#define MIN_LOWERCASE 36 /* 36-61: Lower case */ +#define MAX_LOWERCASE 61 +#define MAX_BASE62 MAX_LOWERCASE + +/* 62**1 = 62 + * 62**2 = 3844 + * 62**3 = 238328 + * 62**4 = 14776336 + * 62**5 = 916132832 + * 62**6 = 56800235584 > UINT32_MAX + */ + +#define BIG_XS 5 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static uint8_t g_base62[MAX_XS]; +static sem_t g_b62sem = SEM_INITIALIZER(1); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: base62_to_char + * + * Description: + * Convert a base62 value to a printable character. + * + ****************************************************************************/ + +static char base62_to_char(uint8_t base62) +{ + if (base62 <= MAX_NUMERIC) + { + return '0' + base62; + } + else if (base62 <= MAX_UPPERCASE) + { + return 'A' + base62 - MIN_UPPERCASE; + } + else /* if (base62 <= MAX_LOWERCASE) */ + { + DEBUGASSERT(base62 <= MAX_LOWERCASE); + return 'a' + base62 - MIN_LOWERCASE; + } +} + +/**************************************************************************** + * Name: incr_base62 + * + * Description: + * increment the base62 value array. + * + ****************************************************************************/ + +static void incr_base62(void) +{ + int i; + + for (i = 0; i < MAX_XS; i++) + { + if (g_base62[i] < MAX_LOWERCASE) + { + g_base62[i]++; + return; + } + else + { + g_base62[i] = 0; + } + } +} + +/**************************************************************************** + * Name: get_base62 + * + * Description: + * Atomically copy and increment the base62 array. + * + ****************************************************************************/ + +static void get_base62(FAR uint8_t *ptr) +{ + int ret; + + while ((ret = sem_wait(&g_b62sem)) < 0) + { + DEBUGASSERT(errno == EINTR); + } + + memcpy(ptr, g_base62, MAX_XS); + incr_base62(); + sem_post(&g_b62sem); +} + +/**************************************************************************** + * Name: copy_base62 + * + * Description: + * Copy the base62 array into the template filename, converting each + * base62 value to a printable character. + * + ****************************************************************************/ + +static void copy_base62(FAR char *dest, int len) +{ + FAR const uint8_t *src; + + src = g_base62; + if (len < MAX_XS) + { + src += MAX_XS - len; + } + + for (; len > 0; len--) + { + *dest++ = base62_to_char(*src++); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mkstemp + * + * Description: + * The mkstemp() function replaces the contents of the string pointed to + * by template by a unique filename, and returns a file descriptor for the + * file open for reading and writing. The function thus prevents any + * possible race condition between testing whether the file exists and + * opening it for use. The string in template should look like a filename + * with six trailing 'X' s; mkstemp() replaces each 'X' with a character + * from the portable filename character set. The characters are chosen + * such that the resulting name does not duplicate the name of an existing + * file at the time of a call to mkstemp(). + * + * Input Parameters: + * template - The base file name that will be modified to produce the + * unique file name. This must be a full path beginning with /tmp. + * This function will modify only the first XXXXXX characters within + * that full path. + * + * Returned Value: + * + * Upon successful completion, mkstemp() returns an open file descriptor. + * Otherwise, -1 is returned if no suitable file could be created. + * + ****************************************************************************/ + +int mkstemp(FAR char *template) +{ + uint8_t base62[MAX_XS]; + uint32_t retries; + FAR char *xptr; + FAR char *ptr; + int xlen; + int fd; + int i; + + /* Count the number of X's at the end of the template */ + + xptr = strchr(template, 'X'); + if (!xptr) + { + /* No Xs? There should always really be 6 */ + + return open(template, O_RDWR | O_CREAT | O_EXCL, 0666); + } + + /* There is at least one.. count all of them */ + + for (xlen = 0, ptr = xptr; xlen < MAX_XS && *ptr == 'X'; xlen++, ptr++); + + /* Ignore any X's after the sixth */ + + if (xlen > MAX_XS) + { + xlen = MAX_XS; + } + + /* If xlen is small, then we need to determine the maximum number of + * retries before the values will repeat. + */ + + if (xlen >= BIG_XS) + { + retries = UINT32_MAX; + } + else + { + for (i = 1, retries = 62; i < xlen; i++, retries *= 62); + } + + /* Then loop until we find a unique file name */ + + while (retries > 0) + { + /* Sample and increment the base62 counter */ + + get_base62(base62); + + /* Form the candidate file name */ + + copy_base62(xptr, xlen); + + /* Attempt to open the candidate file -- creating it exclusively + * + * REVISIT: This prohibits the use of this function to create unique + * directories + */ + + fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0666); + if (fd >= 0) + { + /* We have it... return the file descriptor */ + + return fd; + } + } + + /* We could not find an unique filename */ + + return ERROR; +} + +#endif /* CONFIG_FS_WRITABLE */ + diff --git a/nuttx/libc/stdlib/lib_mktemp.c b/nuttx/libc/stdlib/lib_mktemp.c new file mode 100644 index 0000000000..705c5cb9e3 --- /dev/null +++ b/nuttx/libc/stdlib/lib_mktemp.c @@ -0,0 +1,81 @@ +/**************************************************************************** + * libc/stdlib/lib_mktemp.c + * + * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <nuttx/compiler.h> + +#include <unistd.h> +#include <stdlib.h> + +#ifdef CONFIG_FS_WRITABLE + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mktemp + * + * Description: + * The use of mktemp is dangerous; use mkstemp instead. + * + ****************************************************************************/ + +int mktemp(FAR char *template) +{ + int fd = mkstemp(template); + if (fd < 0) + { + return ERROR; + } + + close(fd); + return OK; +} + +#endif /* CONFIG_FS_WRITABLE */ + |