From: Paul Eggert <eggert@cs.ucla.edu>
To: Eli Zaretskii <eliz@gnu.org>
Cc: 28023@debbugs.gnu.org
Subject: bug#28023: fix make-temp-file race on local host
Date: Wed, 9 Aug 2017 16:36:55 -0700 [thread overview]
Message-ID: <704c73b8-54f1-f7ac-821b-6d715a21a8a2@cs.ucla.edu> (raw)
In-Reply-To: <83lgmssglm.fsf@gnu.org>
[-- Attachment #1: Type: text/plain, Size: 502 bytes --]
Eli Zaretskii wrote:
> Perhaps you are right, and it will "just work". I will have to try
> (for now, I just looked at the sources and the changes, but didn't try
> building).
It looks to me like it should just work. You might also consider the second
attached patch: it removes the MS-Windows implementation of mkostemp, since the
generic code should just work as well. I've tested only the first attached
patch, though: it is basically the same as before except it's rebased to current
master.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Fix-make-temp-file-race-on-local-files.patch --]
[-- Type: text/x-patch; name="0001-Fix-make-temp-file-race-on-local-files.patch", Size: 20531 bytes --]
From 7fe4062aebf56a7de1ae389907098cd461f8d485 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Wed, 9 Aug 2017 16:34:40 -0700
Subject: [PATCH 1/2] Fix make-temp-file race on local files
For the motivation behind this patch, please see Bug#28023 and:
http://emacshorrors.com/posts/make-temp-name.html
The race still exists for magic file names;
fixing this will require Tramp surgery.
* admin/merge-gnulib (GNULIB_MODULES): Add tempname, now
that Emacs is using it directly.
* configure.ac (AUTO_DEPEND): Remove AC_SYS_LONG_FILE_NAMES;
no longer needed.
* lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate.
* lisp/files.el (files--make-magic-temp-file): Rename from
make-temp-file. Add comment describing race bug.
(make-temp-file): Use fileio--make-temp-file for
non-magic files names.
* src/fileio.c: Include tempname.h.
(make_temp_name_tbl, make_temp_name_count)
(make_temp_name_count_initialized_p, make_temp_name): Remove.
(Ffileio__make_temp_file): New function.
(Fmake_temp_name): Use it.
* src/filelock.c (get_boot_time): Use Ffileio__make_temp_file
instead of make_temp_name; this avoids a race.
---
admin/CPP-DEFINES | 1 -
admin/merge-gnulib | 4 +-
configure.ac | 3 -
lib/gnulib.mk.in | 5 +-
lisp/files.el | 15 +++++
m4/gnulib-comp.m4 | 13 +---
src/buffer.c | 1 -
src/fileio.c | 170 ++++++++++++++---------------------------------------
src/filelock.c | 13 ++--
src/lisp.h | 1 -
10 files changed, 69 insertions(+), 157 deletions(-)
diff --git a/admin/CPP-DEFINES b/admin/CPP-DEFINES
index cead305aee..10b558d1ad 100644
--- a/admin/CPP-DEFINES
+++ b/admin/CPP-DEFINES
@@ -205,7 +205,6 @@ HAVE_LIBXML2
HAVE_LIBXMU
HAVE_LOCALTIME_R
HAVE_LOCAL_SOCKETS
-HAVE_LONG_FILE_NAMES
HAVE_LONG_LONG_INT
HAVE_LRAND48
HAVE_LSTAT
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index a16d7fa53e..7eca64305d 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -39,8 +39,8 @@ GNULIB_MODULES=
manywarnings memrchr minmax mkostemp mktime nstrftime
pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat
sig2str socklen stat-time std-gnu11 stdalign stddef stdio
- stpcpy strtoimax symlink sys_stat
- sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub
+ stpcpy strtoimax symlink sys_stat sys_time
+ tempname time time_r time_rz timegm timer-time timespec-add timespec-sub
update-copyright unlocked-io utimens
vla warnings
'
diff --git a/configure.ac b/configure.ac
index 9f80620a80..86d5b3e94f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1779,9 +1779,6 @@ AC_DEFUN
fi
AC_SUBST(AUTO_DEPEND)
-dnl checks for operating system services
-AC_SYS_LONG_FILE_NAMES
-
#### Choose a window system.
## We leave window_system equal to none if
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index c5df3f42e4..30986b4ed7 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -21,7 +21,7 @@
# the same distribution terms as the rest of that program.
#
# Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --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=setenv --avoid=sigprocmask --avoid=stat --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=tzset --avoid=unsetenv --avoid=utime --avoid=utime-h --gnu-make --makefile-name=gnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 d-type diffseq dtoastr dtotimespec dup2 environ execinfo explicit_bzero faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr minmax mkostemp mktime nstrftime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strtoimax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub unlocked-io update-copyright utimens vla warnings
+# Reproduce by: gnulib-tool --import --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=setenv --avoid=sigprocmask --avoid=stat --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=tzset --avoid=unsetenv --avoid=utime --avoid=utime-h --gnu-make --makefile-name=gnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 d-type diffseq dtoastr dtotimespec dup2 environ execinfo explicit_bzero faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr minmax mkostemp mktime nstrftime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strtoimax symlink sys_stat sys_time tempname time time_r time_rz timegm timer-time timespec-add timespec-sub unlocked-io update-copyright utimens vla warnings
MOSTLYCLEANFILES += core *.stackdump
@@ -904,7 +904,6 @@ gl_GNULIB_ENABLED_euidaccess = @gl_GNULIB_ENABLED_euidaccess@
gl_GNULIB_ENABLED_getdtablesize = @gl_GNULIB_ENABLED_getdtablesize@
gl_GNULIB_ENABLED_getgroups = @gl_GNULIB_ENABLED_getgroups@
gl_GNULIB_ENABLED_strtoll = @gl_GNULIB_ENABLED_strtoll@
-gl_GNULIB_ENABLED_tempname = @gl_GNULIB_ENABLED_tempname@
gl_LIBOBJS = @gl_LIBOBJS@
gl_LTLIBOBJS = @gl_LTLIBOBJS@
gltests_LIBOBJS = @gltests_LIBOBJS@
@@ -2701,10 +2700,8 @@ endif
## begin gnulib module tempname
ifeq (,$(OMIT_GNULIB_MODULE_tempname))
-ifneq (,$(gl_GNULIB_ENABLED_tempname))
libgnu_a_SOURCES += tempname.c
-endif
EXTRA_DIST += tempname.h
endif
diff --git a/lisp/files.el b/lisp/files.el
index f2758ab18c..3ed36d24db 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -1417,6 +1417,19 @@ make-temp-file
If DIR-FLAG is non-nil, create a new empty directory instead of a file.
If SUFFIX is non-nil, add that at the end of the file name."
+ (let ((absolute-prefix (expand-file-name prefix temporary-file-directory)))
+ ;; FIXME: Establish make-temp-file file name handlers,
+ ;; to create temporary files and directories without races.
+ ;; For now, if the prefix is magic, fall back on the traditional,
+ ;; insecure way to create temporary files.
+ (if (find-file-name-handler absolute-prefix 'write-region)
+ (files--make-magic-temp-file prefix dir-flag suffix)
+ (fileio--make-temp-file absolute-prefix
+ (if dir-flag t) (or suffix "")))))
+
+(defun files--make-magic-temp-file (prefix &optional dir-flag suffix)
+ "Implement (make-temp-file PREFIX DIR-FLAG SUFFIX),
+even if the result is a magic file name."
;; Create temp files with strict access rights. It's easy to
;; loosen them later, whereas it's impossible to close the
;; time-window of loose permissions otherwise.
@@ -1435,6 +1448,8 @@ make-temp-file
(setq file (concat file suffix)))
(if dir-flag
(make-directory file)
+ ;; FIXME: The 'excl is only aspirational; it is
+ ;; actually a no-op if FILE is a magic file name.
(write-region "" nil file nil 'silent nil 'excl))
nil)
(file-already-exists t))
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index 69d77229bf..d1089860e1 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -387,6 +387,7 @@ AC_DEFUN
AC_PROG_MKDIR_P
gl_SYS_TYPES_H
AC_PROG_MKDIR_P
+ gl_FUNC_GEN_TEMPNAME
gl_HEADER_TIME_H
gl_TIME_R
if test $HAVE_LOCALTIME_R = 0 || test $REPLACE_LOCALTIME_R = 1; then
@@ -424,7 +425,6 @@ AC_DEFUN
gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7=false
gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=false
gl_gnulib_enabled_strtoll=false
- gl_gnulib_enabled_tempname=false
gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec=false
func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b ()
{
@@ -560,13 +560,6 @@ AC_DEFUN
gl_gnulib_enabled_strtoll=true
fi
}
- func_gl_gnulib_m4code_tempname ()
- {
- if ! $gl_gnulib_enabled_tempname; then
- gl_FUNC_GEN_TEMPNAME
- gl_gnulib_enabled_tempname=true
- fi
- }
func_gl_gnulib_m4code_682e609604ccaac6be382e4ee3a4eaec ()
{
if ! $gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec; then
@@ -612,9 +605,6 @@ AC_DEFUN
if test $REPLACE_LSTAT = 1; then
func_gl_gnulib_m4code_dosname
fi
- if test $HAVE_MKOSTEMP = 0; then
- func_gl_gnulib_m4code_tempname
- fi
if test $HAVE_READLINKAT = 0; then
func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b
fi
@@ -644,7 +634,6 @@ AC_DEFUN
AM_CONDITIONAL([gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7], [$gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7])
AM_CONDITIONAL([gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c], [$gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c])
AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoll], [$gl_gnulib_enabled_strtoll])
- AM_CONDITIONAL([gl_GNULIB_ENABLED_tempname], [$gl_gnulib_enabled_tempname])
AM_CONDITIONAL([gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec], [$gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec])
# End of code from modules
m4_ifval(gl_LIBSOURCES_LIST, [
diff --git a/src/buffer.c b/src/buffer.c
index 0d0f43e937..2d508f35cf 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1085,7 +1085,6 @@ is first appended to NAME, to speed up finding a non-existent buffer. */)
genbase = name;
else
{
- /* Note fileio.c:make_temp_name does random differently. */
char number[sizeof "-999999"];
int i = XFASTINT (Frandom (make_number (999999)));
AUTO_STRING_WITH_LEN (lnumber, number, sprintf (number, "-%d", i));
diff --git a/src/fileio.c b/src/fileio.c
index 15845e3914..1ef9bfa82b 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -97,6 +97,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <allocator.h>
#include <careadlinkat.h>
#include <stat-time.h>
+#include <tempname.h>
#include <binary-io.h>
@@ -623,149 +624,67 @@ In Unix-syntax, this function just removes the final slash. */)
return val;
}
-static const char make_temp_name_tbl[64] =
-{
- 'A','B','C','D','E','F','G','H',
- 'I','J','K','L','M','N','O','P',
- 'Q','R','S','T','U','V','W','X',
- 'Y','Z','a','b','c','d','e','f',
- 'g','h','i','j','k','l','m','n',
- 'o','p','q','r','s','t','u','v',
- 'w','x','y','z','0','1','2','3',
- '4','5','6','7','8','9','-','_'
-};
-
-static unsigned make_temp_name_count, make_temp_name_count_initialized_p;
-
-/* Value is a temporary file name starting with PREFIX, a string.
+DEFUN ("fileio--make-temp-file", Ffileio__make_temp_file,
+ Sfileio__make_temp_file, 3, 3, 0,
+ doc: /* Generate a new file whose name starts with PREFIX, a string.
+Return the name of the generated file. If DIR-FLAG is zero, do not
+create the file, just its name. Otherwise, if DIR-FLAG is non-nil,
+create an empty directory. The file name should end in SUFFIX.
- The Emacs process number forms part of the result, so there is
- no danger of generating a name being used by another process.
- In addition, this function makes an attempt to choose a name
- which has no existing file. To make this work, PREFIX should be
- an absolute file name.
+Signal an error if the file could not be created.
- BASE64_P means add the pid as 3 characters in base64
- encoding. In this case, 6 characters will be added to PREFIX to
- form the file name. Otherwise, if Emacs is running on a system
- with long file names, add the pid as a decimal number.
-
- This function signals an error if no unique file name could be
- generated. */
-
-Lisp_Object
-make_temp_name (Lisp_Object prefix, bool base64_p)
+This function does not grok magic file names. */)
+ (Lisp_Object prefix, Lisp_Object dir_flag, Lisp_Object suffix)
{
- Lisp_Object val, encoded_prefix;
- ptrdiff_t len;
- printmax_t pid;
- char *p, *data;
- char pidbuf[INT_BUFSIZE_BOUND (printmax_t)];
- int pidlen;
-
- CHECK_STRING (prefix);
-
- /* VAL is created by adding 6 characters to PREFIX. The first
- three are the PID of this process, in base 64, and the second
- three are incremented if the file already exists. This ensures
- 262144 unique file names per PID per PREFIX. */
-
- pid = getpid ();
-
- if (base64_p)
- {
- pidbuf[0] = make_temp_name_tbl[pid & 63], pid >>= 6;
- pidbuf[1] = make_temp_name_tbl[pid & 63], pid >>= 6;
- pidbuf[2] = make_temp_name_tbl[pid & 63], pid >>= 6;
- pidlen = 3;
- }
- else
+ bool make_temp_name = EQ (dir_flag, make_number (0));
+ CHECK_STRING (suffix);
+ if (!make_temp_name)
+ prefix = Fexpand_file_name (prefix, Vtemporary_file_directory);
+
+ Lisp_Object encoded_prefix = ENCODE_FILE (prefix);
+ Lisp_Object encoded_suffix = ENCODE_FILE (suffix);
+ ptrdiff_t prefix_len = SBYTES (encoded_prefix);
+ ptrdiff_t suffix_len = SBYTES (encoded_suffix);
+ if (INT_MAX < suffix_len)
+ args_out_of_range (prefix, suffix);
+ int nX = 6;
+ Lisp_Object val = make_uninit_string (prefix_len + nX + suffix_len);
+ char *data = SSDATA (val);
+ memcpy (data, SSDATA (encoded_prefix), prefix_len);
+ memset (data + prefix_len, 'X', nX);
+ memcpy (data + prefix_len + nX, SSDATA (encoded_suffix), suffix_len);
+ int kind = (NILP (dir_flag) ? GT_FILE
+ : make_temp_name ? GT_NOCREATE
+ : GT_DIR);
+ int fd = gen_tempname (data, suffix_len, O_BINARY | O_CLOEXEC, kind);
+ if (fd < 0 || (NILP (dir_flag) && emacs_close (fd) != 0))
{
-#ifdef HAVE_LONG_FILE_NAMES
- pidlen = sprintf (pidbuf, "%"pMd, pid);
-#else
- pidbuf[0] = make_temp_name_tbl[pid & 63], pid >>= 6;
- pidbuf[1] = make_temp_name_tbl[pid & 63], pid >>= 6;
- pidbuf[2] = make_temp_name_tbl[pid & 63], pid >>= 6;
- pidlen = 3;
-#endif
- }
-
- encoded_prefix = ENCODE_FILE (prefix);
- len = SBYTES (encoded_prefix);
- val = make_uninit_string (len + 3 + pidlen);
- data = SSDATA (val);
- memcpy (data, SSDATA (encoded_prefix), len);
- p = data + len;
-
- memcpy (p, pidbuf, pidlen);
- p += pidlen;
-
- /* Here we try to minimize useless stat'ing when this function is
- invoked many times successively with the same PREFIX. We achieve
- this by initializing count to a random value, and incrementing it
- afterwards.
-
- We don't want make-temp-name to be called while dumping,
- because then make_temp_name_count_initialized_p would get set
- and then make_temp_name_count would not be set when Emacs starts. */
-
- if (!make_temp_name_count_initialized_p)
- {
- make_temp_name_count = time (NULL);
- make_temp_name_count_initialized_p = 1;
- }
-
- while (1)
- {
- unsigned num = make_temp_name_count;
-
- p[0] = make_temp_name_tbl[num & 63], num >>= 6;
- p[1] = make_temp_name_tbl[num & 63], num >>= 6;
- p[2] = make_temp_name_tbl[num & 63], num >>= 6;
-
- /* Poor man's congruential RN generator. Replace with
- ++make_temp_name_count for debugging. */
- make_temp_name_count += 25229;
- make_temp_name_count %= 225307;
-
- if (!check_existing (data))
+ static char const kind_message[][32] =
{
- /* We want to return only if errno is ENOENT. */
- if (errno == ENOENT)
- return DECODE_FILE (val);
- else
- /* The error here is dubious, but there is little else we
- can do. The alternatives are to return nil, which is
- as bad as (and in many cases worse than) throwing the
- error, or to ignore the error, which will likely result
- in looping through 225307 stat's, which is not only
- dog-slow, but also useless since eventually nil would
- have to be returned anyway. */
- report_file_error ("Cannot create temporary name for prefix",
- prefix);
- /* not reached */
- }
+ [GT_FILE] = "Creating file with prefix",
+ [GT_DIR] = "Creating directory with prefix",
+ [GT_NOCREATE] = "Creating file name with prefix"
+ };
+ report_file_error (kind_message[kind], prefix);
}
+ return DECODE_FILE (val);
}
DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0,
doc: /* Generate temporary file name (string) starting with PREFIX (a string).
-The Emacs process number forms part of the result, so there is no
-danger of generating a name being used by another Emacs process
-\(so long as only a single host can access the containing directory...).
This function tries to choose a name that has no existing file.
For this to work, PREFIX should be an absolute file name, and PREFIX
and the returned string should both be non-magic.
-There is a race condition between calling `make-temp-name' and creating the
-file, which opens all kinds of security holes. For that reason, you should
-normally use `make-temp-file' instead. */)
+There is a race condition between calling `make-temp-name' and
+later creating the file, which opens all kinds of security holes.
+For that reason, you should normally use `make-temp-file' instead. */)
(Lisp_Object prefix)
{
- return make_temp_name (prefix, 0);
+ return Ffileio__make_temp_file (prefix, make_number (0),
+ empty_unibyte_string);
}
DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
@@ -6167,6 +6086,7 @@ This includes interactive calls to `delete-file' and
defsubr (&Sunhandled_file_name_directory);
defsubr (&Sfile_name_as_directory);
defsubr (&Sdirectory_file_name);
+ defsubr (&Sfileio__make_temp_file);
defsubr (&Smake_temp_name);
defsubr (&Sexpand_file_name);
defsubr (&Ssubstitute_in_file_name);
diff --git a/src/filelock.c b/src/filelock.c
index dd8cb28c42..5614657985 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -206,14 +206,11 @@ get_boot_time (void)
WTMP_FILE, counter);
if (! NILP (Ffile_exists_p (tempname)))
{
- /* The utmp functions on mescaline.gnu.org accept only
- file names up to 8 characters long. Choose a 2
- character long prefix, and call make_temp_file with
- second arg non-zero, so that it will add not more
- than 6 characters to the prefix. */
- filename = Fexpand_file_name (build_string ("wt"),
- Vtemporary_file_directory);
- filename = make_temp_name (filename, 1);
+ /* The utmp functions on older systems accept only file
+ names up to 8 bytes long. Choose a 2 byte prefix, so
+ the 6-byte suffix does not make the name too long. */
+ filename = Ffileio__make_temp_file (build_string ("wt"), Qnil,
+ empty_unibyte_string);
CALLN (Fcall_process, build_string ("gzip"), Qnil,
list2 (QCfile, filename), Qnil,
build_string ("-cd"), tempname);
diff --git a/src/lisp.h b/src/lisp.h
index 4de6fc85ec..a65cc9684a 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4013,7 +4013,6 @@ extern bool file_directory_p (const char *);
extern bool file_accessible_directory_p (Lisp_Object);
extern void init_fileio (void);
extern void syms_of_fileio (void);
-extern Lisp_Object make_temp_name (Lisp_Object, bool);
/* Defined in search.c. */
extern void shrink_regexp_cache (void);
--
2.13.4
[-- Attachment #3: 0002-Remove-ms-w32-mkostemp.patch --]
[-- Type: text/x-patch, Size: 5692 bytes --]
From 130f81bd123de154be5247d3237610d1eeab5dca Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Wed, 9 Aug 2017 16:34:40 -0700
Subject: [PATCH 2/2] Remove ms-w32 mkostemp
* lib-src/ntlib.c, nt/inc/ms-w32.h, src/w32.c (mkostemp):
* nt/gnulib-cfg.mk (OMIT_GNULIB_MODULE_mkostemp):
* nt/mingw-cfg.site (ac_cv_func_mkostemp):
Remove, since the generic mkostemp should work on MS-Windows.
---
lib-src/ntlib.c | 56 -------------------------------------------------------
nt/gnulib-cfg.mk | 1 -
nt/inc/ms-w32.h | 2 --
nt/mingw-cfg.site | 1 -
src/w32.c | 55 ------------------------------------------------------
5 files changed, 115 deletions(-)
diff --git a/lib-src/ntlib.c b/lib-src/ntlib.c
index 78ba9061f6..078a43e79c 100644
--- a/lib-src/ntlib.c
+++ b/lib-src/ntlib.c
@@ -37,7 +37,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
char *sys_ctime (const time_t *);
FILE *sys_fopen (const char *, const char *);
int sys_chdir (const char *);
-int mkostemp (char *, int);
int sys_rename (const char *, const char *);
/* MinGW64 defines _TIMEZONE_DEFINED and defines 'struct timespec' in
@@ -396,61 +395,6 @@ lstat (const char * path, struct stat * buf)
return stat (path, buf);
}
-/* Implementation of mkostemp for MS-Windows, to avoid race conditions
- when using mktemp. Copied from w32.c.
-
- This is used only in update-game-score.c. It is overkill for that
- use case, since update-game-score renames the temporary file into
- the game score file, which isn't atomic on MS-Windows anyway, when
- the game score already existed before running the program, which it
- almost always does. But using a simpler implementation just to
- make a point is uneconomical... */
-
-int
-mkostemp (char * template, int flags)
-{
- char * p;
- int i, fd = -1;
- unsigned uid = GetCurrentThreadId ();
- int save_errno = errno;
- static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
-
- errno = EINVAL;
- if (template == NULL)
- return -1;
-
- p = template + strlen (template);
- i = 5;
- /* replace up to the last 5 X's with uid in decimal */
- while (--p >= template && p[0] == 'X' && --i >= 0)
- {
- p[0] = '0' + uid % 10;
- uid /= 10;
- }
-
- if (i < 0 && p[0] == 'X')
- {
- i = 0;
- do
- {
- p[0] = first_char[i];
- if ((fd = open (template,
- flags | _O_CREAT | _O_EXCL | _O_RDWR,
- S_IRUSR | S_IWUSR)) >= 0
- || errno != EEXIST)
- {
- if (fd >= 0)
- errno = save_errno;
- return fd;
- }
- }
- while (++i < sizeof (first_char));
- }
-
- /* Template is badly formed or else we can't generate a unique name. */
- return -1;
-}
-
/* On Windows, you cannot rename into an existing file. */
int
sys_rename (const char *from, const char *to)
diff --git a/nt/gnulib-cfg.mk b/nt/gnulib-cfg.mk
index 175329fb9e..ad798bbe37 100644
--- a/nt/gnulib-cfg.mk
+++ b/nt/gnulib-cfg.mk
@@ -50,7 +50,6 @@ OMIT_GNULIB_MODULE_dirfd =
OMIT_GNULIB_MODULE_fcntl = true
OMIT_GNULIB_MODULE_fcntl-h = true
OMIT_GNULIB_MODULE_inttypes-incomplete = true
-OMIT_GNULIB_MODULE_mkostemp = true
OMIT_GNULIB_MODULE_pipe2 = true
OMIT_GNULIB_MODULE_secure_getenv = true
OMIT_GNULIB_MODULE_signal-h = true
diff --git a/nt/inc/ms-w32.h b/nt/inc/ms-w32.h
index 957d8c6bdb..6cbbb9f869 100644
--- a/nt/inc/ms-w32.h
+++ b/nt/inc/ms-w32.h
@@ -518,8 +518,6 @@ extern int getpagesize (void);
extern void * memrchr (void const *, int, size_t);
-extern int mkostemp (char *, int);
-
#if defined (__MINGW32__)
diff --git a/nt/mingw-cfg.site b/nt/mingw-cfg.site
index a106717979..d9a824008c 100644
--- a/nt/mingw-cfg.site
+++ b/nt/mingw-cfg.site
@@ -79,7 +79,6 @@ ac_cv_func_getaddrinfo=yes
# Implemented as an inline function in ws2tcpip.h
ac_cv_func_gai_strerror=yes
# Implemented in w32.c
-ac_cv_func_mkostemp=yes
ac_cv_func_readlink=yes
ac_cv_func_symlink=yes
# Avoid run-time tests of readlink and symlink, which will fail
diff --git a/src/w32.c b/src/w32.c
index fa3cbe183f..1c58f92d57 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -4397,61 +4397,6 @@ sys_open (const char * path, int oflag, int mode)
return res;
}
-/* Implementation of mkostemp for MS-Windows, to avoid race conditions
- when using mktemp.
-
- Standard algorithm for generating a temporary file name seems to be
- use pid or tid with a letter on the front (in place of the 6 X's)
- and cycle through the letters to find a unique name. We extend
- that to allow any reasonable character as the first of the 6 X's,
- so that the number of simultaneously used temporary files will be
- greater. */
-
-int
-mkostemp (char * template, int flags)
-{
- char * p;
- int i, fd = -1;
- unsigned uid = GetCurrentThreadId ();
- int save_errno = errno;
- static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
-
- errno = EINVAL;
- if (template == NULL)
- return -1;
-
- p = template + strlen (template);
- i = 5;
- /* replace up to the last 5 X's with uid in decimal */
- while (--p >= template && p[0] == 'X' && --i >= 0)
- {
- p[0] = '0' + uid % 10;
- uid /= 10;
- }
-
- if (i < 0 && p[0] == 'X')
- {
- i = 0;
- do
- {
- p[0] = first_char[i];
- if ((fd = sys_open (template,
- flags | _O_CREAT | _O_EXCL | _O_RDWR,
- S_IRUSR | S_IWUSR)) >= 0
- || errno != EEXIST)
- {
- if (fd >= 0)
- errno = save_errno;
- return fd;
- }
- }
- while (++i < sizeof (first_char));
- }
-
- /* Template is badly formed or else we can't generate a unique name. */
- return -1;
-}
-
int
fchmod (int fd, mode_t mode)
{
--
2.13.4
next prev parent reply other threads:[~2017-08-09 23:36 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-08-09 5:38 bug#28023: fix make-temp-file race on local host Paul Eggert
2017-08-09 6:51 ` Michael Albinus
2017-08-09 9:22 ` Paul Eggert
2017-08-09 11:21 ` Michael Albinus
2017-08-13 7:21 ` Paul Eggert
2017-08-12 10:35 ` Michael Albinus
2017-08-12 15:55 ` Paul Eggert
2017-08-12 16:09 ` Eli Zaretskii
2017-08-12 16:25 ` Paul Eggert
2017-08-12 16:52 ` Eli Zaretskii
2017-08-12 17:57 ` Paul Eggert
2017-08-12 18:07 ` Eli Zaretskii
2017-08-12 17:51 ` Michael Albinus
2017-08-09 16:05 ` Eli Zaretskii
2017-08-09 18:47 ` Paul Eggert
2017-08-09 19:09 ` Eli Zaretskii
2017-08-09 23:36 ` Paul Eggert [this message]
2017-08-10 15:35 ` Eli Zaretskii
2017-08-10 22:24 ` Paul Eggert
2017-08-11 6:21 ` Eli Zaretskii
2017-08-11 7:44 ` Paul Eggert
2017-08-11 8:03 ` Eli Zaretskii
2017-08-12 8:31 ` Eli Zaretskii
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=704c73b8-54f1-f7ac-821b-6d715a21a8a2@cs.ucla.edu \
--to=eggert@cs.ucla.edu \
--cc=28023@debbugs.gnu.org \
--cc=eliz@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).