Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libc add mkostemp, mkostemps, mkstemps from FreeBSD.



details:   https://anonhg.NetBSD.org/src/rev/afafccc71183
branches:  trunk
changeset: 330037:afafccc71183
user:      christos <christos%NetBSD.org@localhost>
date:      Wed Jun 18 17:47:58 2014 +0000

description:
add mkostemp, mkostemps, mkstemps from FreeBSD.

diffstat:

 lib/libc/shlib_version      |    4 +-
 lib/libc/stdio/Makefile.inc |    7 +-
 lib/libc/stdio/gettemp.c    |  170 ++++++++++++++++++++-----------------------
 lib/libc/stdio/gettemp.h    |   48 ++++++++++++
 lib/libc/stdio/local.h      |    6 +-
 lib/libc/stdio/mkdtemp.c    |   23 +----
 lib/libc/stdio/mkostemp.c   |   36 +++++++++
 lib/libc/stdio/mkostemps.c  |   36 +++++++++
 lib/libc/stdio/mkstemp.c    |   26 +-----
 lib/libc/stdio/mkstemps.c   |   36 +++++++++
 lib/libc/stdio/mktemp.3     |   75 ++++++++++++++++++-
 lib/libc/stdio/mktemp.c     |   15 +--
 12 files changed, 326 insertions(+), 156 deletions(-)

diffs (truncated from 741 to 300 lines):

diff -r d370f8610aeb -r afafccc71183 lib/libc/shlib_version
--- a/lib/libc/shlib_version    Wed Jun 18 14:47:02 2014 +0000
+++ b/lib/libc/shlib_version    Wed Jun 18 17:47:58 2014 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: shlib_version,v 1.251 2014/06/13 15:45:05 joerg Exp $
+#      $NetBSD: shlib_version,v 1.252 2014/06/18 17:47:58 christos Exp $
 #      Remember to update distrib/sets/lists/base/shl.* when changing
 #
 # things we wish to do on next major version bump:
@@ -41,4 +41,4 @@
 # - redo stdin/stdout/stderr to not require copy relocations
 # - move gethostbyname to a compat library
 major=12
-minor=191
+minor=192
diff -r d370f8610aeb -r afafccc71183 lib/libc/stdio/Makefile.inc
--- a/lib/libc/stdio/Makefile.inc       Wed Jun 18 14:47:02 2014 +0000
+++ b/lib/libc/stdio/Makefile.inc       Wed Jun 18 17:47:58 2014 +0000
@@ -1,5 +1,5 @@
 #      from: @(#)Makefile.inc  5.7 (Berkeley) 6/27/91
-#      $NetBSD: Makefile.inc,v 1.43 2014/01/16 20:31:43 christos Exp $
+#      $NetBSD: Makefile.inc,v 1.44 2014/06/18 17:47:58 christos Exp $
 
 # stdio sources
 .PATH: ${.CURDIR}/stdio
@@ -13,8 +13,9 @@
        fread.c freopen.c fscanf.c fseek.c fseeko.c fsetpos.c ftell.c ftello.c \
        funopen.c fvwrite.c fwalk.c fwide.c fwprintf.c fwrite.c fwscanf.c \
        getc.c getchar.c getdelim.c getline.c gettemp.c getw.c getwc.c \
-       getwchar.c makebuf.c mkdtemp.c mkstemp.c perror.c printf.c putc.c \
-       putchar.c puts.c putw.c putwc.c putwchar.c refill.c remove.c rewind.c \
+       getwchar.c makebuf.c mkdtemp.c mkstemp.c mkstemps.c mkostemp.c \
+       mkostemps.c perror.c printf.c putc.c putchar.c puts.c putw.c putwc.c \
+       putwchar.c refill.c remove.c rewind.c \
        rget.c scanf.c setbuf.c setbuffer.c setvbuf.c snprintf_ss.c \
        sscanf.c stdio.c swprintf.c swscanf.c tmpfile.c ungetc.c ungetwc.c \
        vasprintf.c vdprintf.c vfprintf.c vfscanf.c vfwprintf.c vfwscanf.c \
diff -r d370f8610aeb -r afafccc71183 lib/libc/stdio/gettemp.c
--- a/lib/libc/stdio/gettemp.c  Wed Jun 18 14:47:02 2014 +0000
+++ b/lib/libc/stdio/gettemp.c  Wed Jun 18 17:47:58 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: gettemp.c,v 1.17 2014/01/21 19:09:48 seanb Exp $       */
+/*     $NetBSD: gettemp.c,v 1.18 2014/06/18 17:47:58 christos Exp $    */
 
 /*
  * Copyright (c) 1987, 1993
@@ -29,9 +29,7 @@
  * SUCH DAMAGE.
  */
 
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
+#include "gettemp.h"
 
 #if !HAVE_NBTOOL_CONFIG_H || !HAVE_MKSTEMP || !HAVE_MKDTEMP
 
@@ -40,129 +38,119 @@
 #if 0
 static char sccsid[] = "@(#)mktemp.c   8.1 (Berkeley) 6/4/93";
 #else
-__RCSID("$NetBSD: gettemp.c,v 1.17 2014/01/21 19:09:48 seanb Exp $");
+__RCSID("$NetBSD: gettemp.c,v 1.18 2014/06/18 17:47:58 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
+#include <sys/param.h>
 #include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
+#include <string.h>
 
-#if HAVE_NBTOOL_CONFIG_H
-#define        GETTEMP         __nbcompat_gettemp
-#else
-#include "reentrant.h"
-#include "local.h"
-#define        GETTEMP         __gettemp
-#endif
+static const unsigned char padchar[] =
+"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
 
 int
-GETTEMP(char *path, int *doopen, int domkdir)
+GETTEMP(char *path, int *doopen, int domkdir, int slen, int oflags)
 {
-       char *start, *trv;
+       char *start, *trv, *suffp, *carryp;
+       char *pad;
        struct stat sbuf;
-       u_int pid;
-
-       /* To guarantee multiple calls generate unique names even if
-          the file is not created. 676 different possibilities with 7
-          or more X's, 26 with 6 or less. */
-       static char xtra[2] = "aa";
-       int xcnt = 0;
+       int rval;
+       uint32_t rand;
+       char carrybuf[MAXPATHLEN];
 
        _DIAGASSERT(path != NULL);
        /* doopen may be NULL */
-
-       pid = getpid();
-
-       /* Move to end of path and count trailing X's. */
-       for (trv = path; *trv; ++trv)
-               if (*trv == 'X')
-                       xcnt++;
-               else
-                       xcnt = 0;       
-
-       /* Use at least one from xtra.  Use 2 if more than 6 X's. */
-       if (xcnt > 0) {
-               *--trv = xtra[0];
-               xcnt--;
-       }
-       if (xcnt > 5) {
-               *--trv = xtra[1];
-               xcnt--;
+       if ((doopen != NULL && domkdir) || slen < 0 ||
+           (oflags & ~(O_APPEND | O_DIRECT | O_SHLOCK | O_EXLOCK | O_SYNC |
+           O_CLOEXEC)) != 0) {
+               errno = EINVAL;
+               return 0;
        }
 
-       /* Set remaining X's to pid digits with 0's to the left. */
-       for (; xcnt > 0; xcnt--) {
-               *--trv = (pid % 10) + '0';
-               pid /= 10;
+       for (trv = path; *trv != '\0'; ++trv)
+               continue;
+
+       if (trv - path >= MAXPATHLEN) {
+               errno = ENAMETOOLONG;
+               return 0;
+       }
+       trv -= slen;
+       suffp = trv;
+       --trv;
+       if (trv < path || NULL != strchr(suffp, '/')) {
+               errno = EINVAL;
+               return 0;
        }
 
-       /* update xtra for next call. */
-       if (xtra[0] != 'z')
-               xtra[0]++;
-       else {
-               xtra[0] = 'a';
-               if (xtra[1] != 'z')
-                       xtra[1]++;
-               else
-                       xtra[1] = 'a';
+       /* Fill space with random characters */
+       while (trv >= path && *trv == 'X') {
+               rand = arc4random_uniform(sizeof(padchar) - 1);
+               *trv-- = padchar[rand];
        }
+       start = trv + 1;
+
+       /* save first combination of random characters */
+       memcpy(carrybuf, start, suffp - start);
 
        /*
-        * check the target directory; if you have six X's and it
-        * doesn't exist this runs for a *very* long time.
+        * check the target directory.
         */
-       for (start = trv + 1;; --trv) {
-               if (trv <= path)
-                       break;
-               if (*trv == '/') {
-                       int e;
-                       *trv = '\0';
-                       e = stat(path, &sbuf);
-                       *trv = '/';
-                       if (e == -1)
-                               return doopen == NULL && !domkdir;
-                       if (!S_ISDIR(sbuf.st_mode)) {
-                               errno = ENOTDIR;
-                               return doopen == NULL && !domkdir;
+       if (doopen != NULL || domkdir) {
+               for (; trv > path; --trv) {
+                       if (*trv == '/') {
+                               *trv = '\0';
+                               rval = stat(path, &sbuf);
+                               *trv = '/';
+                               if (rval != 0)
+                                       return 0;
+                               if (!S_ISDIR(sbuf.st_mode)) {
+                                       errno = ENOTDIR;
+                                       return 0;
+                               }
+                               break;
                        }
-                       break;
                }
        }
 
        for (;;) {
                if (doopen) {
-                       if ((*doopen =
-                           open(path, O_CREAT | O_EXCL | O_RDWR, 0600)) >= 0)
+                       if ((*doopen = open(path, O_CREAT|O_EXCL|O_RDWR|oflags,
+                           0600)) != -1)
                                return 1;
                        if (errno != EEXIST)
                                return 0;
                } else if (domkdir) {
-                       if (mkdir(path, 0700) >= 0)
+                       if (mkdir(path, 0700) != -1)
                                return 1;
                        if (errno != EEXIST)
                                return 0;
                } else if (lstat(path, &sbuf))
-                       return errno == ENOENT ? 1 : 0;
+                       return errno == ENOENT;
 
-               /* tricky little algorithm for backward compatibility */
-               for (trv = start;;) {
-                       if (!*trv)
+               /*
+                * If we have a collision,
+                * cycle through the space of filenames
+                */
+               for (trv = start, carryp = carrybuf;;) {
+                       /* have we tried all possible permutations? */
+                       if (trv == suffp)
+                               return 0; /* yes - exit with EEXIST */
+                       pad = strchr((const char *)padchar, *trv);
+                       if (pad == NULL) {
+                               /* this should never happen */
+                               errno = EIO;
                                return 0;
-                       if (*trv == 'z')
-                               *trv++ = 'a';
-                       else {
-                               if (isdigit((unsigned char)*trv))
-                                       *trv = 'a';
-                               else
-                                       ++*trv;
+                       }
+                       /* increment character */
+                       *trv = (*++pad == '\0') ? padchar[0] : *pad;
+                       /* carry to next position? */
+                       if (*trv == *carryp) {
+                               /* increment position and loop */
+                               ++trv;
+                               ++carryp;
+                       } else {
+                               /* try with new name */
                                break;
                        }
                }
diff -r d370f8610aeb -r afafccc71183 lib/libc/stdio/gettemp.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libc/stdio/gettemp.h  Wed Jun 18 17:47:58 2014 +0000
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+#ifndef _GETTEMP_H_
+#define _GETTEMP_H_
+
+#include "namespace.h"
+
+#if HAVE_NBTOOL_CONFIG_H
+# include "nbtool_config.h"



Home | Main Index | Thread Index | Old Index