diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/dirent.in.h | 2 | ||||
| -rw-r--r-- | lib/dirfd.c | 32 | ||||
| -rw-r--r-- | lib/fdopendir.c | 13 | ||||
| -rw-r--r-- | lib/getdtablesize.c | 42 | ||||
| -rw-r--r-- | lib/getopt.c | 52 | ||||
| -rw-r--r-- | lib/gnulib.mk | 11 | ||||
| -rw-r--r-- | lib/signal.in.h | 8 | ||||
| -rw-r--r-- | lib/tempname.c | 118 | ||||
| -rw-r--r-- | lib/tempname.h | 15 |
9 files changed, 209 insertions, 84 deletions
diff --git a/lib/dirent.in.h b/lib/dirent.in.h index ddd3b84fbb2..154d2689e3d 100644 --- a/lib/dirent.in.h +++ b/lib/dirent.in.h | |||
| @@ -77,6 +77,7 @@ typedef struct gl_directory DIR; | |||
| 77 | # if !(defined __cplusplus && defined GNULIB_NAMESPACE) | 77 | # if !(defined __cplusplus && defined GNULIB_NAMESPACE) |
| 78 | # undef opendir | 78 | # undef opendir |
| 79 | # define opendir rpl_opendir | 79 | # define opendir rpl_opendir |
| 80 | # define GNULIB_defined_opendir 1 | ||
| 80 | # endif | 81 | # endif |
| 81 | _GL_FUNCDECL_RPL (opendir, DIR *, (const char *dir_name) _GL_ARG_NONNULL ((1))); | 82 | _GL_FUNCDECL_RPL (opendir, DIR *, (const char *dir_name) _GL_ARG_NONNULL ((1))); |
| 82 | _GL_CXXALIAS_RPL (opendir, DIR *, (const char *dir_name)); | 83 | _GL_CXXALIAS_RPL (opendir, DIR *, (const char *dir_name)); |
| @@ -128,6 +129,7 @@ _GL_WARN_ON_USE (rewinddir, "rewinddir is not portable - " | |||
| 128 | # if !(defined __cplusplus && defined GNULIB_NAMESPACE) | 129 | # if !(defined __cplusplus && defined GNULIB_NAMESPACE) |
| 129 | # undef closedir | 130 | # undef closedir |
| 130 | # define closedir rpl_closedir | 131 | # define closedir rpl_closedir |
| 132 | # define GNULIB_defined_closedir 1 | ||
| 131 | # endif | 133 | # endif |
| 132 | _GL_FUNCDECL_RPL (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1))); | 134 | _GL_FUNCDECL_RPL (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1))); |
| 133 | _GL_CXXALIAS_RPL (closedir, int, (DIR *dirp)); | 135 | _GL_CXXALIAS_RPL (closedir, int, (DIR *dirp)); |
diff --git a/lib/dirfd.c b/lib/dirfd.c new file mode 100644 index 00000000000..c91f8e55872 --- /dev/null +++ b/lib/dirfd.c | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | /* dirfd.c -- return the file descriptor associated with an open DIR* | ||
| 2 | |||
| 3 | Copyright (C) 2001, 2006, 2008-2015 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This program is free software: you can redistribute it and/or modify | ||
| 6 | it under the terms of the GNU General Public License as published by | ||
| 7 | the Free Software Foundation; either version 3 of the License, or | ||
| 8 | (at your option) any later version. | ||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License | ||
| 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | ||
| 17 | |||
| 18 | /* Written by Jim Meyering. */ | ||
| 19 | |||
| 20 | #include <config.h> | ||
| 21 | |||
| 22 | #include <dirent.h> | ||
| 23 | #include <errno.h> | ||
| 24 | |||
| 25 | int | ||
| 26 | dirfd (DIR *dir_p) | ||
| 27 | { | ||
| 28 | int fd = DIR_TO_FD (dir_p); | ||
| 29 | if (fd == -1) | ||
| 30 | errno = ENOTSUP; | ||
| 31 | return fd; | ||
| 32 | } | ||
diff --git a/lib/fdopendir.c b/lib/fdopendir.c index 9dc1e7b26dc..837a8219b33 100644 --- a/lib/fdopendir.c +++ b/lib/fdopendir.c | |||
| @@ -93,7 +93,7 @@ fdopendir (int fd) | |||
| 93 | That way, barring race conditions, fd_clone_opendir returns a | 93 | That way, barring race conditions, fd_clone_opendir returns a |
| 94 | stream whose file descriptor is FD. | 94 | stream whose file descriptor is FD. |
| 95 | 95 | ||
| 96 | If REPLACE_CHDIR or CWD is null, use opendir ("/proc/self/fd/...", | 96 | If REPLACE_FCHDIR or CWD is null, use opendir ("/proc/self/fd/...", |
| 97 | falling back on fchdir metadata. Otherwise, CWD is a saved version | 97 | falling back on fchdir metadata. Otherwise, CWD is a saved version |
| 98 | of the working directory; use fchdir/opendir(".")/restore_cwd(CWD). */ | 98 | of the working directory; use fchdir/opendir(".")/restore_cwd(CWD). */ |
| 99 | static DIR * | 99 | static DIR * |
| @@ -156,7 +156,16 @@ fd_clone_opendir (int fd, struct saved_cwd const *cwd) | |||
| 156 | if (! dir && EXPECTED_ERRNO (saved_errno)) | 156 | if (! dir && EXPECTED_ERRNO (saved_errno)) |
| 157 | { | 157 | { |
| 158 | char const *name = _gl_directory_name (fd); | 158 | char const *name = _gl_directory_name (fd); |
| 159 | return (name ? opendir (name) : NULL); | 159 | DIR *dp = name ? opendir (name) : NULL; |
| 160 | |||
| 161 | /* The caller has done an elaborate dance to arrange for opendir to | ||
| 162 | consume just the right file descriptor. If dirfd returns -1, | ||
| 163 | though, we're on a system like mingw where opendir does not | ||
| 164 | consume a file descriptor. Consume it via 'dup' instead. */ | ||
| 165 | if (dp && dirfd (dp) < 0) | ||
| 166 | dup (fd); | ||
| 167 | |||
| 168 | return dp; | ||
| 160 | } | 169 | } |
| 161 | # endif | 170 | # endif |
| 162 | errno = saved_errno; | 171 | errno = saved_errno; |
diff --git a/lib/getdtablesize.c b/lib/getdtablesize.c index 59b97360bc5..03eb7ef1bff 100644 --- a/lib/getdtablesize.c +++ b/lib/getdtablesize.c | |||
| @@ -84,32 +84,38 @@ getdtablesize (void) | |||
| 84 | return dtablesize; | 84 | return dtablesize; |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | #elif HAVE_GETDTABLESIZE | 87 | #else |
| 88 | 88 | ||
| 89 | # include <limits.h> | ||
| 89 | # include <sys/resource.h> | 90 | # include <sys/resource.h> |
| 90 | # undef getdtablesize | ||
| 91 | 91 | ||
| 92 | int | 92 | # ifndef RLIM_SAVED_CUR |
| 93 | rpl_getdtablesize(void) | 93 | # define RLIM_SAVED_CUR RLIM_INFINITY |
| 94 | { | 94 | # endif |
| 95 | /* To date, this replacement is only compiled for Cygwin 1.7.25, | 95 | # ifndef RLIM_SAVED_MAX |
| 96 | which auto-increased the RLIMIT_NOFILE soft limit until it | 96 | # define RLIM_SAVED_MAX RLIM_INFINITY |
| 97 | hits the compile-time constant hard limit of 3200. Although | 97 | # endif |
| 98 | that version of cygwin supported a child process inheriting | ||
| 99 | a smaller soft limit, the smaller limit is not enforced, so | ||
| 100 | we might as well just report the hard limit. */ | ||
| 101 | struct rlimit lim; | ||
| 102 | if (!getrlimit (RLIMIT_NOFILE, &lim) && lim.rlim_max != RLIM_INFINITY) | ||
| 103 | return lim.rlim_max; | ||
| 104 | return getdtablesize (); | ||
| 105 | } | ||
| 106 | 98 | ||
| 107 | #elif defined _SC_OPEN_MAX | 99 | # ifdef __CYGWIN__ |
| 100 | /* Cygwin 1.7.25 auto-increases the RLIMIT_NOFILE soft limit until it | ||
| 101 | hits the compile-time constant hard limit of 3200. We might as | ||
| 102 | well just report the hard limit. */ | ||
| 103 | # define rlim_cur rlim_max | ||
| 104 | # endif | ||
| 108 | 105 | ||
| 109 | int | 106 | int |
| 110 | getdtablesize (void) | 107 | getdtablesize (void) |
| 111 | { | 108 | { |
| 112 | return sysconf (_SC_OPEN_MAX); | 109 | struct rlimit lim; |
| 110 | |||
| 111 | if (getrlimit (RLIMIT_NOFILE, &lim) == 0 | ||
| 112 | && 0 <= lim.rlim_cur && lim.rlim_cur <= INT_MAX | ||
| 113 | && lim.rlim_cur != RLIM_INFINITY | ||
| 114 | && lim.rlim_cur != RLIM_SAVED_CUR | ||
| 115 | && lim.rlim_cur != RLIM_SAVED_MAX) | ||
| 116 | return lim.rlim_cur; | ||
| 117 | |||
| 118 | return INT_MAX; | ||
| 113 | } | 119 | } |
| 114 | 120 | ||
| 115 | #endif | 121 | #endif |
diff --git a/lib/getopt.c b/lib/getopt.c index 3b9c585a28c..212cbf73410 100644 --- a/lib/getopt.c +++ b/lib/getopt.c | |||
| @@ -487,7 +487,20 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, | |||
| 487 | const struct option *p; | 487 | const struct option *p; |
| 488 | struct option_list *next; | 488 | struct option_list *next; |
| 489 | } *ambig_list = NULL; | 489 | } *ambig_list = NULL; |
| 490 | #ifdef _LIBC | ||
| 491 | /* malloc() not used for _LIBC to simplify failure messages. */ | ||
| 492 | # define free_option_list(l) | ||
| 493 | #else | ||
| 494 | # define free_option_list(l) \ | ||
| 495 | while (l != NULL) \ | ||
| 496 | { \ | ||
| 497 | struct option_list *pn = l->next; \ | ||
| 498 | free (l); \ | ||
| 499 | l = pn; \ | ||
| 500 | } | ||
| 501 | #endif | ||
| 490 | int exact = 0; | 502 | int exact = 0; |
| 503 | int ambig = 0; | ||
| 491 | int indfound = -1; | 504 | int indfound = -1; |
| 492 | int option_index; | 505 | int option_index; |
| 493 | 506 | ||
| @@ -514,22 +527,37 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, | |||
| 514 | pfound = p; | 527 | pfound = p; |
| 515 | indfound = option_index; | 528 | indfound = option_index; |
| 516 | } | 529 | } |
| 530 | else if (ambig) | ||
| 531 | ; /* Taking simpler path to handling ambiguities. */ | ||
| 517 | else if (long_only | 532 | else if (long_only |
| 518 | || pfound->has_arg != p->has_arg | 533 | || pfound->has_arg != p->has_arg |
| 519 | || pfound->flag != p->flag | 534 | || pfound->flag != p->flag |
| 520 | || pfound->val != p->val) | 535 | || pfound->val != p->val) |
| 521 | { | 536 | { |
| 522 | /* Second or later nonexact match found. */ | 537 | /* Second or later nonexact match found. */ |
| 538 | #ifdef _LIBC | ||
| 539 | struct option_list *newp = alloca (sizeof (*newp)); | ||
| 540 | #else | ||
| 523 | struct option_list *newp = malloc (sizeof (*newp)); | 541 | struct option_list *newp = malloc (sizeof (*newp)); |
| 524 | newp->p = p; | 542 | if (newp == NULL) |
| 525 | newp->next = ambig_list; | 543 | { |
| 526 | ambig_list = newp; | 544 | free_option_list (ambig_list); |
| 545 | ambig_list = NULL; | ||
| 546 | ambig = 1; /* Use simpler fallback message. */ | ||
| 547 | } | ||
| 548 | else | ||
| 549 | #endif | ||
| 550 | { | ||
| 551 | newp->p = p; | ||
| 552 | newp->next = ambig_list; | ||
| 553 | ambig_list = newp; | ||
| 554 | } | ||
| 527 | } | 555 | } |
| 528 | } | 556 | } |
| 529 | 557 | ||
| 530 | if (ambig_list != NULL && !exact) | 558 | if ((ambig || ambig_list) && !exact) |
| 531 | { | 559 | { |
| 532 | if (print_errors) | 560 | if (print_errors && ambig_list) |
| 533 | { | 561 | { |
| 534 | struct option_list first; | 562 | struct option_list first; |
| 535 | first.p = pfound; | 563 | first.p = pfound; |
| @@ -585,18 +613,20 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, | |||
| 585 | fputc ('\n', stderr); | 613 | fputc ('\n', stderr); |
| 586 | #endif | 614 | #endif |
| 587 | } | 615 | } |
| 616 | else if (print_errors && ambig) | ||
| 617 | { | ||
| 618 | fprintf (stderr, | ||
| 619 | _("%s: option '%s' is ambiguous\n"), | ||
| 620 | argv[0], argv[d->optind]); | ||
| 621 | } | ||
| 588 | d->__nextchar += strlen (d->__nextchar); | 622 | d->__nextchar += strlen (d->__nextchar); |
| 589 | d->optind++; | 623 | d->optind++; |
| 590 | d->optopt = 0; | 624 | d->optopt = 0; |
| 625 | free_option_list (ambig_list); | ||
| 591 | return '?'; | 626 | return '?'; |
| 592 | } | 627 | } |
| 593 | 628 | ||
| 594 | while (ambig_list != NULL) | 629 | free_option_list (ambig_list); |
| 595 | { | ||
| 596 | struct option_list *pn = ambig_list->next; | ||
| 597 | free (ambig_list); | ||
| 598 | ambig_list = pn; | ||
| 599 | } | ||
| 600 | 630 | ||
| 601 | if (pfound != NULL) | 631 | if (pfound != NULL) |
| 602 | { | 632 | { |
diff --git a/lib/gnulib.mk b/lib/gnulib.mk index 1b671e7f6de..7703cbfe283 100644 --- a/lib/gnulib.mk +++ b/lib/gnulib.mk | |||
| @@ -237,6 +237,17 @@ EXTRA_DIST += dirent.in.h | |||
| 237 | 237 | ||
| 238 | ## end gnulib module dirent | 238 | ## end gnulib module dirent |
| 239 | 239 | ||
| 240 | ## begin gnulib module dirfd | ||
| 241 | |||
| 242 | if gl_GNULIB_ENABLED_dirfd | ||
| 243 | |||
| 244 | endif | ||
| 245 | EXTRA_DIST += dirfd.c | ||
| 246 | |||
| 247 | EXTRA_libgnu_a_SOURCES += dirfd.c | ||
| 248 | |||
| 249 | ## end gnulib module dirfd | ||
| 250 | |||
| 240 | ## begin gnulib module dosname | 251 | ## begin gnulib module dosname |
| 241 | 252 | ||
| 242 | if gl_GNULIB_ENABLED_dosname | 253 | if gl_GNULIB_ENABLED_dosname |
diff --git a/lib/signal.in.h b/lib/signal.in.h index 0f2ff5af843..265b72ab0ec 100644 --- a/lib/signal.in.h +++ b/lib/signal.in.h | |||
| @@ -55,11 +55,13 @@ | |||
| 55 | #ifndef _@GUARD_PREFIX@_SIGNAL_H | 55 | #ifndef _@GUARD_PREFIX@_SIGNAL_H |
| 56 | #define _@GUARD_PREFIX@_SIGNAL_H | 56 | #define _@GUARD_PREFIX@_SIGNAL_H |
| 57 | 57 | ||
| 58 | /* Mac OS X 10.3, FreeBSD 6.4, OpenBSD 3.8, OSF/1 4.0, Solaris 2.6 declare | 58 | /* Mac OS X 10.3, FreeBSD 6.4, OpenBSD 3.8, OSF/1 4.0, Solaris 2.6, Android |
| 59 | pthread_sigmask in <pthread.h>, not in <signal.h>. | 59 | declare pthread_sigmask in <pthread.h>, not in <signal.h>. |
| 60 | But avoid namespace pollution on glibc systems.*/ | 60 | But avoid namespace pollution on glibc systems.*/ |
| 61 | #if (@GNULIB_PTHREAD_SIGMASK@ || defined GNULIB_POSIXCHECK) \ | 61 | #if (@GNULIB_PTHREAD_SIGMASK@ || defined GNULIB_POSIXCHECK) \ |
| 62 | && ((defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || defined __OpenBSD__ || defined __osf__ || defined __sun) \ | 62 | && ((defined __APPLE__ && defined __MACH__) \ |
| 63 | || defined __FreeBSD__ || defined __OpenBSD__ || defined __osf__ \ | ||
| 64 | || defined __sun || defined __ANDROID__) \ | ||
| 63 | && ! defined __GLIBC__ | 65 | && ! defined __GLIBC__ |
| 64 | # include <pthread.h> | 66 | # include <pthread.h> |
| 65 | #endif | 67 | #endif |
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 | } | ||
diff --git a/lib/tempname.h b/lib/tempname.h index b560ee5cb14..e6093607463 100644 --- a/lib/tempname.h +++ b/lib/tempname.h | |||
| @@ -32,6 +32,10 @@ | |||
| 32 | # define GT_NOCREATE 2 | 32 | # define GT_NOCREATE 2 |
| 33 | # endif | 33 | # endif |
| 34 | 34 | ||
| 35 | #ifdef __cplusplus | ||
| 36 | extern "C" { | ||
| 37 | #endif | ||
| 38 | |||
| 35 | /* Generate a temporary file name based on TMPL. TMPL must match the | 39 | /* Generate a temporary file name based on TMPL. TMPL must match the |
| 36 | rules for mk[s]temp (i.e. end in "XXXXXX", possibly with a suffix). | 40 | rules for mk[s]temp (i.e. end in "XXXXXX", possibly with a suffix). |
| 37 | The name constructed does not exist at the time of the call to | 41 | The name constructed does not exist at the time of the call to |
| @@ -47,4 +51,15 @@ | |||
| 47 | We use a clever algorithm to get hard-to-predict names. */ | 51 | We use a clever algorithm to get hard-to-predict names. */ |
| 48 | extern int gen_tempname (char *tmpl, int suffixlen, int flags, int kind); | 52 | extern int gen_tempname (char *tmpl, int suffixlen, int flags, int kind); |
| 49 | 53 | ||
| 54 | /* Similar to gen_tempname, but TRYFUNC is called for each temporary | ||
| 55 | name to try. If TRYFUNC returns a non-negative number, TRY_GEN_TEMPNAME | ||
| 56 | returns with this value. Otherwise, if errno is set to EEXIST, another | ||
| 57 | name is tried, or else TRY_GEN_TEMPNAME returns -1. */ | ||
| 58 | extern int try_tempname (char *tmpl, int suffixlen, void *args, | ||
| 59 | int (*tryfunc) (char *, void *)); | ||
| 60 | |||
| 61 | #ifdef __cplusplus | ||
| 62 | } | ||
| 63 | #endif | ||
| 64 | |||
| 50 | #endif /* GL_TEMPNAME_H */ | 65 | #endif /* GL_TEMPNAME_H */ |