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:27 UTC

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

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;
+}