mktemp.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       mktemp.c (4208B)
       ---
            1 /*
            2  * Copyright (c) 1987, 1993
            3  *        The Regents of the University of California.  All rights reserved.
            4  *
            5  * Redistribution and use in source and binary forms, with or without
            6  * modification, are permitted provided that the following conditions
            7  * are met:
            8  * 1. Redistributions of source code must retain the above copyright
            9  *    notice, this list of conditions and the following disclaimer.
           10  * 2. Redistributions in binary form must reproduce the above copyright
           11  *    notice, this list of conditions and the following disclaimer in the
           12  *    documentation and/or other materials provided with the distribution.
           13  * 3. All advertising materials mentioning features or use of this software
           14  *    must display the following acknowledgement:
           15  *        This product includes software developed by the University of
           16  *        California, Berkeley and its contributors.
           17  * 4. Neither the name of the University nor the names of its contributors
           18  *    may be used to endorse or promote products derived from this software
           19  *    without specific prior written permission.
           20  *
           21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
           22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
           23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
           24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
           25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
           26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
           27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
           28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
           29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
           30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
           31  * SUCH DAMAGE.
           32  */
           33 
           34 #include <sys/types.h>
           35 #include <sys/stat.h>
           36 #include <fcntl.h>
           37 #include <errno.h>
           38 #include <stdio.h>
           39 #include <stdlib.h>
           40 #include <string.h>
           41 #include <ctype.h>
           42 #include <unistd.h>
           43 
           44 char *_mktemp(char *);
           45 
           46 static int _gettemp(char *, int *, int, int);
           47 
           48 static const unsigned char padchar[] =
           49 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
           50 
           51 int
           52 mkstemps(path, slen)
           53         char *path;
           54         int slen;
           55 {
           56         int fd;
           57 
           58         return (_gettemp(path, &fd, 0, slen) ? fd : -1);
           59 }
           60 
           61 int
           62 mkstemp(path)
           63         char *path;
           64 {
           65         int fd;
           66 
           67         return (_gettemp(path, &fd, 0, 0) ? fd : -1);
           68 }
           69 
           70 char *
           71 mkdtemp(path)
           72         char *path;
           73 {
           74         return (_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL);
           75 }
           76 
           77 char *
           78 _mktemp(path)
           79         char *path;
           80 {
           81         return (_gettemp(path, (int *)NULL, 0, 0) ? path : (char *)NULL);
           82 }
           83 
           84 char *
           85 mktemp(path)
           86         char *path;
           87 {
           88         return (_mktemp(path));
           89 }
           90 
           91 static int
           92 _gettemp(path, doopen, domkdir, slen)
           93         char *path;
           94         int *doopen;
           95         int domkdir;
           96         int slen;
           97 {
           98         char *start, *trv, *suffp;
           99         char *pad;
          100         struct stat sbuf;
          101         int rval;
          102         uint32_t randx;
          103 
          104         if (doopen != NULL && domkdir) {
          105                 errno = EINVAL;
          106                 return (0);
          107         }
          108 
          109         for (trv = path; *trv != '\0'; ++trv)
          110                 ;
          111         trv -= slen;
          112         suffp = trv;
          113         --trv;
          114         if (trv < path) {
          115                 errno = EINVAL;
          116                 return (0);
          117         }
          118 
          119         /* Fill space with random characters */
          120         while (trv >= path && *trv == 'X') {
          121                 randx = rand() % (sizeof(padchar) - 1);
          122                 *trv-- = padchar[randx];
          123         }
          124         start = trv + 1;
          125 
          126         /*
          127          * check the target directory.
          128          */
          129         if (doopen != NULL || domkdir) {
          130                 for (; trv > path; --trv) {
          131                         if (*trv == '/') {
          132                                 *trv = '\0';
          133                                 rval = stat(path, &sbuf);
          134                                 *trv = '/';
          135                                 if (rval != 0)
          136                                         return (0);
          137                                 if (!S_ISDIR(sbuf.st_mode)) {
          138                                         errno = ENOTDIR;
          139                                         return (0);
          140                                 }
          141                                 break;
          142                         }
          143                 }
          144         }
          145 
          146         for (;;) {
          147                 if (doopen) {
          148                         if ((*doopen =
          149                             open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
          150                                 return (1);
          151                         if (errno != EEXIST)
          152                                 return (0);
          153                 } else if (domkdir) {
          154                         if (mkdir(path, 0700) == 0)
          155                                 return (1);
          156                         if (errno != EEXIST)
          157                                 return (0);
          158                 } else if (lstat(path, &sbuf))
          159                         return (errno == ENOENT);
          160 
          161                 /* If we have a collision, cycle through the space of filenames */
          162                 for (trv = start;;) {
          163                         if (*trv == '\0' || trv == suffp)
          164                                 return (0);
          165                         pad = strchr(padchar, *trv);
          166                         if (pad == NULL || *++pad == '\0')
          167                                 *trv++ = padchar[0];
          168                         else {
          169                                 *trv++ = *pad;
          170                                 break;
          171                         }
          172                 }
          173         }
          174         /*NOTREACHED*/
          175 }