Browse Source

Rework __gen_tempname() to better match glibc, and add mkstemp64(),
which is needed for busybox ash when using largefile support.
-Erik

Eric Andersen 23 years ago
parent
commit
cdb29e3ea6

+ 13 - 0
include/features.h

@@ -417,6 +417,19 @@ uClibc was built without large file support enabled.
 /* --- this is added to integrate linuxthreads */
 #define __USE_UNIX98            1
 
+/* For want of a better place, here are some function prototypes
+ * for things from libc/misc/internals */
+#define	__need_size_t
+#include <stddef.h>
+extern int __path_search (char *tmpl, size_t tmpl_len, const char *dir, 
+	        const char *pfx, int try_tmpdir);
+extern int __gen_tempname (char *__tmpl, int __kind);
+/* The __kind argument to __gen_tempname may be one of: */
+#define __GT_FILE     0       /* create a file */
+#define __GT_BIGFILE  1       /* create a file, using open64 */
+#define __GT_DIR      2       /* create a directory */
+#define __GT_NOCREATE 3       /* just find a name not currently in use */
+
 #endif /* _LIBC only stuff */
 
 

+ 64 - 42
libc/misc/internals/tempname.c

@@ -27,12 +27,14 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/time.h>
 
+
 /* Return nonzero if DIR is an existent directory.  */
 static int direxists (const char *dir)
 {
@@ -46,8 +48,8 @@ static int direxists (const char *dir)
    for use with mk[s]temp.  Will fail (-1) if DIR is non-null and
    doesn't exist, none of the searched dirs exists, or there's not
    enough space in TMPL. */
-int __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx,
-	       int try_tmpdir)
+int __path_search (char *tmpl, size_t tmpl_len, const char *dir, 
+	const char *pfx, int try_tmpdir)
 {
     //const char *d;
     size_t dlen, plen;
@@ -111,22 +113,28 @@ static const char letters[] =
 /* Generate a temporary file name based on TMPL.  TMPL must match the
    rules for mk[s]temp (i.e. end in "XXXXXX").  The name constructed
    does not exist at the time of the call to __gen_tempname.  TMPL is
-   overwritten with the result.  If OPENIT is nonzero, creates the
-   file and returns a read-write fd; the file is mode 0600 modulo
-   umask.  If LARGEFILE is nonzero, uses open64() instead of open().
+   overwritten with the result.  
+
+   KIND may be one of:
+   __GT_NOCREATE:       simply verify that the name does not exist
+                        at the time of the call.
+   __GT_FILE:           create the file using open(O_CREAT|O_EXCL)
+                        and return a read-write fd.  The file is mode 0600.
+   __GT_BIGFILE:        same as __GT_FILE but use open64().
+   __GT_DIR:            create a directory, which will be mode 0700.
 
    We use a clever algorithm to get hard-to-predict names. */
-int __gen_tempname (char *tmpl, int openit)
+int __gen_tempname (char *tmpl, int kind)
 {
     int len;
     char *XXXXXX;
     static uint64_t value;
     struct timeval tv;
-	uint32_t high, low, rh;
-	unsigned int k;
+    uint32_t high, low, rh;
+    unsigned int k;
     int count, fd;
     int save_errno = errno;
-	int i;
+    int i;
 
     len = strlen (tmpl);
     if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
@@ -148,46 +156,60 @@ int __gen_tempname (char *tmpl, int openit)
 	high = value >> 32;
 
 	for (i = 0 ; i < 6 ; i++) {
-		rh = high % 62;
-		high /= 62;
+	    rh = high % 62;
+	    high /= 62;
 #define L ((UINT32_MAX % 62 + 1) % 62)
-		k = (low % 62) + (L * rh);
+	    k = (low % 62) + (L * rh);
 #undef L
 #define H ((UINT32_MAX / 62) + ((UINT32_MAX % 62 + 1) / 62))
-		low = (low / 62) + (H * rh) + (k / 62);
+	    low = (low / 62) + (H * rh) + (k / 62);
 #undef H
-		k %= 62;
-		XXXXXX[i] = letters[k];
+	    k %= 62;
+	    XXXXXX[i] = letters[k];
 	}
 
-	if (openit)
-	{
-	    fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, 0600);
-	    if (fd >= 0)
-	    {
-		__set_errno (save_errno);
-		return fd;
-	    }
-	    else if (errno != EEXIST)
-		/* Any other error will apply also to other names we might
-		   try, and there are 2^32 or so of them, so give up now. */
-		return -1;
-	}
-	else
-	{
-	    struct stat st;
-	    if (stat (tmpl, &st) < 0)
-	    {
-		if (errno == ENOENT)
+	switch(kind) {
+	    case __GT_NOCREATE:
 		{
-		    __set_errno (save_errno);
-		    return 0;
+		    struct stat st;
+		    if (stat (tmpl, &st) < 0)
+		    {
+			if (errno == ENOENT)
+			{
+			    __set_errno (save_errno);
+			    return 0;
+			}
+			else
+			    /* Give up now. */
+			    return -1;
+		    }
+		    else
+			continue;
 		}
-		else
-		    /* Give up now. */
-		    return -1;
-	    }
+	    case __GT_FILE:
+		fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+		break;
+#if defined __UCLIBC_HAVE_LFS__
+	    case __GT_BIGFILE:
+		fd = open64 (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+		break;
+#endif
+	    case __GT_DIR:
+		fd = mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
+		break;
+	    default:
+		fd = -1;
+		assert (! "invalid KIND in __gen_tempname");
 	}
+
+	if (fd >= 0) {
+	    __set_errno (save_errno);
+	    return fd;
+	}
+	else if (errno != EEXIST)
+	    /* Any other error will apply also to other names we might
+	       try, and there are 2^32 or so of them, so give up now. */
+	    return -1;
     }
 
     /* We got out of the loop because we ran out of combinations to try.  */

+ 1 - 6
libc/stdio/tempnam.c

@@ -19,11 +19,6 @@
 #include <stdio.h>
 #include <string.h>
 
-extern int __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx,
-	               int try_tmpdir);
-extern int __gen_tempname (char *tmpl, int openit);
-
-
 /* Generate a unique temporary filename using up to five characters of PFX
    if it is not NULL.  The directory to put this file in is searched for
    as follows: First the environment variable "TMPDIR" is checked.
@@ -39,7 +34,7 @@ tempnam (const char *dir, const char *pfx)
   if (__path_search (buf, FILENAME_MAX, dir, pfx, 1))
     return NULL;
 
-  if (__gen_tempname (buf, 0))
+  if (__gen_tempname (buf, __GT_NOCREATE))
     return NULL;
 
   return strdup (buf);

+ 1 - 5
libc/stdio/tmpfile.c

@@ -20,10 +20,6 @@
 #include <stdio.h>
 #include <unistd.h>
 
-extern int __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx,
-	       int try_tmpdir);
-extern int __gen_tempname (char *tmpl, int openit);
-
 /* This returns a new stream opened on a temporary file (generated
    by tmpnam).  The file is opened with mode "w+b" (binary read/write).
    If we couldn't generate a unique filename or the file couldn't
@@ -36,7 +32,7 @@ FILE * tmpfile (void)
 
     if (__path_search (buf, FILENAME_MAX, NULL, "tmpf", 0))
 	return NULL;
-    fd = __gen_tempname (buf, 1);
+    fd = __gen_tempname (buf, __GT_FILE);
     if (fd < 0)
 	return NULL;
 

+ 3 - 7
libc/stdio/tmpnam.c

@@ -19,15 +19,11 @@
 #include <stdio.h>
 #include <string.h>
 
-extern int __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx,
-	       int try_tmpdir);
-extern int __gen_tempname (char *tmpl, int openit);
-
 static char tmpnam_buffer[L_tmpnam];
 
 /* Generate a unique filename in P_tmpdir.
-
-   This function is *not* thread safe when S == NULL!  */
+   This function is *not* thread safe when S == NULL!  
+*/
 char * tmpnam (char *s)
 {
     /* By using two buffers we manage to be thread safe in the case
@@ -40,7 +36,7 @@ char * tmpnam (char *s)
     if (__path_search (s ? : tmpbuf, L_tmpnam, NULL, NULL, 0))
 	return NULL;
 
-    if (__gen_tempname (s ? : tmpbuf, 0))
+    if (__gen_tempname (s ? : tmpbuf, __GT_NOCREATE))
 	return NULL;
 
     if (s == NULL)

+ 1 - 5
libc/stdio/tmpnam_r.c

@@ -18,10 +18,6 @@
 
 #include <stdio.h>
 
-extern int __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx,
-	       int try_tmpdir);
-extern int __gen_tempname (char *tmpl, int openit);
-
 /* Generate a unique filename in P_tmpdir.  If S is NULL return NULL.
    This makes this function thread safe.  */
 char * tmpnam_r (char *s)
@@ -31,7 +27,7 @@ char * tmpnam_r (char *s)
 
     if (__path_search (s, L_tmpnam, NULL, NULL, 0))
 	return NULL;
-    if (__gen_tempname (s, 0))
+    if (__gen_tempname (s, __GT_NOCREATE))
 	return NULL;
 
     return s;

+ 2 - 2
libc/stdlib/Makefile

@@ -38,8 +38,8 @@ MSRC2=atexit.c
 MOBJ2=atexit.o on_exit.o __exit_handler.o exit.o
 
 CSRC =	abort.c getenv.c mktemp.c qsort.c realpath.c bsearch.c \
-	mkstemp.c putenv.c rand.c random.c random_r.c setenv.c system.c div.c \
-	ldiv.c getpt.c ptsname.c grantpt.c unlockpt.c gcvt.c
+	mkstemp.c mkstemp64.c putenv.c rand.c random.c random_r.c setenv.c \
+	system.c div.c ldiv.c getpt.c ptsname.c grantpt.c unlockpt.c gcvt.c
 CSRC+=  drand48.c drand48-iter.c drand48_r.c erand48.c erand48_r.c \
 	jrand48.c jrand48_r.c lrand48.c lrand48_r.c mrand48.c mrand48_r.c \
 	nrand48.c nrand48_r.c rand_r.c srand48.c srand48_r.c

+ 1 - 3
libc/stdlib/mkstemp.c

@@ -19,13 +19,11 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-extern int __gen_tempname (char *tmpl, int openit);
-
 /* Generate a unique temporary file name from TEMPLATE.
    The last six characters of TEMPLATE must be "XXXXXX";
    they are replaced with a string that makes the filename unique.
    Then open the file and return a fd. */
 int mkstemp (char *template)
 {
-    return __gen_tempname (template, 1);
+    return __gen_tempname (template, __GT_FILE);
 }

+ 29 - 0
libc/stdlib/mkstemp64.c

@@ -0,0 +1,29 @@
+/* Copyright (C) 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Generate a unique temporary file name from TEMPLATE.
+   The last six characters of TEMPLATE must be "XXXXXX";
+   they are replaced with a string that makes the filename unique.
+   Then open the file and return a fd. */
+int mkstemp64 (char *template)
+{
+    return __gen_tempname (template, __GT_BIGFILE);
+}

+ 1 - 3
libc/stdlib/mktemp.c

@@ -19,14 +19,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-extern int __gen_tempname (char *tmpl, int openit);
-
 /* Generate a unique temporary file name from TEMPLATE.
    The last six characters of TEMPLATE must be "XXXXXX";
    they are replaced with a string that makes the filename unique.  */
 char * mktemp (char *template)
 {
-    if (__gen_tempname (template, 0) < 0)
+    if (__gen_tempname (template, __GT_NOCREATE) < 0)
 	/* We return the null string if we can't find a unique file name.  */
 	template[0] = '\0';