summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-11-05 09:39:18 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-11-05 09:39:18 -0600
commit242d5e18ce594dab9ed6777fd7cde7e9dae4c99f (patch)
tree60c9154f5bc41df0bd53812c57aee51cc8f3363a
parent8d32bce60e8345d3ab90dbf5018234dac53df162 (diff)
downloadnuttx-242d5e18ce594dab9ed6777fd7cde7e9dae4c99f.tar.gz
nuttx-242d5e18ce594dab9ed6777fd7cde7e9dae4c99f.tar.bz2
nuttx-242d5e18ce594dab9ed6777fd7cde7e9dae4c99f.zip
Add mktemp() and mkstemp()
-rw-r--r--nuttx/include/stdlib.h4
-rw-r--r--nuttx/libc/stdlib/Make.defs4
-rw-r--r--nuttx/libc/stdlib/lib_mkstemp.c297
-rw-r--r--nuttx/libc/stdlib/lib_mktemp.c81
4 files changed, 385 insertions, 1 deletions
diff --git a/nuttx/include/stdlib.h b/nuttx/include/stdlib.h
index 127b35163..c149e0ac1 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/stdlib/Make.defs b/nuttx/libc/stdlib/Make.defs
index 5501ef0c1..6a0d8ad7d 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 000000000..3269463f5
--- /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 000000000..705c5cb9e
--- /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 */
+