Main Page | Modules | Data Structures | File List | Data Fields

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/libu.h>
00035 #include <sys/types.h>
00036 #include <sys/stat.h>
00037 #include <limits.h>
00038 #include <fcntl.h>
00039 #include <errno.h>
00040 #include <stdio.h>
00041 #include <stdlib.h>
00042 #include <string.h>
00043 #include <ctype.h>
00044 #include <unistd.h>
00045 
00046 #ifndef HAVE_MKSTEMPS
00047 
00048 static int _gettemp(char *, int *, int, int);
00049 static unsigned int __time_seed (void);
00050 
00051 static const unsigned char padchar[] =
00052     "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
00053 
00054 int
00055 mkstemps(path, slen)
00056     char *path;
00057     int slen;
00058 {
00059     int fd;
00060 
00061     return (_gettemp(path, &fd, 0, slen) ? fd : -1);
00062 }
00063 
00064 static int
00065 _gettemp(path, doopen, domkdir, slen)
00066     char *path;
00067     int *doopen;
00068     int domkdir;
00069     int slen;
00070 {
00071     char *start, *trv, *suffp;
00072     char *pad;
00073     struct stat sbuf;
00074     int rval;
00075     int __rand;
00076 
00077     srand(__time_seed());
00078 
00079     if (doopen != NULL && domkdir) {
00080         errno = EINVAL;
00081         return (0);
00082     }
00083 
00084     for (trv = path; *trv != '\0'; ++trv)
00085         ;
00086     trv -= slen;
00087     suffp = trv;
00088     --trv;
00089     if (trv < path) {
00090         errno = EINVAL;
00091         return (0);
00092     }
00093 
00094     /* Fill space with random characters */
00095     while (trv >= path && *trv == 'X') {
00096         __rand = rand() % (sizeof(padchar) - 1);
00097         *trv-- = padchar[__rand];
00098     }
00099     start = trv + 1;
00100 
00101     /*
00102      * check the target directory.
00103      */
00104     if (doopen != NULL || domkdir) {
00105         for (; trv > path; --trv) {
00106             if (*trv == '/') {
00107                 *trv = '\0';
00108                 rval = stat(path, &sbuf);
00109                 *trv = '/';
00110                 if (rval != 0)
00111                     return (0);
00112                 if (!S_ISDIR(sbuf.st_mode)) {
00113                     errno = ENOTDIR;
00114                     return (0);
00115                 }
00116                 break;
00117             }
00118         }
00119     }
00120 
00121     for (;;) {
00122         if (doopen) {
00123             if ((*doopen =
00124                 open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
00125                 return (1);
00126             if (errno != EEXIST)
00127                 return (0);
00128         } else if (domkdir) {
00129             if (mkdir(path, 0700) == 0)
00130                 return (1);
00131             if (errno != EEXIST)
00132                 return (0);
00133         } else if (lstat(path, &sbuf))
00134             return (errno == ENOENT);
00135 
00136         /* If we have a collision, cycle through the space of filenames */
00137         for (trv = start;;) {
00138             if (*trv == '\0' || trv == suffp)
00139                 return (0);
00140             pad = strchr((const char *) padchar, *trv);
00141             if (pad == NULL || *++pad == '\0')
00142                 *trv++ = padchar[0];
00143             else {
00144                 *trv++ = *pad;
00145                 break;
00146             }
00147         }
00148     }
00149     /*NOTREACHED*/
00150 }
00151 
00152 static unsigned int __time_seed (void)
00153 {
00154     time_t now;
00155     unsigned char *p;
00156     unsigned seed = 0;
00157     size_t i;
00158 
00159     now = time(NULL);
00160     p = (unsigned char *) &now;
00161 
00162     for (i = 0; i < sizeof now; i++)
00163         seed = seed * (UCHAR_MAX + 2U) + p[i];
00164 
00165     return seed;
00166 }
00167 
00168 #else
00169 int mkstemps (char *template, int suffixlen);
00170 #endif  /* !HAVE_MKSTEMPS */

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