diff options
| author | Paul Eggert | 2013-08-04 09:56:56 -0700 |
|---|---|---|
| committer | Paul Eggert | 2013-08-04 09:56:56 -0700 |
| commit | e0fdb6943066032db294720915c3bd644bf2bcd1 (patch) | |
| tree | 0aa420b81dc0187e2efec3ff4fe3cf046ad1c598 | |
| parent | 484ab23924d39b3e26d54074fd659633e1660ef4 (diff) | |
| download | emacs-e0fdb6943066032db294720915c3bd644bf2bcd1.tar.gz emacs-e0fdb6943066032db294720915c3bd644bf2bcd1.zip | |
Fix some minor races in hosts lacking mkostemp.
Gnulib's emulation of mkostemp doesn't have races that Emacs's does.
* configure.ac (mkostemp): Remove check for this function;
gnulib does the check now.
(mkstemp): Remove check for this no-longer-used function.
* lib/mkostemp.c, lib/secure_getenv.c, lib/tempname.c, lib/tempname.h:
* m4/mkostemp.m4, m4/secure_getenv.m4, m4/tempname.m4:
New files, copied from Gnulib.
* lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
* admin/merge-gnulib (GNULIB_MODULES): Add mkostemp.
* lib-src/movemail.c (main):
* lib-src/update-game-score.c (write_scores):
Use mkostemp (which now works on all platforms, due to changes
in the portability layer) rather than mktemp (which has a race)
or mkstemp (which we no longer bother with).
* src/callproc.c (create_temp_file):
* src/filelock.c (create_lock_file):
Assume mkostemp, since it's now provided by Gnulib.
Fixes: debbugs:15015
| -rw-r--r-- | ChangeLog | 12 | ||||
| -rw-r--r-- | admin/ChangeLog | 5 | ||||
| -rwxr-xr-x | admin/merge-gnulib | 2 | ||||
| -rw-r--r-- | configure.ac | 2 | ||||
| -rw-r--r-- | lib-src/ChangeLog | 9 | ||||
| -rw-r--r-- | lib-src/movemail.c | 17 | ||||
| -rw-r--r-- | lib-src/update-game-score.c | 12 | ||||
| -rw-r--r-- | lib/gnulib.mk | 32 | ||||
| -rw-r--r-- | lib/mkostemp.c | 46 | ||||
| -rw-r--r-- | lib/secure_getenv.c | 41 | ||||
| -rw-r--r-- | lib/tempname.c | 306 | ||||
| -rw-r--r-- | lib/tempname.h | 50 | ||||
| -rw-r--r-- | m4/gnulib-comp.m4 | 44 | ||||
| -rw-r--r-- | m4/mkostemp.m4 | 23 | ||||
| -rw-r--r-- | m4/secure_getenv.m4 | 25 | ||||
| -rw-r--r-- | m4/tempname.m4 | 19 | ||||
| -rw-r--r-- | src/ChangeLog | 7 | ||||
| -rw-r--r-- | src/callproc.c | 14 | ||||
| -rw-r--r-- | src/filelock.c | 18 |
19 files changed, 632 insertions, 52 deletions
| @@ -1,3 +1,15 @@ | |||
| 1 | 2013-08-04 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Fix some minor races in hosts lacking mkostemp (Bug#15015). | ||
| 4 | Gnulib's emulation of mkostemp doesn't have races that Emacs's does. | ||
| 5 | * configure.ac (mkostemp): Remove check for this function; | ||
| 6 | gnulib does the check now. | ||
| 7 | (mkstemp): Remove check for this no-longer-used function. | ||
| 8 | * lib/mkostemp.c, lib/secure_getenv.c, lib/tempname.c, lib/tempname.h: | ||
| 9 | * m4/mkostemp.m4, m4/secure_getenv.m4, m4/tempname.m4: | ||
| 10 | New files, copied from Gnulib. | ||
| 11 | * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate. | ||
| 12 | |||
| 1 | 2013-07-29 Michael Albinus <michael.albinus@gmx.de> | 13 | 2013-07-29 Michael Albinus <michael.albinus@gmx.de> |
| 2 | 14 | ||
| 3 | * INSTALL (DETAILED BUILDING AND INSTALLATION): Add | 15 | * INSTALL (DETAILED BUILDING AND INSTALLATION): Add |
diff --git a/admin/ChangeLog b/admin/ChangeLog index cbcd698e8b1..5373a9d20b6 100644 --- a/admin/ChangeLog +++ b/admin/ChangeLog | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | 2013-08-04 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Fix some minor races in hosts lacking mkostemp (Bug#15015). | ||
| 4 | * merge-gnulib (GNULIB_MODULES): Add mkostemp. | ||
| 5 | |||
| 1 | 2013-07-12 Glenn Morris <rgm@gnu.org> | 6 | 2013-07-12 Glenn Morris <rgm@gnu.org> |
| 2 | 7 | ||
| 3 | * admin.el (manual-style-string): Use non-abbreviated url. | 8 | * admin.el (manual-style-string): Use non-abbreviated url. |
diff --git a/admin/merge-gnulib b/admin/merge-gnulib index 82e0cd77fca..97126704d10 100755 --- a/admin/merge-gnulib +++ b/admin/merge-gnulib | |||
| @@ -32,7 +32,7 @@ GNULIB_MODULES=' | |||
| 32 | fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync | 32 | fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync |
| 33 | getloadavg getopt-gnu gettime gettimeofday | 33 | getloadavg getopt-gnu gettime gettimeofday |
| 34 | intprops largefile lstat | 34 | intprops largefile lstat |
| 35 | manywarnings memrchr mktime | 35 | manywarnings memrchr mkostemp mktime |
| 36 | pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat | 36 | pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat |
| 37 | sig2str socklen stat-time stdalign stdarg stdbool stdio | 37 | sig2str socklen stat-time stdalign stdarg stdbool stdio |
| 38 | strftime strtoimax strtoumax symlink sys_stat | 38 | strftime strtoimax strtoumax symlink sys_stat |
diff --git a/configure.ac b/configure.ac index d8557f29898..89aba556bb3 100644 --- a/configure.ac +++ b/configure.ac | |||
| @@ -3277,7 +3277,7 @@ select getpagesize setlocale \ | |||
| 3277 | getrlimit setrlimit shutdown getaddrinfo \ | 3277 | getrlimit setrlimit shutdown getaddrinfo \ |
| 3278 | strsignal setitimer \ | 3278 | strsignal setitimer \ |
| 3279 | sendto recvfrom getsockname getpeername getifaddrs freeifaddrs \ | 3279 | sendto recvfrom getsockname getpeername getifaddrs freeifaddrs \ |
| 3280 | gai_strerror mkostemp mkstemp getline getdelim sync \ | 3280 | gai_strerror getline getdelim sync \ |
| 3281 | difftime posix_memalign \ | 3281 | difftime posix_memalign \ |
| 3282 | getpwent endpwent getgrent endgrent \ | 3282 | getpwent endpwent getgrent endgrent \ |
| 3283 | touchlock \ | 3283 | touchlock \ |
diff --git a/lib-src/ChangeLog b/lib-src/ChangeLog index f41c23df5d2..2cfe46f5352 100644 --- a/lib-src/ChangeLog +++ b/lib-src/ChangeLog | |||
| @@ -1,3 +1,12 @@ | |||
| 1 | 2013-08-04 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Fix some minor races in hosts lacking mkostemp (Bug#15015). | ||
| 4 | * movemail.c (main): | ||
| 5 | * update-game-score.c (write_scores): | ||
| 6 | Use mkostemp (which now works on all platforms, due to changes | ||
| 7 | in the portability layer) rather than mktemp (which has a race) | ||
| 8 | or mkstemp (which we no longer bother with). | ||
| 9 | |||
| 1 | 2013-07-10 Paul Eggert <eggert@cs.ucla.edu> | 10 | 2013-07-10 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 11 | ||
| 3 | Port to C89. | 12 | Port to C89. |
diff --git a/lib-src/movemail.c b/lib-src/movemail.c index 81ac8aa187c..9434782cb17 100644 --- a/lib-src/movemail.c +++ b/lib-src/movemail.c | |||
| @@ -304,24 +304,13 @@ main (int argc, char **argv) | |||
| 304 | 304 | ||
| 305 | memcpy (tempname, inname, inname_dirlen); | 305 | memcpy (tempname, inname, inname_dirlen); |
| 306 | strcpy (tempname + inname_dirlen, "EXXXXXX"); | 306 | strcpy (tempname + inname_dirlen, "EXXXXXX"); |
| 307 | #ifdef HAVE_MKSTEMP | 307 | desc = mkostemp (tempname, 0); |
| 308 | desc = mkstemp (tempname); | ||
| 309 | #else | ||
| 310 | mktemp (tempname); | ||
| 311 | if (!*tempname) | ||
| 312 | desc = -1; | ||
| 313 | else | ||
| 314 | { | ||
| 315 | unlink (tempname); | ||
| 316 | desc = open (tempname, O_WRONLY | O_CREAT | O_EXCL, 0600); | ||
| 317 | } | ||
| 318 | #endif | ||
| 319 | if (desc < 0) | 308 | if (desc < 0) |
| 320 | { | 309 | { |
| 321 | int mkstemp_errno = errno; | 310 | int mkostemp_errno = errno; |
| 322 | error ("error while creating what would become the lock file", | 311 | error ("error while creating what would become the lock file", |
| 323 | 0, 0); | 312 | 0, 0); |
| 324 | errno = mkstemp_errno; | 313 | errno = mkostemp_errno; |
| 325 | pfatal_with_name (tempname); | 314 | pfatal_with_name (tempname); |
| 326 | } | 315 | } |
| 327 | close (desc); | 316 | close (desc); |
diff --git a/lib-src/update-game-score.c b/lib-src/update-game-score.c index ec8b4317770..1699e305c8d 100644 --- a/lib-src/update-game-score.c +++ b/lib-src/update-game-score.c | |||
| @@ -383,6 +383,7 @@ sort_scores (struct score_entry *scores, int count, int reverse) | |||
| 383 | static int | 383 | static int |
| 384 | write_scores (const char *filename, const struct score_entry *scores, int count) | 384 | write_scores (const char *filename, const struct score_entry *scores, int count) |
| 385 | { | 385 | { |
| 386 | int fd; | ||
| 386 | FILE *f; | 387 | FILE *f; |
| 387 | int i; | 388 | int i; |
| 388 | char *tempfile = malloc (strlen (filename) + strlen (".tempXXXXXX") + 1); | 389 | char *tempfile = malloc (strlen (filename) + strlen (".tempXXXXXX") + 1); |
| @@ -390,12 +391,11 @@ write_scores (const char *filename, const struct score_entry *scores, int count) | |||
| 390 | return -1; | 391 | return -1; |
| 391 | strcpy (tempfile, filename); | 392 | strcpy (tempfile, filename); |
| 392 | strcat (tempfile, ".tempXXXXXX"); | 393 | strcat (tempfile, ".tempXXXXXX"); |
| 393 | #ifdef HAVE_MKSTEMP | 394 | fd = mkostemp (tempfile, 0); |
| 394 | if (mkstemp (tempfile) < 0 | 395 | if (fd < 0) |
| 395 | #else | 396 | return -1; |
| 396 | if (mktemp (tempfile) != tempfile | 397 | f = fdopen (fd, "w"); |
| 397 | #endif | 398 | if (! f) |
| 398 | || !(f = fopen (tempfile, "w"))) | ||
| 399 | return -1; | 399 | return -1; |
| 400 | for (i = 0; i < count; i++) | 400 | for (i = 0; i < count; i++) |
| 401 | if (fprintf (f, "%ld %s %s\n", scores[i].score, scores[i].username, | 401 | if (fprintf (f, "%ld %s %s\n", scores[i].score, scores[i].username, |
diff --git a/lib/gnulib.mk b/lib/gnulib.mk index d053e15efc1..32255181fb4 100644 --- a/lib/gnulib.mk +++ b/lib/gnulib.mk | |||
| @@ -21,7 +21,7 @@ | |||
| 21 | # the same distribution terms as the rest of that program. | 21 | # the same distribution terms as the rest of that program. |
| 22 | # | 22 | # |
| 23 | # Generated by gnulib-tool. | 23 | # Generated by gnulib-tool. |
| 24 | # Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday intprops largefile lstat manywarnings memrchr mktime pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat sig2str socklen stat-time stdalign stdarg stdbool stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timer-time timespec-add timespec-sub unsetenv utimens warnings | 24 | # Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat sig2str socklen stat-time stdalign stdarg stdbool stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timer-time timespec-add timespec-sub unsetenv utimens warnings |
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | MOSTLYCLEANFILES += core *.stackdump | 27 | MOSTLYCLEANFILES += core *.stackdump |
| @@ -560,6 +560,15 @@ EXTRA_libgnu_a_SOURCES += memrchr.c | |||
| 560 | 560 | ||
| 561 | ## end gnulib module memrchr | 561 | ## end gnulib module memrchr |
| 562 | 562 | ||
| 563 | ## begin gnulib module mkostemp | ||
| 564 | |||
| 565 | |||
| 566 | EXTRA_DIST += mkostemp.c | ||
| 567 | |||
| 568 | EXTRA_libgnu_a_SOURCES += mkostemp.c | ||
| 569 | |||
| 570 | ## end gnulib module mkostemp | ||
| 571 | |||
| 563 | ## begin gnulib module mktime | 572 | ## begin gnulib module mktime |
| 564 | 573 | ||
| 565 | 574 | ||
| @@ -657,6 +666,17 @@ EXTRA_DIST += root-uid.h | |||
| 657 | 666 | ||
| 658 | ## end gnulib module root-uid | 667 | ## end gnulib module root-uid |
| 659 | 668 | ||
| 669 | ## begin gnulib module secure_getenv | ||
| 670 | |||
| 671 | if gl_GNULIB_ENABLED_secure_getenv | ||
| 672 | |||
| 673 | endif | ||
| 674 | EXTRA_DIST += secure_getenv.c | ||
| 675 | |||
| 676 | EXTRA_libgnu_a_SOURCES += secure_getenv.c | ||
| 677 | |||
| 678 | ## end gnulib module secure_getenv | ||
| 679 | |||
| 660 | ## begin gnulib module sig2str | 680 | ## begin gnulib module sig2str |
| 661 | 681 | ||
| 662 | 682 | ||
| @@ -1480,6 +1500,16 @@ EXTRA_DIST += sys_time.in.h | |||
| 1480 | 1500 | ||
| 1481 | ## end gnulib module sys_time | 1501 | ## end gnulib module sys_time |
| 1482 | 1502 | ||
| 1503 | ## begin gnulib module tempname | ||
| 1504 | |||
| 1505 | if gl_GNULIB_ENABLED_tempname | ||
| 1506 | libgnu_a_SOURCES += tempname.c | ||
| 1507 | |||
| 1508 | endif | ||
| 1509 | EXTRA_DIST += tempname.h | ||
| 1510 | |||
| 1511 | ## end gnulib module tempname | ||
| 1512 | |||
| 1483 | ## begin gnulib module time | 1513 | ## begin gnulib module time |
| 1484 | 1514 | ||
| 1485 | BUILT_SOURCES += time.h | 1515 | BUILT_SOURCES += time.h |
diff --git a/lib/mkostemp.c b/lib/mkostemp.c new file mode 100644 index 00000000000..2188ff5dd61 --- /dev/null +++ b/lib/mkostemp.c | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | /* Copyright (C) 1998-1999, 2001, 2005-2007, 2009-2013 Free Software | ||
| 2 | Foundation, Inc. | ||
| 3 | This file is derived from the one in the GNU C Library. | ||
| 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 | #if !_LIBC | ||
| 19 | # include <config.h> | ||
| 20 | #endif | ||
| 21 | |||
| 22 | #include <stdlib.h> | ||
| 23 | |||
| 24 | #if !_LIBC | ||
| 25 | # include "tempname.h" | ||
| 26 | # define __gen_tempname gen_tempname | ||
| 27 | # ifndef __GTFILE | ||
| 28 | # define __GT_FILE GT_FILE | ||
| 29 | # endif | ||
| 30 | #endif | ||
| 31 | |||
| 32 | #include <stdio.h> | ||
| 33 | |||
| 34 | #ifndef __GT_FILE | ||
| 35 | # define __GT_FILE 0 | ||
| 36 | #endif | ||
| 37 | |||
| 38 | /* Generate a unique temporary file name from XTEMPLATE. | ||
| 39 | The last six characters of XTEMPLATE must be "XXXXXX"; | ||
| 40 | they are replaced with a string that makes the file name unique. | ||
| 41 | Then open the file and return a fd. */ | ||
| 42 | int | ||
| 43 | mkostemp (char *xtemplate, int flags) | ||
| 44 | { | ||
| 45 | return __gen_tempname (xtemplate, 0, flags, __GT_FILE); | ||
| 46 | } | ||
diff --git a/lib/secure_getenv.c b/lib/secure_getenv.c new file mode 100644 index 00000000000..6c11c5e0edb --- /dev/null +++ b/lib/secure_getenv.c | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | /* Look up an environment variable more securely. | ||
| 2 | |||
| 3 | Copyright 2013 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This program is free software: you can redistribute it and/or modify it | ||
| 6 | under the terms of the GNU General Public License as published | ||
| 7 | by 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 GNU | ||
| 13 | 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 | #include <config.h> | ||
| 19 | |||
| 20 | #include <stdlib.h> | ||
| 21 | |||
| 22 | #if !HAVE___SECURE_GETENV | ||
| 23 | # if HAVE_ISSETUGID | ||
| 24 | # include <unistd.h> | ||
| 25 | # else | ||
| 26 | # undef issetugid | ||
| 27 | # define issetugid() 1 | ||
| 28 | # endif | ||
| 29 | #endif | ||
| 30 | |||
| 31 | char * | ||
| 32 | secure_getenv (char const *name) | ||
| 33 | { | ||
| 34 | #if HAVE___SECURE_GETENV | ||
| 35 | return __secure_getenv (name); | ||
| 36 | #else | ||
| 37 | if (issetugid ()) | ||
| 38 | return 0; | ||
| 39 | return getenv (name); | ||
| 40 | #endif | ||
| 41 | } | ||
diff --git a/lib/tempname.c b/lib/tempname.c new file mode 100644 index 00000000000..087b79b31fe --- /dev/null +++ b/lib/tempname.c | |||
| @@ -0,0 +1,306 @@ | |||
| 1 | /* tempname.c - generate the name of a temporary file. | ||
| 2 | |||
| 3 | Copyright (C) 1991-2003, 2005-2007, 2009-2013 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 | /* Extracted from glibc sysdeps/posix/tempname.c. See also tmpdir.c. */ | ||
| 19 | |||
| 20 | #if !_LIBC | ||
| 21 | # include <config.h> | ||
| 22 | # include "tempname.h" | ||
| 23 | #endif | ||
| 24 | |||
| 25 | #include <sys/types.h> | ||
| 26 | #include <assert.h> | ||
| 27 | |||
| 28 | #include <errno.h> | ||
| 29 | #ifndef __set_errno | ||
| 30 | # define __set_errno(Val) errno = (Val) | ||
| 31 | #endif | ||
| 32 | |||
| 33 | #include <stdio.h> | ||
| 34 | #ifndef P_tmpdir | ||
| 35 | # define P_tmpdir "/tmp" | ||
| 36 | #endif | ||
| 37 | #ifndef TMP_MAX | ||
| 38 | # define TMP_MAX 238328 | ||
| 39 | #endif | ||
| 40 | #ifndef __GT_FILE | ||
| 41 | # define __GT_FILE 0 | ||
| 42 | # define __GT_DIR 1 | ||
| 43 | # define __GT_NOCREATE 2 | ||
| 44 | #endif | ||
| 45 | #if !_LIBC && (GT_FILE != __GT_FILE || GT_DIR != __GT_DIR \ | ||
| 46 | || GT_NOCREATE != __GT_NOCREATE) | ||
| 47 | # error report this to bug-gnulib@gnu.org | ||
| 48 | #endif | ||
| 49 | |||
| 50 | #include <stddef.h> | ||
| 51 | #include <stdlib.h> | ||
| 52 | #include <string.h> | ||
| 53 | |||
| 54 | #include <fcntl.h> | ||
| 55 | #include <sys/time.h> | ||
| 56 | #include <stdint.h> | ||
| 57 | #include <unistd.h> | ||
| 58 | |||
| 59 | #include <sys/stat.h> | ||
| 60 | |||
| 61 | #if _LIBC | ||
| 62 | # define struct_stat64 struct stat64 | ||
| 63 | #else | ||
| 64 | # define struct_stat64 struct stat | ||
| 65 | # define __gen_tempname gen_tempname | ||
| 66 | # define __getpid getpid | ||
| 67 | # define __gettimeofday gettimeofday | ||
| 68 | # define __mkdir mkdir | ||
| 69 | # define __open open | ||
| 70 | # define __lxstat64(version, file, buf) lstat (file, buf) | ||
| 71 | # define __secure_getenv secure_getenv | ||
| 72 | #endif | ||
| 73 | |||
| 74 | #ifdef _LIBC | ||
| 75 | # include <hp-timing.h> | ||
| 76 | # if HP_TIMING_AVAIL | ||
| 77 | # define RANDOM_BITS(Var) \ | ||
| 78 | if (__builtin_expect (value == UINT64_C (0), 0)) \ | ||
| 79 | { \ | ||
| 80 | /* If this is the first time this function is used initialize \ | ||
| 81 | the variable we accumulate the value in to some somewhat \ | ||
| 82 | random value. If we'd not do this programs at startup time \ | ||
| 83 | might have a reduced set of possible names, at least on slow \ | ||
| 84 | machines. */ \ | ||
| 85 | struct timeval tv; \ | ||
| 86 | __gettimeofday (&tv, NULL); \ | ||
| 87 | value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \ | ||
| 88 | } \ | ||
| 89 | HP_TIMING_NOW (Var) | ||
| 90 | # endif | ||
| 91 | #endif | ||
| 92 | |||
| 93 | /* Use the widest available unsigned type if uint64_t is not | ||
| 94 | available. The algorithm below extracts a number less than 62**6 | ||
| 95 | (approximately 2**35.725) from uint64_t, so ancient hosts where | ||
| 96 | uintmax_t is only 32 bits lose about 3.725 bits of randomness, | ||
| 97 | which is better than not having mkstemp at all. */ | ||
| 98 | #if !defined UINT64_MAX && !defined uint64_t | ||
| 99 | # define uint64_t uintmax_t | ||
| 100 | #endif | ||
| 101 | |||
| 102 | #if _LIBC | ||
| 103 | /* Return nonzero if DIR is an existent directory. */ | ||
| 104 | static int | ||
| 105 | direxists (const char *dir) | ||
| 106 | { | ||
| 107 | struct_stat64 buf; | ||
| 108 | return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode); | ||
| 109 | } | ||
| 110 | |||
| 111 | /* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is | ||
| 112 | non-null and exists, uses it; otherwise uses the first of $TMPDIR, | ||
| 113 | P_tmpdir, /tmp that exists. Copies into TMPL a template suitable | ||
| 114 | for use with mk[s]temp. Will fail (-1) if DIR is non-null and | ||
| 115 | doesn't exist, none of the searched dirs exists, or there's not | ||
| 116 | enough space in TMPL. */ | ||
| 117 | int | ||
| 118 | __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, | ||
| 119 | int try_tmpdir) | ||
| 120 | { | ||
| 121 | const char *d; | ||
| 122 | size_t dlen, plen; | ||
| 123 | |||
| 124 | if (!pfx || !pfx[0]) | ||
| 125 | { | ||
| 126 | pfx = "file"; | ||
| 127 | plen = 4; | ||
| 128 | } | ||
| 129 | else | ||
| 130 | { | ||
| 131 | plen = strlen (pfx); | ||
| 132 | if (plen > 5) | ||
| 133 | plen = 5; | ||
| 134 | } | ||
| 135 | |||
| 136 | if (try_tmpdir) | ||
| 137 | { | ||
| 138 | d = __secure_getenv ("TMPDIR"); | ||
| 139 | if (d != NULL && direxists (d)) | ||
| 140 | dir = d; | ||
| 141 | else if (dir != NULL && direxists (dir)) | ||
| 142 | /* nothing */ ; | ||
| 143 | else | ||
| 144 | dir = NULL; | ||
| 145 | } | ||
| 146 | if (dir == NULL) | ||
| 147 | { | ||
| 148 | if (direxists (P_tmpdir)) | ||
| 149 | dir = P_tmpdir; | ||
| 150 | else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) | ||
| 151 | dir = "/tmp"; | ||
| 152 | else | ||
| 153 | { | ||
| 154 | __set_errno (ENOENT); | ||
| 155 | return -1; | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 159 | dlen = strlen (dir); | ||
| 160 | while (dlen > 1 && dir[dlen - 1] == '/') | ||
| 161 | dlen--; /* remove trailing slashes */ | ||
| 162 | |||
| 163 | /* check we have room for "${dir}/${pfx}XXXXXX\0" */ | ||
| 164 | if (tmpl_len < dlen + 1 + plen + 6 + 1) | ||
| 165 | { | ||
| 166 | __set_errno (EINVAL); | ||
| 167 | return -1; | ||
| 168 | } | ||
| 169 | |||
| 170 | sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx); | ||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | #endif /* _LIBC */ | ||
| 174 | |||
| 175 | /* These are the characters used in temporary file names. */ | ||
| 176 | static const char letters[] = | ||
| 177 | "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; | ||
| 178 | |||
| 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 | ||
| 193 | __gen_tempname (char *tmpl, int suffixlen, int flags, int kind) | ||
| 194 | { | ||
| 195 | int len; | ||
| 196 | char *XXXXXX; | ||
| 197 | static uint64_t value; | ||
| 198 | uint64_t random_time_bits; | ||
| 199 | unsigned int count; | ||
| 200 | int fd = -1; | ||
| 201 | int save_errno = errno; | ||
| 202 | struct_stat64 st; | ||
| 203 | |||
| 204 | /* A lower bound on the number of temporary files to attempt to | ||
| 205 | generate. The maximum total number of temporary file names that | ||
| 206 | can exist for a given template is 62**6. It should never be | ||
| 207 | necessary to try all of these combinations. Instead if a reasonable | ||
| 208 | number of names is tried (we define reasonable as 62**3) fail to | ||
| 209 | give the system administrator the chance to remove the problems. */ | ||
| 210 | #define ATTEMPTS_MIN (62 * 62 * 62) | ||
| 211 | |||
| 212 | /* The number of times to attempt to generate a temporary file. To | ||
| 213 | conform to POSIX, this must be no smaller than TMP_MAX. */ | ||
| 214 | #if ATTEMPTS_MIN < TMP_MAX | ||
| 215 | unsigned int attempts = TMP_MAX; | ||
| 216 | #else | ||
| 217 | unsigned int attempts = ATTEMPTS_MIN; | ||
| 218 | #endif | ||
| 219 | |||
| 220 | len = strlen (tmpl); | ||
| 221 | if (len < 6 + suffixlen || memcmp (&tmpl[len - 6 - suffixlen], "XXXXXX", 6)) | ||
| 222 | { | ||
| 223 | __set_errno (EINVAL); | ||
| 224 | return -1; | ||
| 225 | } | ||
| 226 | |||
| 227 | /* This is where the Xs start. */ | ||
| 228 | XXXXXX = &tmpl[len - 6 - suffixlen]; | ||
| 229 | |||
| 230 | /* Get some more or less random data. */ | ||
| 231 | #ifdef RANDOM_BITS | ||
| 232 | RANDOM_BITS (random_time_bits); | ||
| 233 | #else | ||
| 234 | { | ||
| 235 | struct timeval tv; | ||
| 236 | __gettimeofday (&tv, NULL); | ||
| 237 | random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; | ||
| 238 | } | ||
| 239 | #endif | ||
| 240 | value += random_time_bits ^ __getpid (); | ||
| 241 | |||
| 242 | for (count = 0; count < attempts; value += 7777, ++count) | ||
| 243 | { | ||
| 244 | uint64_t v = value; | ||
| 245 | |||
| 246 | /* Fill in the random bits. */ | ||
| 247 | XXXXXX[0] = letters[v % 62]; | ||
| 248 | v /= 62; | ||
| 249 | XXXXXX[1] = letters[v % 62]; | ||
| 250 | v /= 62; | ||
| 251 | XXXXXX[2] = letters[v % 62]; | ||
| 252 | v /= 62; | ||
| 253 | XXXXXX[3] = letters[v % 62]; | ||
| 254 | v /= 62; | ||
| 255 | XXXXXX[4] = letters[v % 62]; | ||
| 256 | v /= 62; | ||
| 257 | XXXXXX[5] = letters[v % 62]; | ||
| 258 | |||
| 259 | switch (kind) | ||
| 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) | ||
| 295 | { | ||
| 296 | __set_errno (save_errno); | ||
| 297 | return fd; | ||
| 298 | } | ||
| 299 | else if (errno != EEXIST) | ||
| 300 | return -1; | ||
| 301 | } | ||
| 302 | |||
| 303 | /* We got out of the loop because we ran out of combinations to try. */ | ||
| 304 | __set_errno (EEXIST); | ||
| 305 | return -1; | ||
| 306 | } | ||
diff --git a/lib/tempname.h b/lib/tempname.h new file mode 100644 index 00000000000..333267dfd09 --- /dev/null +++ b/lib/tempname.h | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | /* Create a temporary file or directory. | ||
| 2 | |||
| 3 | Copyright (C) 2006, 2009-2013 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 | /* header written by Eric Blake */ | ||
| 19 | |||
| 20 | #ifndef GL_TEMPNAME_H | ||
| 21 | # define GL_TEMPNAME_H | ||
| 22 | |||
| 23 | # include <stdio.h> | ||
| 24 | |||
| 25 | # ifdef __GT_FILE | ||
| 26 | # define GT_FILE __GT_FILE | ||
| 27 | # define GT_DIR __GT_DIR | ||
| 28 | # define GT_NOCREATE __GT_NOCREATE | ||
| 29 | # else | ||
| 30 | # define GT_FILE 0 | ||
| 31 | # define GT_DIR 1 | ||
| 32 | # define GT_NOCREATE 2 | ||
| 33 | # endif | ||
| 34 | |||
| 35 | /* 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). | ||
| 37 | The name constructed does not exist at the time of the call to | ||
| 38 | gen_tempname. TMPL is overwritten with the result. | ||
| 39 | |||
| 40 | KIND may be one of: | ||
| 41 | GT_NOCREATE: simply verify that the name does not exist | ||
| 42 | at the time of the call. | ||
| 43 | GT_FILE: create a large file using open(O_CREAT|O_EXCL) | ||
| 44 | and return a read-write fd. The file is mode 0600. | ||
| 45 | GT_DIR: create a directory, which will be mode 0700. | ||
| 46 | |||
| 47 | We use a clever algorithm to get hard-to-predict names. */ | ||
| 48 | extern int gen_tempname (char *tmpl, int suffixlen, int flags, int kind); | ||
| 49 | |||
| 50 | #endif /* GL_TEMPNAME_H */ | ||
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index d7062e862de..af9a9ca3ae0 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 | |||
| @@ -89,6 +89,7 @@ AC_DEFUN([gl_EARLY], | |||
| 89 | # Code from module lstat: | 89 | # Code from module lstat: |
| 90 | # Code from module manywarnings: | 90 | # Code from module manywarnings: |
| 91 | # Code from module memrchr: | 91 | # Code from module memrchr: |
| 92 | # Code from module mkostemp: | ||
| 92 | # Code from module mktime: | 93 | # Code from module mktime: |
| 93 | # Code from module multiarch: | 94 | # Code from module multiarch: |
| 94 | # Code from module nocrash: | 95 | # Code from module nocrash: |
| @@ -102,6 +103,7 @@ AC_DEFUN([gl_EARLY], | |||
| 102 | # Code from module readlink: | 103 | # Code from module readlink: |
| 103 | # Code from module readlinkat: | 104 | # Code from module readlinkat: |
| 104 | # Code from module root-uid: | 105 | # Code from module root-uid: |
| 106 | # Code from module secure_getenv: | ||
| 105 | # Code from module sig2str: | 107 | # Code from module sig2str: |
| 106 | # Code from module signal-h: | 108 | # Code from module signal-h: |
| 107 | # Code from module snippet/_Noreturn: | 109 | # Code from module snippet/_Noreturn: |
| @@ -134,6 +136,7 @@ AC_DEFUN([gl_EARLY], | |||
| 134 | # Code from module sys_select: | 136 | # Code from module sys_select: |
| 135 | # Code from module sys_stat: | 137 | # Code from module sys_stat: |
| 136 | # Code from module sys_time: | 138 | # Code from module sys_time: |
| 139 | # Code from module tempname: | ||
| 137 | # Code from module time: | 140 | # Code from module time: |
| 138 | # Code from module time_r: | 141 | # Code from module time_r: |
| 139 | # Code from module timer-time: | 142 | # Code from module timer-time: |
| @@ -274,6 +277,13 @@ AC_DEFUN([gl_INIT], | |||
| 274 | gl_PREREQ_MEMRCHR | 277 | gl_PREREQ_MEMRCHR |
| 275 | fi | 278 | fi |
| 276 | gl_STRING_MODULE_INDICATOR([memrchr]) | 279 | gl_STRING_MODULE_INDICATOR([memrchr]) |
| 280 | gl_FUNC_MKOSTEMP | ||
| 281 | if test $HAVE_MKOSTEMP = 0; then | ||
| 282 | AC_LIBOBJ([mkostemp]) | ||
| 283 | gl_PREREQ_MKOSTEMP | ||
| 284 | fi | ||
| 285 | gl_MODULE_INDICATOR([mkostemp]) | ||
| 286 | gl_STDLIB_MODULE_INDICATOR([mkostemp]) | ||
| 277 | gl_FUNC_MKTIME | 287 | gl_FUNC_MKTIME |
| 278 | if test $REPLACE_MKTIME = 1; then | 288 | if test $REPLACE_MKTIME = 1; then |
| 279 | AC_LIBOBJ([mktime]) | 289 | AC_LIBOBJ([mktime]) |
| @@ -381,9 +391,11 @@ AC_DEFUN([gl_INIT], | |||
| 381 | gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7=false | 391 | gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7=false |
| 382 | gl_gnulib_enabled_pathmax=false | 392 | gl_gnulib_enabled_pathmax=false |
| 383 | gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=false | 393 | gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=false |
| 394 | gl_gnulib_enabled_secure_getenv=false | ||
| 384 | gl_gnulib_enabled_stat=false | 395 | gl_gnulib_enabled_stat=false |
| 385 | gl_gnulib_enabled_strtoll=false | 396 | gl_gnulib_enabled_strtoll=false |
| 386 | gl_gnulib_enabled_strtoull=false | 397 | gl_gnulib_enabled_strtoull=false |
| 398 | gl_gnulib_enabled_tempname=false | ||
| 387 | gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec=false | 399 | gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec=false |
| 388 | func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b () | 400 | func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b () |
| 389 | { | 401 | { |
| @@ -485,6 +497,18 @@ AC_DEFUN([gl_INIT], | |||
| 485 | gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=true | 497 | gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=true |
| 486 | fi | 498 | fi |
| 487 | } | 499 | } |
| 500 | func_gl_gnulib_m4code_secure_getenv () | ||
| 501 | { | ||
| 502 | if ! $gl_gnulib_enabled_secure_getenv; then | ||
| 503 | gl_FUNC_SECURE_GETENV | ||
| 504 | if test $HAVE_SECURE_GETENV = 0; then | ||
| 505 | AC_LIBOBJ([secure_getenv]) | ||
| 506 | gl_PREREQ_SECURE_GETENV | ||
| 507 | fi | ||
| 508 | gl_STDLIB_MODULE_INDICATOR([secure_getenv]) | ||
| 509 | gl_gnulib_enabled_secure_getenv=true | ||
| 510 | fi | ||
| 511 | } | ||
| 488 | func_gl_gnulib_m4code_stat () | 512 | func_gl_gnulib_m4code_stat () |
| 489 | { | 513 | { |
| 490 | if ! $gl_gnulib_enabled_stat; then | 514 | if ! $gl_gnulib_enabled_stat; then |
| @@ -527,6 +551,14 @@ AC_DEFUN([gl_INIT], | |||
| 527 | gl_gnulib_enabled_strtoull=true | 551 | gl_gnulib_enabled_strtoull=true |
| 528 | fi | 552 | fi |
| 529 | } | 553 | } |
| 554 | func_gl_gnulib_m4code_tempname () | ||
| 555 | { | ||
| 556 | if ! $gl_gnulib_enabled_tempname; then | ||
| 557 | gl_FUNC_GEN_TEMPNAME | ||
| 558 | gl_gnulib_enabled_tempname=true | ||
| 559 | func_gl_gnulib_m4code_secure_getenv | ||
| 560 | fi | ||
| 561 | } | ||
| 530 | func_gl_gnulib_m4code_682e609604ccaac6be382e4ee3a4eaec () | 562 | func_gl_gnulib_m4code_682e609604ccaac6be382e4ee3a4eaec () |
| 531 | { | 563 | { |
| 532 | if ! $gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec; then | 564 | if ! $gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec; then |
| @@ -569,6 +601,9 @@ AC_DEFUN([gl_INIT], | |||
| 569 | if test $REPLACE_LSTAT = 1; then | 601 | if test $REPLACE_LSTAT = 1; then |
| 570 | func_gl_gnulib_m4code_stat | 602 | func_gl_gnulib_m4code_stat |
| 571 | fi | 603 | fi |
| 604 | if test $HAVE_MKOSTEMP = 0; then | ||
| 605 | func_gl_gnulib_m4code_tempname | ||
| 606 | fi | ||
| 572 | if test $HAVE_READLINK = 0 || test $REPLACE_READLINK = 1; then | 607 | if test $HAVE_READLINK = 0 || test $REPLACE_READLINK = 1; then |
| 573 | func_gl_gnulib_m4code_stat | 608 | func_gl_gnulib_m4code_stat |
| 574 | fi | 609 | fi |
| @@ -598,9 +633,11 @@ AC_DEFUN([gl_INIT], | |||
| 598 | AM_CONDITIONAL([gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7], [$gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7]) | 633 | AM_CONDITIONAL([gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7], [$gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7]) |
| 599 | AM_CONDITIONAL([gl_GNULIB_ENABLED_pathmax], [$gl_gnulib_enabled_pathmax]) | 634 | AM_CONDITIONAL([gl_GNULIB_ENABLED_pathmax], [$gl_gnulib_enabled_pathmax]) |
| 600 | AM_CONDITIONAL([gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c], [$gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c]) | 635 | AM_CONDITIONAL([gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c], [$gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c]) |
| 636 | AM_CONDITIONAL([gl_GNULIB_ENABLED_secure_getenv], [$gl_gnulib_enabled_secure_getenv]) | ||
| 601 | AM_CONDITIONAL([gl_GNULIB_ENABLED_stat], [$gl_gnulib_enabled_stat]) | 637 | AM_CONDITIONAL([gl_GNULIB_ENABLED_stat], [$gl_gnulib_enabled_stat]) |
| 602 | AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoll], [$gl_gnulib_enabled_strtoll]) | 638 | AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoll], [$gl_gnulib_enabled_strtoll]) |
| 603 | AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoull], [$gl_gnulib_enabled_strtoull]) | 639 | AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoull], [$gl_gnulib_enabled_strtoull]) |
| 640 | AM_CONDITIONAL([gl_GNULIB_ENABLED_tempname], [$gl_gnulib_enabled_tempname]) | ||
| 604 | AM_CONDITIONAL([gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec], [$gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec]) | 641 | AM_CONDITIONAL([gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec], [$gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec]) |
| 605 | # End of code from modules | 642 | # End of code from modules |
| 606 | m4_ifval(gl_LIBSOURCES_LIST, [ | 643 | m4_ifval(gl_LIBSOURCES_LIST, [ |
| @@ -806,6 +843,7 @@ AC_DEFUN([gl_FILE_LIST], [ | |||
| 806 | lib/md5.c | 843 | lib/md5.c |
| 807 | lib/md5.h | 844 | lib/md5.h |
| 808 | lib/memrchr.c | 845 | lib/memrchr.c |
| 846 | lib/mkostemp.c | ||
| 809 | lib/mktime-internal.h | 847 | lib/mktime-internal.h |
| 810 | lib/mktime.c | 848 | lib/mktime.c |
| 811 | lib/openat-priv.h | 849 | lib/openat-priv.h |
| @@ -821,6 +859,7 @@ AC_DEFUN([gl_FILE_LIST], [ | |||
| 821 | lib/readlink.c | 859 | lib/readlink.c |
| 822 | lib/readlinkat.c | 860 | lib/readlinkat.c |
| 823 | lib/root-uid.h | 861 | lib/root-uid.h |
| 862 | lib/secure_getenv.c | ||
| 824 | lib/sha1.c | 863 | lib/sha1.c |
| 825 | lib/sha1.h | 864 | lib/sha1.h |
| 826 | lib/sha256.c | 865 | lib/sha256.c |
| @@ -853,6 +892,8 @@ AC_DEFUN([gl_FILE_LIST], [ | |||
| 853 | lib/sys_select.in.h | 892 | lib/sys_select.in.h |
| 854 | lib/sys_stat.in.h | 893 | lib/sys_stat.in.h |
| 855 | lib/sys_time.in.h | 894 | lib/sys_time.in.h |
| 895 | lib/tempname.c | ||
| 896 | lib/tempname.h | ||
| 856 | lib/time.in.h | 897 | lib/time.in.h |
| 857 | lib/time_r.c | 898 | lib/time_r.c |
| 858 | lib/timespec-add.c | 899 | lib/timespec-add.c |
| @@ -908,6 +949,7 @@ AC_DEFUN([gl_FILE_LIST], [ | |||
| 908 | m4/manywarnings.m4 | 949 | m4/manywarnings.m4 |
| 909 | m4/md5.m4 | 950 | m4/md5.m4 |
| 910 | m4/memrchr.m4 | 951 | m4/memrchr.m4 |
| 952 | m4/mkostemp.m4 | ||
| 911 | m4/mktime.m4 | 953 | m4/mktime.m4 |
| 912 | m4/multiarch.m4 | 954 | m4/multiarch.m4 |
| 913 | m4/nocrash.m4 | 955 | m4/nocrash.m4 |
| @@ -919,6 +961,7 @@ AC_DEFUN([gl_FILE_LIST], [ | |||
| 919 | m4/putenv.m4 | 961 | m4/putenv.m4 |
| 920 | m4/readlink.m4 | 962 | m4/readlink.m4 |
| 921 | m4/readlinkat.m4 | 963 | m4/readlinkat.m4 |
| 964 | m4/secure_getenv.m4 | ||
| 922 | m4/setenv.m4 | 965 | m4/setenv.m4 |
| 923 | m4/sha1.m4 | 966 | m4/sha1.m4 |
| 924 | m4/sha256.m4 | 967 | m4/sha256.m4 |
| @@ -948,6 +991,7 @@ AC_DEFUN([gl_FILE_LIST], [ | |||
| 948 | m4/sys_socket_h.m4 | 991 | m4/sys_socket_h.m4 |
| 949 | m4/sys_stat_h.m4 | 992 | m4/sys_stat_h.m4 |
| 950 | m4/sys_time_h.m4 | 993 | m4/sys_time_h.m4 |
| 994 | m4/tempname.m4 | ||
| 951 | m4/time_h.m4 | 995 | m4/time_h.m4 |
| 952 | m4/time_r.m4 | 996 | m4/time_r.m4 |
| 953 | m4/timer_time.m4 | 997 | m4/timer_time.m4 |
diff --git a/m4/mkostemp.m4 b/m4/mkostemp.m4 new file mode 100644 index 00000000000..6d101eeda39 --- /dev/null +++ b/m4/mkostemp.m4 | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | # mkostemp.m4 serial 2 | ||
| 2 | dnl Copyright (C) 2009-2013 Free Software Foundation, Inc. | ||
| 3 | dnl This file is free software; the Free Software Foundation | ||
| 4 | dnl gives unlimited permission to copy and/or distribute it, | ||
| 5 | dnl with or without modifications, as long as this notice is preserved. | ||
| 6 | |||
| 7 | AC_DEFUN([gl_FUNC_MKOSTEMP], | ||
| 8 | [ | ||
| 9 | AC_REQUIRE([gl_STDLIB_H_DEFAULTS]) | ||
| 10 | |||
| 11 | dnl Persuade glibc <stdlib.h> to declare mkostemp(). | ||
| 12 | AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) | ||
| 13 | |||
| 14 | AC_CHECK_FUNCS_ONCE([mkostemp]) | ||
| 15 | if test $ac_cv_func_mkostemp != yes; then | ||
| 16 | HAVE_MKOSTEMP=0 | ||
| 17 | fi | ||
| 18 | ]) | ||
| 19 | |||
| 20 | # Prerequisites of lib/mkostemp.c. | ||
| 21 | AC_DEFUN([gl_PREREQ_MKOSTEMP], | ||
| 22 | [ | ||
| 23 | ]) | ||
diff --git a/m4/secure_getenv.m4 b/m4/secure_getenv.m4 new file mode 100644 index 00000000000..5da5298f669 --- /dev/null +++ b/m4/secure_getenv.m4 | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | # Look up an environment variable more securely. | ||
| 2 | dnl Copyright 2013 Free Software Foundation, Inc. | ||
| 3 | dnl This file is free software; the Free Software Foundation | ||
| 4 | dnl gives unlimited permission to copy and/or distribute it, | ||
| 5 | dnl with or without modifications, as long as this notice is preserved. | ||
| 6 | |||
| 7 | AC_DEFUN([gl_FUNC_SECURE_GETENV], | ||
| 8 | [ | ||
| 9 | dnl Persuade glibc <stdlib.h> to declare secure_getenv(). | ||
| 10 | AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) | ||
| 11 | |||
| 12 | AC_REQUIRE([gl_STDLIB_H_DEFAULTS]) | ||
| 13 | AC_CHECK_FUNCS_ONCE([secure_getenv]) | ||
| 14 | if test $ac_cv_func_secure_getenv = no; then | ||
| 15 | HAVE_SECURE_GETENV=0 | ||
| 16 | fi | ||
| 17 | ]) | ||
| 18 | |||
| 19 | # Prerequisites of lib/secure_getenv.c. | ||
| 20 | AC_DEFUN([gl_PREREQ_SECURE_GETENV], [ | ||
| 21 | AC_CHECK_FUNCS([__secure_getenv]) | ||
| 22 | if test $ac_cv_func___secure_getenv = no; then | ||
| 23 | AC_CHECK_FUNCS([issetugid]) | ||
| 24 | fi | ||
| 25 | ]) | ||
diff --git a/m4/tempname.m4 b/m4/tempname.m4 new file mode 100644 index 00000000000..a6e42dcea81 --- /dev/null +++ b/m4/tempname.m4 | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | #serial 5 | ||
| 2 | |||
| 3 | # Copyright (C) 2006-2007, 2009-2013 Free Software Foundation, Inc. | ||
| 4 | # This file is free software; the Free Software Foundation | ||
| 5 | # gives unlimited permission to copy and/or distribute it, | ||
| 6 | # with or without modifications, as long as this notice is preserved. | ||
| 7 | |||
| 8 | # glibc provides __gen_tempname as a wrapper for mk[ds]temp. Expose | ||
| 9 | # it as a public API, and provide it on systems that are lacking. | ||
| 10 | AC_DEFUN([gl_FUNC_GEN_TEMPNAME], | ||
| 11 | [ | ||
| 12 | gl_PREREQ_TEMPNAME | ||
| 13 | ]) | ||
| 14 | |||
| 15 | # Prerequisites of lib/tempname.c. | ||
| 16 | AC_DEFUN([gl_PREREQ_TEMPNAME], | ||
| 17 | [ | ||
| 18 | : | ||
| 19 | ]) | ||
diff --git a/src/ChangeLog b/src/ChangeLog index c29c4c8da59..f8f2fa47089 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,10 @@ | |||
| 1 | 2013-08-04 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Fix some minor races in hosts lacking mkostemp (Bug#15015). | ||
| 4 | * callproc.c (create_temp_file): | ||
| 5 | * filelock.c (create_lock_file): | ||
| 6 | Assume mkostemp, since it's now provided by Gnulib. | ||
| 7 | |||
| 1 | 2013-08-04 Eli Zaretskii <eliz@gnu.org> | 8 | 2013-08-04 Eli Zaretskii <eliz@gnu.org> |
| 2 | 9 | ||
| 3 | * w32.c (mkostemp): New function. | 10 | * w32.c (mkostemp): New function. |
diff --git a/src/callproc.c b/src/callproc.c index 450fc57f929..54bc5cd9dc0 100644 --- a/src/callproc.c +++ b/src/callproc.c | |||
| @@ -1009,23 +1009,11 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args) | |||
| 1009 | tempfile = SSDATA (filename_string); | 1009 | tempfile = SSDATA (filename_string); |
| 1010 | 1010 | ||
| 1011 | { | 1011 | { |
| 1012 | int fd; | 1012 | int fd = mkostemp (tempfile, O_CLOEXEC); |
| 1013 | |||
| 1014 | #ifdef HAVE_MKOSTEMP | ||
| 1015 | fd = mkostemp (tempfile, O_CLOEXEC); | ||
| 1016 | #elif defined HAVE_MKSTEMP | ||
| 1017 | fd = mkstemp (tempfile); | ||
| 1018 | #else | ||
| 1019 | errno = EEXIST; | ||
| 1020 | mktemp (tempfile); | ||
| 1021 | fd = *tempfile ? 0 : -1; | ||
| 1022 | #endif | ||
| 1023 | if (fd < 0) | 1013 | if (fd < 0) |
| 1024 | report_file_error ("Failed to open temporary file using pattern", | 1014 | report_file_error ("Failed to open temporary file using pattern", |
| 1025 | pattern); | 1015 | pattern); |
| 1026 | #if defined HAVE_MKOSTEMP || defined HAVE_MKSTEMP | ||
| 1027 | emacs_close (fd); | 1016 | emacs_close (fd); |
| 1028 | #endif | ||
| 1029 | } | 1017 | } |
| 1030 | 1018 | ||
| 1031 | record_unwind_protect (delete_temp_file, filename_string); | 1019 | record_unwind_protect (delete_temp_file, filename_string); |
diff --git a/src/filelock.c b/src/filelock.c index b9c991e4baf..0f31b7d4deb 100644 --- a/src/filelock.c +++ b/src/filelock.c | |||
| @@ -411,28 +411,14 @@ create_lock_file (char *lfname, char *lock_info_str, bool force) | |||
| 411 | memcpy (nonce, lfname, lfdirlen); | 411 | memcpy (nonce, lfname, lfdirlen); |
| 412 | strcpy (nonce + lfdirlen, nonce_base); | 412 | strcpy (nonce + lfdirlen, nonce_base); |
| 413 | 413 | ||
| 414 | #if HAVE_MKOSTEMP | ||
| 415 | /* Prefer mkostemp to mkstemp, as it avoids a window where FD is | ||
| 416 | temporarily open without close-on-exec. */ | ||
| 417 | fd = mkostemp (nonce, O_BINARY | O_CLOEXEC); | 414 | fd = mkostemp (nonce, O_BINARY | O_CLOEXEC); |
| 418 | #elif HAVE_MKSTEMP | ||
| 419 | /* Prefer mkstemp to mktemp, as it avoids a race between | ||
| 420 | mktemp and emacs_open. */ | ||
| 421 | fd = mkstemp (nonce); | ||
| 422 | #else | ||
| 423 | mktemp (nonce); | ||
| 424 | fd = emacs_open (nonce, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, | ||
| 425 | S_IRUSR | S_IWUSR); | ||
| 426 | #endif | ||
| 427 | |||
| 428 | if (fd < 0) | 415 | if (fd < 0) |
| 429 | err = errno; | 416 | err = errno; |
| 430 | else | 417 | else |
| 431 | { | 418 | { |
| 432 | ptrdiff_t lock_info_len; | 419 | ptrdiff_t lock_info_len; |
| 433 | #if ! (HAVE_MKOSTEMP && O_CLOEXEC) | 420 | if (! O_CLOEXEC) |
| 434 | fcntl (fd, F_SETFD, FD_CLOEXEC); | 421 | fcntl (fd, F_SETFD, FD_CLOEXEC); |
| 435 | #endif | ||
| 436 | lock_info_len = strlen (lock_info_str); | 422 | lock_info_len = strlen (lock_info_str); |
| 437 | err = 0; | 423 | err = 0; |
| 438 | /* Use 'write', not 'emacs_write', as garbage collection | 424 | /* Use 'write', not 'emacs_write', as garbage collection |