aboutsummaryrefslogtreecommitdiffstats
path: root/lib/tempname.c
diff options
context:
space:
mode:
authorPaul Eggert2015-02-20 23:31:17 -0800
committerPaul Eggert2015-02-20 23:32:45 -0800
commit066b17df681fabb40108d719086669957aebbc51 (patch)
tree27f9362ed6a6e68ef6b61925932f84bb1afb37b8 /lib/tempname.c
parent43fb42da8bd6851b5b22d2bbb5d2cd8ceede9c09 (diff)
downloademacs-066b17df681fabb40108d719086669957aebbc51.tar.gz
emacs-066b17df681fabb40108d719086669957aebbc51.zip
Merge from gnulib
* doc/misc/texinfo.tex: Update from gnulib. * lib/getdtablesize.c, lib/getopt.c, lib/signal.in.h, lib/tempname.c: * lib/tempname.h, m4/dup2.m4, m4/fcntl.m4, m4/getdtablesize.m4: Update from gnulib, incorporating: 2015-02-20 getdtablesize: port better for Android 2015-02-19 fcntl: Fix cross compiling 2015-02-18 dup2, fcntl: cross-compile better for Android 2015-02-18 getopt: don't crash on memory exhaustion 2015-02-17 tempname: allow compilation with C++ (trivial) 2015-02-17 dup2, fcntl: port to AIX 2015-02-16 getdtablesize, dup2, fcntl: port to Android 2015-02-11 getdtablesize, signal_h: Fix Android build 2015-02-11 maint: various whitespace cleanups in tempname
Diffstat (limited to 'lib/tempname.c')
-rw-r--r--lib/tempname.c118
1 files changed, 68 insertions, 50 deletions
diff --git a/lib/tempname.c b/lib/tempname.c
index 088b224ab96..8e6d26cc485 100644
--- a/lib/tempname.c
+++ b/lib/tempname.c
@@ -62,6 +62,7 @@
62# define struct_stat64 struct stat64 62# define struct_stat64 struct stat64
63#else 63#else
64# define struct_stat64 struct stat 64# define struct_stat64 struct stat
65# define __try_tempname try_tempname
65# define __gen_tempname gen_tempname 66# define __gen_tempname gen_tempname
66# define __getpid getpid 67# define __getpid getpid
67# define __gettimeofday gettimeofday 68# define __gettimeofday gettimeofday
@@ -176,21 +177,9 @@ __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx,
176static const char letters[] = 177static const char letters[] =
177"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 178"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
178 179
179/* Generate a temporary file name based on TMPL. TMPL must match the
180 rules for mk[s]temp (i.e. end in "XXXXXX", possibly with a suffix).
181 The name constructed does not exist at the time of the call to
182 __gen_tempname. TMPL is overwritten with the result.
183
184 KIND may be one of:
185 __GT_NOCREATE: simply verify that the name does not exist
186 at the time of the call.
187 __GT_FILE: create the file using open(O_CREAT|O_EXCL)
188 and return a read-write fd. The file is mode 0600.
189 __GT_DIR: create a directory, which will be mode 0700.
190
191 We use a clever algorithm to get hard-to-predict names. */
192int 180int
193__gen_tempname (char *tmpl, int suffixlen, int flags, int kind) 181__try_tempname (char *tmpl, int suffixlen, void *args,
182 int (*tryfunc) (char *, void *))
194{ 183{
195 int len; 184 int len;
196 char *XXXXXX; 185 char *XXXXXX;
@@ -199,7 +188,6 @@ __gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
199 unsigned int count; 188 unsigned int count;
200 int fd = -1; 189 int fd = -1;
201 int save_errno = errno; 190 int save_errno = errno;
202 struct_stat64 st;
203 191
204 /* A lower bound on the number of temporary files to attempt to 192 /* A lower bound on the number of temporary files to attempt to
205 generate. The maximum total number of temporary file names that 193 generate. The maximum total number of temporary file names that
@@ -256,41 +244,7 @@ __gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
256 v /= 62; 244 v /= 62;
257 XXXXXX[5] = letters[v % 62]; 245 XXXXXX[5] = letters[v % 62];
258 246
259 switch (kind) 247 fd = tryfunc (tmpl, args);
260 {
261 case __GT_FILE:
262 fd = __open (tmpl,
263 (flags & ~O_ACCMODE)
264 | O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
265 break;
266
267 case __GT_DIR:
268 fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
269 break;
270
271 case __GT_NOCREATE:
272 /* This case is backward from the other three. __gen_tempname
273 succeeds if __xstat fails because the name does not exist.
274 Note the continue to bypass the common logic at the bottom
275 of the loop. */
276 if (__lxstat64 (_STAT_VER, tmpl, &st) < 0)
277 {
278 if (errno == ENOENT)
279 {
280 __set_errno (save_errno);
281 return 0;
282 }
283 else
284 /* Give up now. */
285 return -1;
286 }
287 continue;
288
289 default:
290 assert (! "invalid KIND in __gen_tempname");
291 abort ();
292 }
293
294 if (fd >= 0) 248 if (fd >= 0)
295 { 249 {
296 __set_errno (save_errno); 250 __set_errno (save_errno);
@@ -304,3 +258,67 @@ __gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
304 __set_errno (EEXIST); 258 __set_errno (EEXIST);
305 return -1; 259 return -1;
306} 260}
261
262static int
263try_file (char *tmpl, void *flags)
264{
265 int *openflags = flags;
266 return __open (tmpl,
267 (*openflags & ~O_ACCMODE)
268 | O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
269}
270
271static int
272try_dir (char *tmpl, void *flags)
273{
274 return __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
275}
276
277static int
278try_nocreate (char *tmpl, void *flags)
279{
280 struct_stat64 st;
281
282 if (__lxstat64 (_STAT_VER, tmpl, &st) == 0)
283 __set_errno (EEXIST);
284 return errno == ENOENT ? 0 : -1;
285}
286
287/* Generate a temporary file name based on TMPL. TMPL must match the
288 rules for mk[s]temp (i.e. end in "XXXXXX", possibly with a suffix).
289 The name constructed does not exist at the time of the call to
290 __gen_tempname. TMPL is overwritten with the result.
291
292 KIND may be one of:
293 __GT_NOCREATE: simply verify that the name does not exist
294 at the time of the call.
295 __GT_FILE: create the file using open(O_CREAT|O_EXCL)
296 and return a read-write fd. The file is mode 0600.
297 __GT_DIR: create a directory, which will be mode 0700.
298
299 We use a clever algorithm to get hard-to-predict names. */
300int
301__gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
302{
303 int (*tryfunc) (char *, void *);
304
305 switch (kind)
306 {
307 case __GT_FILE:
308 tryfunc = try_file;
309 break;
310
311 case __GT_DIR:
312 tryfunc = try_dir;
313 break;
314
315 case __GT_NOCREATE:
316 tryfunc = try_nocreate;
317 break;
318
319 default:
320 assert (! "invalid KIND in __gen_tempname");
321 abort ();
322 }
323 return __try_tempname (tmpl, suffixlen, &flags, tryfunc);
324}