diff options
| author | Paul Eggert | 2015-02-20 23:31:17 -0800 |
|---|---|---|
| committer | Paul Eggert | 2015-02-20 23:32:45 -0800 |
| commit | 066b17df681fabb40108d719086669957aebbc51 (patch) | |
| tree | 27f9362ed6a6e68ef6b61925932f84bb1afb37b8 /lib/tempname.c | |
| parent | 43fb42da8bd6851b5b22d2bbb5d2cd8ceede9c09 (diff) | |
| download | emacs-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.c | 118 |
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, | |||
| 176 | static const char letters[] = | 177 | static 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. */ | ||
| 192 | int | 180 | int |
| 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 | |||
| 262 | static int | ||
| 263 | try_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 | |||
| 271 | static int | ||
| 272 | try_dir (char *tmpl, void *flags) | ||
| 273 | { | ||
| 274 | return __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); | ||
| 275 | } | ||
| 276 | |||
| 277 | static int | ||
| 278 | try_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. */ | ||
| 300 | int | ||
| 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 | } | ||