You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2020/09/19 11:16:25 UTC

[incubator-nuttx] branch master updated (0826b82 -> 216c33a)

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git.


    from 0826b82  libs/libc/time: add stub for futimes/ns(2)
     new 7816b5e  include/stdlib: alignment function definitions
     new 4067a9f  libs/libc/stdio: correct the prototype of mktemp(3)
     new 216c33a  libs/libc/stdlib: Implement mkdtemp(3) syscall

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 include/stdlib.h                                 |  37 ++--
 libs/libc/stdio/lib_tempnam.c                    |  17 +-
 libs/libc/stdio/lib_tmpnam.c                     |   6 +-
 libs/libc/stdlib/Make.defs                       |   2 +-
 libs/libc/stdlib/{lib_mktemp.c => lib_mkdtemp.c} |  45 +++--
 libs/libc/stdlib/lib_mkstemp.c                   | 213 +---------------------
 libs/libc/stdlib/lib_mktemp.c                    | 215 ++++++++++++++++++++++-
 7 files changed, 280 insertions(+), 255 deletions(-)
 copy libs/libc/stdlib/{lib_mktemp.c => lib_mkdtemp.c} (57%)


[incubator-nuttx] 03/03: libs/libc/stdlib: Implement mkdtemp(3) syscall

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 216c33a5c714619b07772c38a816d92cf3040dee
Author: chao.an <an...@xiaomi.com>
AuthorDate: Sat Aug 29 12:18:13 2020 +0800

    libs/libc/stdlib: Implement mkdtemp(3) syscall
    
    See the reference here:
    https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdtemp.html
    
    Change-Id: I49081ecafc011a843e6067b1118b53bf65d4418b
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 include/stdlib.h               |  1 +
 libs/libc/stdlib/Make.defs     |  2 +-
 libs/libc/stdlib/lib_mkdtemp.c | 87 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 89 insertions(+), 1 deletion(-)

diff --git a/include/stdlib.h b/include/stdlib.h
index feab8a0..3eaf0e2 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -237,6 +237,7 @@ lldiv_t   lldiv(long long number, long long denom);
 
 FAR char *mktemp(FAR char *path_template);
 int       mkstemp(FAR char *path_template);
+FAR char *mkdtemp(FAR char *path_template);
 
 /* Sorting */
 
diff --git a/libs/libc/stdlib/Make.defs b/libs/libc/stdlib/Make.defs
index 22e33d9..2a5bcb7 100644
--- a/libs/libc/stdlib/Make.defs
+++ b/libs/libc/stdlib/Make.defs
@@ -25,7 +25,7 @@ CSRCS += lib_atol.c lib_atoll.c lib_div.c lib_ldiv.c lib_lldiv.c lib_Exit.c
 CSRCS += lib_itoa.c lib_labs.c lib_llabs.c lib_realpath.c lib_bsearch.c
 CSRCS += lib_rand.c lib_posix_memalign.c lib_qsort.c lib_srand.c lib_strtol.c
 CSRCS += lib_strtoll.c lib_strtoul.c lib_strtoull.c lib_strtod.c lib_strtof.c
-CSRCS += lib_strtold.c lib_checkbase.c lib_mktemp.c lib_mkstemp.c
+CSRCS += lib_strtold.c lib_checkbase.c lib_mktemp.c lib_mkstemp.c lib_mkdtemp.c
 
 ifeq ($(CONFIG_LIBC_WCHAR),y)
 CSRCS += lib_mblen.c lib_mbtowc.c lib_wctomb.c
diff --git a/libs/libc/stdlib/lib_mkdtemp.c b/libs/libc/stdlib/lib_mkdtemp.c
new file mode 100644
index 0000000..59e7a14
--- /dev/null
+++ b/libs/libc/stdlib/lib_mkdtemp.c
@@ -0,0 +1,87 @@
+/****************************************************************************
+ * libs/libc/stdlib/lib_mkdtemp.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/compiler.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+/****************************************************************************
+ * Pre-processor definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mkdtemp
+ *
+ * Description:
+ *  The mkdtemp() function shall create a directory with a unique name
+ *  derived from template. The application shall ensure that the string
+ *  provided in template is a pathname ending with at least six trailing
+ *  'X' characters. The mkdtemp() function shall modify the contents of
+ *  template by replacing six or more 'X' characters at the end of the
+ *  pathname with the same number of characters from the portable filename
+ *  character set. The characters shall be chosen such that the resulting
+ *  pathname does not duplicate the name of an existing file at the time
+ *  of the call to mkdtemp(). The mkdtemp() function shall use the
+ *  resulting pathname to create the new directory as if by a call to:
+ *
+ * Input Parameters:
+ *   template - The base directory name that will be modified to produce
+ *     the unique 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, the mkdtemp() function shall return the
+ *   value of template. Otherwise, it shall return a null pointer and
+ *   shall set errno to indicate the error.
+ *
+ ****************************************************************************/
+
+FAR char *mkdtemp(FAR char *path_template)
+{
+  FAR char *path = mktemp(path_template);
+
+  if (path)
+    {
+      if (mkdir(path, S_IRWXU) < 0)
+        {
+          path = NULL;
+        }
+    }
+
+  return path;
+}


[incubator-nuttx] 01/03: include/stdlib: alignment function definitions

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 7816b5ec8c1f171d4ef8380c68d6ce5372f1a9aa
Author: chao.an <an...@xiaomi.com>
AuthorDate: Sat Aug 29 11:03:19 2020 +0800

    include/stdlib: alignment function definitions
    
    Change-Id: Id12ed4241698c8d4426907ca72eef334894ee1f3
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 include/stdlib.h | 36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/include/stdlib.h b/include/stdlib.h
index fd6df08..3f32264 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -170,13 +170,13 @@ double    strtod(FAR const char *str, FAR char **endptr);
 long double strtold(FAR const char *str, FAR char **endptr);
 #endif
 
-int atoi(FAR const char *nptr);
-long atol(FAR const char *nptr);
+int       atoi(FAR const char *nptr);
+long      atol(FAR const char *nptr);
 #ifdef CONFIG_HAVE_LONG_LONG
 long long atoll(FAR const char *nptr);
 #endif
 #ifdef CONFIG_HAVE_DOUBLE
-double atof(FAR const char *nptr);
+double    atof(FAR const char *nptr);
 #endif
 
 /* Binary to string conversions */
@@ -202,17 +202,17 @@ FAR void *memalign(size_t, size_t);
 FAR void *zalloc(size_t);
 FAR void *calloc(size_t, size_t);
 FAR void *aligned_alloc(size_t, size_t);
-int posix_memalign(FAR void **, size_t, size_t);
+int       posix_memalign(FAR void **, size_t, size_t);
 
 /* Pseudo-Terminals */
 
 #ifdef CONFIG_PSEUDOTERM_SUSV1
 FAR char *ptsname(int fd);
-int ptsname_r(int fd, FAR char *buf, size_t buflen);
+int       ptsname_r(int fd, FAR char *buf, size_t buflen);
 #endif
 
 #ifdef CONFIG_PSEUDOTERM
-int unlockpt(int fd);
+int       unlockpt(int fd);
 
 /* int grantpt(int fd); Not implemented */
 
@@ -221,33 +221,33 @@ int unlockpt(int fd);
 
 /* Arithmetic */
 
-int      abs(int j);
-long int labs(long int j);
+int       abs(int j);
+long int  labs(long int j);
 #ifdef CONFIG_HAVE_LONG_LONG
 long long int llabs(long long int j);
 #endif
 
-div_t    div(int number, int denom);
-ldiv_t   ldiv(long number, long denom);
+div_t     div(int number, int denom);
+ldiv_t    ldiv(long number, long denom);
 #ifdef CONFIG_HAVE_LONG_LONG
-lldiv_t  lldiv(long long number, long long denom);
+lldiv_t   lldiv(long long number, long long denom);
 #endif
 
 /* Temporary files */
 
-int      mktemp(FAR char *path_template);
-int      mkstemp(FAR char *path_template);
+int       mktemp(FAR char *path_template);
+int       mkstemp(FAR char *path_template);
 
 /* Sorting */
 
-void     qsort(FAR void *base, size_t nel, size_t width,
-               CODE int (*compar)(FAR const void *, FAR const void *));
+void      qsort(FAR void *base, size_t nel, size_t width,
+                CODE int (*compar)(FAR const void *, FAR const void *));
 
 /* Binary search */
 
-FAR void *bsearch(FAR const void *key, FAR const void *base, size_t nel,
-                  size_t width, CODE int (*compar)(FAR const void *,
-                  FAR const void *));
+FAR void  *bsearch(FAR const void *key, FAR const void *base, size_t nel,
+                   size_t width, CODE int (*compar)(FAR const void *,
+                   FAR const void *));
 
 #undef EXTERN
 #if defined(__cplusplus)


[incubator-nuttx] 02/03: libs/libc/stdio: correct the prototype of mktemp(3)

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 4067a9f0579c35cbaa54626ca8053a76d0b7b9e8
Author: chao.an <an...@xiaomi.com>
AuthorDate: Thu Sep 17 16:03:38 2020 +0800

    libs/libc/stdio: correct the prototype of mktemp(3)
    
    From:   int       mktemp(FAR char *path_template);
    To:     FAR char *mktemp(FAR char *path_template);
    
    See the reference here:
    https://pubs.opengroup.org/onlinepubs/009695399/functions/mktemp.html
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 include/stdlib.h               |   2 +-
 libs/libc/stdio/lib_tempnam.c  |  17 ++--
 libs/libc/stdio/lib_tmpnam.c   |   6 +-
 libs/libc/stdlib/lib_mkstemp.c | 213 ++--------------------------------------
 libs/libc/stdlib/lib_mktemp.c  | 215 +++++++++++++++++++++++++++++++++++++++--
 5 files changed, 226 insertions(+), 227 deletions(-)

diff --git a/include/stdlib.h b/include/stdlib.h
index 3f32264..feab8a0 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -235,7 +235,7 @@ lldiv_t   lldiv(long long number, long long denom);
 
 /* Temporary files */
 
-int       mktemp(FAR char *path_template);
+FAR char *mktemp(FAR char *path_template);
 int       mkstemp(FAR char *path_template);
 
 /* Sorting */
diff --git a/libs/libc/stdio/lib_tempnam.c b/libs/libc/stdio/lib_tempnam.c
index 1e2acaf..b9ef6e3 100644
--- a/libs/libc/stdio/lib_tempnam.c
+++ b/libs/libc/stdio/lib_tempnam.c
@@ -87,21 +87,24 @@
 
 FAR char *tempnam(FAR const char *dir, FAR const char *pfx)
 {
+  FAR char *template;
   FAR char *path;
-  int ret;
 
-  asprintf(&path, "%s/%s-XXXXXX.tmp", dir, pfx);
-  if (path)
+  asprintf(&template, "%s/%s-XXXXXX", dir, pfx);
+  if (template)
     {
-      ret = mktemp(path);
-      if (ret == OK)
+      path = mktemp(template);
+      if (path != NULL)
         {
           return path;
         }
 
-      lib_free(path);
+      lib_free(template);
+    }
+  else
+    {
+      set_errno(ENOMEM);
     }
 
-  set_errno(ENOMEM);
   return NULL;
 }
diff --git a/libs/libc/stdio/lib_tmpnam.c b/libs/libc/stdio/lib_tmpnam.c
index 67d0eb8..b94caa2 100644
--- a/libs/libc/stdio/lib_tmpnam.c
+++ b/libs/libc/stdio/lib_tmpnam.c
@@ -82,14 +82,12 @@
 FAR char *tmpnam(FAR char *s)
 {
   static char path[L_tmpnam];
-  int ret;
 
   if (s == NULL)
     {
       s = path;
     }
 
-  snprintf(s, L_tmpnam, "%s/XXXXXX.tmp", P_tmpdir);
-  ret = mktemp(s);
-  return (ret == OK) ? s : NULL;
+  snprintf(s, L_tmpnam, "%s/XXXXXX", P_tmpdir);
+  return mktemp(s);
 }
diff --git a/libs/libc/stdlib/lib_mkstemp.c b/libs/libc/stdlib/lib_mkstemp.c
index 9fcc2df..b6ef6c5 100644
--- a/libs/libc/stdlib/lib_mkstemp.c
+++ b/libs/libc/stdlib/lib_mkstemp.c
@@ -25,143 +25,9 @@
 #include <nuttx/config.h>
 #include <nuttx/compiler.h>
 
-#include <stdint.h>
-#include <stdio.h>
-#include <fcntl.h>
+#include <unistd.h>
 #include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include <nuttx/semaphore.h>
-
-/****************************************************************************
- * Pre-processor definitions
- ****************************************************************************/
-
-#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 = MAX_XS - 1; i >= 0; 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(_SEM_ERRNO(ret) == EINTR || _SEM_ERRNO(ret) == ECANCELED);
-    }
-
-  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 const uint8_t *src, FAR char *dest, int len)
-{
-  if (len < MAX_XS)
-    {
-      src += MAX_XS - len;
-    }
-
-  for (; len > 0; len--)
-    {
-      *dest++ = base62_to_char(*src++);
-    }
-}
+#include <fcntl.h>
 
 /****************************************************************************
  * Public Functions
@@ -195,78 +61,13 @@ static void copy_base62(FAR const uint8_t *src, FAR char *dest, int len)
 
 int mkstemp(FAR char *path_template)
 {
-  uint8_t base62[MAX_XS];
-  uint32_t retries;
-  FAR char *xptr;
-  int xlen;
-  int fd;
-  int i;
-
-  /* Count the number of X's at the end of the template */
-
-  xptr = &path_template[strlen(path_template)];
-  for (xlen = 0; xlen < MAX_XS && path_template < xptr && *(xptr - 1) == 'X';
-       xlen++, xptr--);
+  FAR char *path = mktemp(path_template);
+  int ret = ERROR;
 
-  if (xlen == 0)
+  if (path)
     {
-      /* No Xs?  There should always really be 6 */
-
-      return open(path_template, O_RDWR | O_CREAT | O_EXCL, 0666);
-    }
-
-  /* Ignore any X's after the sixth */
-
-  if (xlen > MAX_XS)
-    {
-      xptr += 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(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(path_template, O_RDWR | O_CREAT | O_EXCL, 0666);
-      if (fd >= 0)
-        {
-          /* We have it... return the file descriptor */
-
-          return fd;
-        }
-
-      retries--;
+      ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0666);
     }
 
-  /* We could not find an unique filename */
-
-  return ERROR;
+  return ret;
 }
-
diff --git a/libs/libc/stdlib/lib_mktemp.c b/libs/libc/stdlib/lib_mktemp.c
index 1c4f15d..eb3c438 100644
--- a/libs/libc/stdlib/lib_mktemp.c
+++ b/libs/libc/stdlib/lib_mktemp.c
@@ -25,18 +25,147 @@
 #include <nuttx/config.h>
 #include <nuttx/compiler.h>
 
-#include <unistd.h>
+#include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <nuttx/semaphore.h>
 
 /****************************************************************************
  * Pre-processor definitions
  ****************************************************************************/
 
+#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 = MAX_XS - 1; i >= 0; 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(_SEM_ERRNO(ret) == EINTR || _SEM_ERRNO(ret) == ECANCELED);
+    }
+
+  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 const uint8_t *src, FAR char *dest, int len)
+{
+  if (len < MAX_XS)
+    {
+      src += MAX_XS - len;
+    }
+
+  for (; len > 0; len--)
+    {
+      *dest++ = base62_to_char(*src++);
+    }
+}
+
+/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
@@ -44,19 +173,87 @@
  * Name: mktemp
  *
  * Description:
- *   The use of mktemp is dangerous; use mkstemp instead.
+ *   The mktemp() function generates a unique temporary filename from
+ *   template. The last six characters of template must be XXXXXX and these
+ *   are replaced with a string that makes the filename unique. Since it
+ *   will be modified, template must not be a string constant, but should be
+ *   declared as a character array.
  *
  ****************************************************************************/
 
-int mktemp(FAR char *path_template)
+FAR char *mktemp(FAR char *path_template)
 {
-  int fd = mkstemp(path_template);
-  if (fd < 0)
+  uint8_t base62[MAX_XS];
+  uint32_t retries;
+  struct stat buf;
+  FAR char *xptr;
+  int xlen;
+  int ret;
+  int i;
+
+  /* Count the number of X's at the end of the template */
+
+  xptr = &path_template[strlen(path_template)];
+  for (xlen = 0; xlen < MAX_XS && path_template < xptr && *(xptr - 1) == 'X';
+       xlen++, xptr--);
+
+  if (xlen == 0)
     {
-      return ERROR;
+      /* No Xs?  There should always really be 6 */
+
+      return path_template;
     }
 
-  close(fd);
-  return OK;
-}
+  /* Ignore any X's after the sixth */
 
+  if (xlen > MAX_XS)
+    {
+      xptr += 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(base62, xptr, xlen);
+
+      /* Attempt to stat the candidate file */
+
+      ret = stat(path_template, &buf);
+      if (ret < 0 && errno == ENOENT)
+        {
+          /* We have it... Clear the errno and return the template */
+
+          set_errno(0);
+          return path_template;
+        }
+
+      retries--;
+    }
+
+  /* We could not find an unique filename */
+
+  set_errno(EINVAL);
+
+  return NULL;
+}