mkstemps.c
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
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
00097 while (trv >= path && *trv == 'X') {
00098 __rand = rand() % (sizeof(padchar) - 1);
00099 *trv-- = padchar[__rand];
00100 }
00101 start = trv + 1;
00102
00103
00104
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
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
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
00170 int mkstemps (char *template, int suffixlen);
00171 #endif