00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 #include <config.h>
00021 #endif
00022
00023 #ifndef HAVE_TEMPNAM
00024
00025 #include <errno.h>
00026 #include <stddef.h>
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030
00031 #ifdef HAVE_UNISTD_H
00032 #ifdef HAVE_SYS_TYPES_H
00033 #include <sys/types.h>
00034 #endif
00035 #include <unistd.h>
00036 #endif
00037
00038 #include <fcntl.h>
00039
00040 #include "statdefs.h"
00041
00042 #ifndef FILENAME_MAX
00043 #ifdef MAXPATHLEN
00044 #define FILENAME_MAX MAXPATHLEN
00045 #else
00046 #define FILENAME_MAX 1024
00047 #endif
00048 #endif
00049
00050 #ifndef P_tmpdir
00051 #define P_tmpdir "/usr/tmp/"
00052 #endif
00053
00054
00055 static int
00056 diraccess (const char *dir)
00057 {
00058 struct stat buf;
00059 return stat (dir, &buf) == 0 && S_ISDIR (buf.st_mode);
00060 }
00061
00062
00063 static int
00064 exists (const char *file)
00065 {
00066
00067 struct stat st;
00068 int save = errno;
00069 if (stat (file, &st) == 0)
00070 return 1;
00071 else
00072 {
00073
00074
00075
00076
00077
00078 int exists = errno != ENOENT;
00079 errno = save;
00080 return exists;
00081 }
00082 }
00083
00084
00085
00086 static const char letters[] =
00087 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 char *
00104 __stdio_gen_tempname (const char *dir, const char *pfx,
00105 int dir_search, size_t *lenptr,
00106 FILE **streamptr)
00107 {
00108 int saverrno = errno;
00109 static const char tmpdir[] = P_tmpdir;
00110 static size_t indices[2];
00111 size_t *idx;
00112 static char buf[FILENAME_MAX];
00113 static pid_t oldpid = (pid_t) 0;
00114 pid_t pid = getpid();
00115 register size_t len, plen, dlen;
00116
00117 if (dir_search)
00118 {
00119 register const char *d = getenv("TMPDIR");
00120 if (d != NULL && !diraccess(d))
00121 d = NULL;
00122 if (d == NULL && dir != NULL && diraccess(dir))
00123 d = dir;
00124 if (d == NULL && diraccess(tmpdir))
00125 d = tmpdir;
00126 if (d == NULL && diraccess("/tmp"))
00127 d = "/tmp";
00128 if (d == NULL)
00129 {
00130 errno = ENOENT;
00131 return NULL;
00132 }
00133 dir = d;
00134 }
00135 else
00136 dir = tmpdir;
00137
00138 dlen = strlen (dir);
00139
00140
00141 while (dlen > 1 && dir[dlen - 1] == '/')
00142 --dlen;
00143
00144 if (pfx != NULL && *pfx != '\0')
00145 {
00146 plen = strlen(pfx);
00147 if (plen > 5)
00148 plen = 5;
00149 }
00150 else
00151 plen = 0;
00152
00153 if (dir != tmpdir && !strcmp(dir, tmpdir))
00154 dir = tmpdir;
00155 idx = &indices[(plen == 0 && dir == tmpdir) ? 1 : 0];
00156
00157 if (pid != oldpid)
00158 {
00159 oldpid = pid;
00160 indices[0] = indices[1] = 0;
00161 }
00162
00163 len = dlen + 1 + plen + 5 + 3;
00164 for (; *idx < ((sizeof (letters) - 1) * (sizeof (letters) - 1) *
00165 (sizeof (letters) - 1));
00166 ++*idx)
00167 {
00168
00169
00170
00171
00172
00173 if (sizeof (buf) < len)
00174 return NULL;
00175
00176 sprintf (buf, "%.*s/%.*s%.5d%c%c%c",
00177 (int) dlen, dir, (int) plen,
00178 pfx, pid % 100000,
00179 letters[*idx
00180 % (sizeof (letters) - 1)],
00181 letters[(*idx / (sizeof (letters) - 1))
00182 % (sizeof (letters) - 1)],
00183 letters[(*idx / ((sizeof (letters) - 1) *
00184 (sizeof (letters) - 1)))
00185 % (sizeof (letters) - 1)]
00186 );
00187
00188 if (! buf || strlen (buf) != (int) len)
00189 return NULL;
00190
00191 if (streamptr != NULL)
00192 abort ();
00193 else if (exists (buf))
00194 continue;
00195
00196
00197
00198
00199 errno = saverrno;
00200
00201 if (lenptr != NULL)
00202 *lenptr = len + 1;
00203 return buf;
00204 }
00205
00206
00207 errno = EEXIST;
00208 return NULL;
00209 }
00210
00211 #endif