mkstemps.c

00001 /*
00002  * Copyright (c) 1987, 1993
00003  *  The Regents of the University of California.  All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. All advertising materials mentioning features or use of this software
00014  *    must display the following acknowledgement:
00015  *  This product includes software developed by the University of
00016  *  California, Berkeley and its contributors.
00017  * 4. Neither the name of the University nor the names of its contributors
00018  *    may be used to endorse or promote products derived from this software
00019  *    without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00022  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00025  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00026  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00027  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00028  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  */
00033 
00034 #include <u/missing/mkstemps.h>
00035 
00036 #ifdef OS_WIN
00037 #include <windows.h>
00038 #define __mkdir(dir, perm) CreateDirectory(dir, NULL)
00039 #define lstat(path, buf) stat(path, buf)
00040 #else
00041 #define __mkdir(dir, perm) mkdir(dir, perm)
00042 #endif
00043 
00044 #ifndef HAVE_MKSTEMPS
00045 
00046 #include <sys/types.h>
00047 #include <sys/stat.h>
00048 #include <time.h>
00049 #include <limits.h>
00050 #include <fcntl.h>
00051 #include <errno.h>
00052 #include <stdio.h>
00053 #include <stdlib.h>
00054 #include <string.h>
00055 #include <ctype.h>
00056 #include <unistd.h>
00057 
00058 static int _gettemp(char *, int *, int, int);
00059 static unsigned int __time_seed (void);
00060 
00061 static const unsigned char padchar[] =
00062     "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
00063 
00064 int mkstemps(char *path, int slen)
00065 {
00066     int fd;
00067 
00068     return (_gettemp(path, &fd, 0, slen) ? fd : -1);
00069 }
00070 
00071 static int _gettemp(char *path, int *doopen, int domkdir, int slen)
00072 {
00073     char *start, *trv, *suffp;
00074     char *pad;
00075     struct stat sbuf;
00076     int rval;
00077     int __rand;
00078 
00079     srand(__time_seed());
00080 
00081     if (doopen != NULL && domkdir) {
00082         errno = EINVAL;
00083         return (0);
00084     }
00085 
00086     for (trv = path; *trv != '\0'; ++trv)
00087         ;
00088     trv -= slen;
00089     suffp = trv;
00090     --trv;
00091     if (trv < path) {
00092         errno = EINVAL;
00093         return (0);
00094     }
00095 
00096     /* Fill space with random characters */
00097     while (trv >= path && *trv == 'X') {
00098         __rand = rand() % (sizeof(padchar) - 1);
00099         *trv-- = padchar[__rand];
00100     }
00101     start = trv + 1;
00102 
00103     /*
00104      * check the target directory.
00105      */
00106     if (doopen != NULL || domkdir) {
00107         for (; trv > path; --trv) {
00108             if (*trv == '/') {
00109                 *trv = '\0';
00110                 rval = stat(path, &sbuf);
00111                 *trv = '/';
00112                 if (rval != 0)
00113                     return (0);
00114                 if (!S_ISDIR(sbuf.st_mode)) {
00115                     errno = ENOTDIR;
00116                     return (0);
00117                 }
00118                 break;
00119             }
00120         }
00121     }
00122 
00123     for (;;) {
00124         if (doopen) {
00125             if ((*doopen = open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
00126                 return (1);
00127             if (errno != EEXIST)
00128                 return (0);
00129         } else if (domkdir) {
00130             if (__mkdir(path, 0700) == 0)
00131                 return (1);
00132             if (errno != EEXIST)
00133                 return (0);
00134         } else if (lstat(path, &sbuf))
00135             return (errno == ENOENT);
00136 
00137         /* If we have a collision, cycle through the space of filenames */
00138         for (trv = start;;) {
00139             if (*trv == '\0' || trv == suffp)
00140                 return (0);
00141             pad = strchr((const char *) padchar, *trv);
00142             if (pad == NULL || *++pad == '\0')
00143                 *trv++ = padchar[0];
00144             else {
00145                 *trv++ = *pad;
00146                 break;
00147             }
00148         }
00149     }
00150     /*NOTREACHED*/
00151 }
00152 
00153 static unsigned int __time_seed (void)
00154 {
00155     time_t now;
00156     unsigned char *p;
00157     unsigned seed = 0;
00158     size_t i;
00159 
00160     now = time(NULL);
00161     p = (unsigned char *) &now;
00162 
00163     for (i = 0; i < sizeof now; i++)
00164         seed = seed * (UCHAR_MAX + 2U) + p[i];
00165 
00166     return seed;
00167 }
00168 
00169 #else   /* HAVE_MKSTEMPS */
00170 int mkstemps (char *template, int suffixlen);
00171 #endif  /* !HAVE_MKSTEMPS */

←Products
© 2005-2012 - KoanLogic S.r.l. - All rights reserved