aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2017-08-12 14:00:17 -0700
committerPaul Eggert2017-08-12 15:14:45 -0700
commita6ad98ad66e1d0c0dac5f25ba91e11d0cf9da725 (patch)
tree183748df6a5b71f1b48deecc824eef27939ff2f8
parent9eb30cb03613ae158c870d603a05a6a6393dc485 (diff)
downloademacs-a6ad98ad66e1d0c0dac5f25ba91e11d0cf9da725.tar.gz
emacs-a6ad98ad66e1d0c0dac5f25ba91e11d0cf9da725.zip
Improve make-temp-file performance on local files
For the motivation behind this patch, please see Bug#28023 and: http://emacshorrors.com/posts/make-temp-name.html Although, given the recent changes to Tramp, the related security problem in make-temp-file is already fixed, make-temp-file still has several unnecessary system calls. In the typical case on GNU/Linux, this patch replaces 8 syscalls (symlink, open, close, readlinkat, uname, getpid, unlink, umask) by 2 (open, close). * 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. (make-temp-file): Use make-temp-file-internal for non-magic file 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. (Fmake_temp_file_internal): New function. (Fmake_temp_name): Use it. * src/filelock.c (get_boot_time): Use Fmake_temp_file_internal instead of make_temp_name.
-rw-r--r--admin/CPP-DEFINES1
-rwxr-xr-xadmin/merge-gnulib4
-rw-r--r--configure.ac3
-rw-r--r--lib/gnulib.mk.in5
-rw-r--r--lisp/files.el9
-rw-r--r--m4/gnulib-comp.m413
-rw-r--r--src/buffer.c1
-rw-r--r--src/fileio.c170
-rw-r--r--src/filelock.c13
-rw-r--r--src/lisp.h1
10 files changed, 63 insertions, 157 deletions
diff --git a/admin/CPP-DEFINES b/admin/CPP-DEFINES
index cead305aee1..10b558d1ada 100644
--- a/admin/CPP-DEFINES
+++ b/admin/CPP-DEFINES
@@ -205,7 +205,6 @@ HAVE_LIBXML2
205HAVE_LIBXMU 205HAVE_LIBXMU
206HAVE_LOCALTIME_R 206HAVE_LOCALTIME_R
207HAVE_LOCAL_SOCKETS 207HAVE_LOCAL_SOCKETS
208HAVE_LONG_FILE_NAMES
209HAVE_LONG_LONG_INT 208HAVE_LONG_LONG_INT
210HAVE_LRAND48 209HAVE_LRAND48
211HAVE_LSTAT 210HAVE_LSTAT
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index a16d7fa53ea..7eca64305de 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -39,8 +39,8 @@ GNULIB_MODULES='
39 manywarnings memrchr minmax mkostemp mktime nstrftime 39 manywarnings memrchr minmax mkostemp mktime nstrftime
40 pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat 40 pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat
41 sig2str socklen stat-time std-gnu11 stdalign stddef stdio 41 sig2str socklen stat-time std-gnu11 stdalign stddef stdio
42 stpcpy strtoimax symlink sys_stat 42 stpcpy strtoimax symlink sys_stat sys_time
43 sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub 43 tempname time time_r time_rz timegm timer-time timespec-add timespec-sub
44 update-copyright unlocked-io utimens 44 update-copyright unlocked-io utimens
45 vla warnings 45 vla warnings
46' 46'
diff --git a/configure.ac b/configure.ac
index 9f80620a807..86d5b3e94f9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1779,9 +1779,6 @@ if test "$GCC" = yes && test "$ac_enable_autodepend" = yes; then
1779fi 1779fi
1780AC_SUBST(AUTO_DEPEND) 1780AC_SUBST(AUTO_DEPEND)
1781 1781
1782dnl checks for operating system services
1783AC_SYS_LONG_FILE_NAMES
1784
1785#### Choose a window system. 1782#### Choose a window system.
1786 1783
1787## We leave window_system equal to none if 1784## We leave window_system equal to none if
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index c5df3f42e47..30986b4ed7f 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -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 --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 24# 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
25 25
26 26
27MOSTLYCLEANFILES += core *.stackdump 27MOSTLYCLEANFILES += core *.stackdump
@@ -904,7 +904,6 @@ gl_GNULIB_ENABLED_euidaccess = @gl_GNULIB_ENABLED_euidaccess@
904gl_GNULIB_ENABLED_getdtablesize = @gl_GNULIB_ENABLED_getdtablesize@ 904gl_GNULIB_ENABLED_getdtablesize = @gl_GNULIB_ENABLED_getdtablesize@
905gl_GNULIB_ENABLED_getgroups = @gl_GNULIB_ENABLED_getgroups@ 905gl_GNULIB_ENABLED_getgroups = @gl_GNULIB_ENABLED_getgroups@
906gl_GNULIB_ENABLED_strtoll = @gl_GNULIB_ENABLED_strtoll@ 906gl_GNULIB_ENABLED_strtoll = @gl_GNULIB_ENABLED_strtoll@
907gl_GNULIB_ENABLED_tempname = @gl_GNULIB_ENABLED_tempname@
908gl_LIBOBJS = @gl_LIBOBJS@ 907gl_LIBOBJS = @gl_LIBOBJS@
909gl_LTLIBOBJS = @gl_LTLIBOBJS@ 908gl_LTLIBOBJS = @gl_LTLIBOBJS@
910gltests_LIBOBJS = @gltests_LIBOBJS@ 909gltests_LIBOBJS = @gltests_LIBOBJS@
@@ -2701,10 +2700,8 @@ endif
2701## begin gnulib module tempname 2700## begin gnulib module tempname
2702ifeq (,$(OMIT_GNULIB_MODULE_tempname)) 2701ifeq (,$(OMIT_GNULIB_MODULE_tempname))
2703 2702
2704ifneq (,$(gl_GNULIB_ENABLED_tempname))
2705libgnu_a_SOURCES += tempname.c 2703libgnu_a_SOURCES += tempname.c
2706 2704
2707endif
2708EXTRA_DIST += tempname.h 2705EXTRA_DIST += tempname.h
2709 2706
2710endif 2707endif
diff --git a/lisp/files.el b/lisp/files.el
index 0fe7f9c522a..19573cdf7b2 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -1407,6 +1407,15 @@ You can then use `write-region' to write new data into the file.
1407If DIR-FLAG is non-nil, create a new empty directory instead of a file. 1407If DIR-FLAG is non-nil, create a new empty directory instead of a file.
1408 1408
1409If SUFFIX is non-nil, add that at the end of the file name." 1409If SUFFIX is non-nil, add that at the end of the file name."
1410 (let ((absolute-prefix (expand-file-name prefix temporary-file-directory)))
1411 (if (find-file-name-handler absolute-prefix 'write-region)
1412 (files--make-magic-temp-file prefix dir-flag suffix)
1413 (make-temp-file-internal absolute-prefix
1414 (if dir-flag t) (or suffix "")))))
1415
1416(defun files--make-magic-temp-file (prefix &optional dir-flag suffix)
1417 "Implement (make-temp-file PREFIX DIR-FLAG SUFFIX).
1418This implementation works on magic file names."
1410 ;; Create temp files with strict access rights. It's easy to 1419 ;; Create temp files with strict access rights. It's easy to
1411 ;; loosen them later, whereas it's impossible to close the 1420 ;; loosen them later, whereas it's impossible to close the
1412 ;; time-window of loose permissions otherwise. 1421 ;; time-window of loose permissions otherwise.
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index 69d77229bf7..d1089860e19 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -387,6 +387,7 @@ AC_DEFUN([gl_INIT],
387 AC_PROG_MKDIR_P 387 AC_PROG_MKDIR_P
388 gl_SYS_TYPES_H 388 gl_SYS_TYPES_H
389 AC_PROG_MKDIR_P 389 AC_PROG_MKDIR_P
390 gl_FUNC_GEN_TEMPNAME
390 gl_HEADER_TIME_H 391 gl_HEADER_TIME_H
391 gl_TIME_R 392 gl_TIME_R
392 if test $HAVE_LOCALTIME_R = 0 || test $REPLACE_LOCALTIME_R = 1; then 393 if test $HAVE_LOCALTIME_R = 0 || test $REPLACE_LOCALTIME_R = 1; then
@@ -424,7 +425,6 @@ AC_DEFUN([gl_INIT],
424 gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7=false 425 gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7=false
425 gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=false 426 gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=false
426 gl_gnulib_enabled_strtoll=false 427 gl_gnulib_enabled_strtoll=false
427 gl_gnulib_enabled_tempname=false
428 gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec=false 428 gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec=false
429 func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b () 429 func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b ()
430 { 430 {
@@ -560,13 +560,6 @@ AC_DEFUN([gl_INIT],
560 gl_gnulib_enabled_strtoll=true 560 gl_gnulib_enabled_strtoll=true
561 fi 561 fi
562 } 562 }
563 func_gl_gnulib_m4code_tempname ()
564 {
565 if ! $gl_gnulib_enabled_tempname; then
566 gl_FUNC_GEN_TEMPNAME
567 gl_gnulib_enabled_tempname=true
568 fi
569 }
570 func_gl_gnulib_m4code_682e609604ccaac6be382e4ee3a4eaec () 563 func_gl_gnulib_m4code_682e609604ccaac6be382e4ee3a4eaec ()
571 { 564 {
572 if ! $gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec; then 565 if ! $gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec; then
@@ -612,9 +605,6 @@ AC_DEFUN([gl_INIT],
612 if test $REPLACE_LSTAT = 1; then 605 if test $REPLACE_LSTAT = 1; then
613 func_gl_gnulib_m4code_dosname 606 func_gl_gnulib_m4code_dosname
614 fi 607 fi
615 if test $HAVE_MKOSTEMP = 0; then
616 func_gl_gnulib_m4code_tempname
617 fi
618 if test $HAVE_READLINKAT = 0; then 608 if test $HAVE_READLINKAT = 0; then
619 func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b 609 func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b
620 fi 610 fi
@@ -644,7 +634,6 @@ AC_DEFUN([gl_INIT],
644 AM_CONDITIONAL([gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7], [$gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7]) 634 AM_CONDITIONAL([gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7], [$gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7])
645 AM_CONDITIONAL([gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c], [$gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c]) 635 AM_CONDITIONAL([gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c], [$gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c])
646 AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoll], [$gl_gnulib_enabled_strtoll]) 636 AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoll], [$gl_gnulib_enabled_strtoll])
647 AM_CONDITIONAL([gl_GNULIB_ENABLED_tempname], [$gl_gnulib_enabled_tempname])
648 AM_CONDITIONAL([gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec], [$gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec]) 637 AM_CONDITIONAL([gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec], [$gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec])
649 # End of code from modules 638 # End of code from modules
650 m4_ifval(gl_LIBSOURCES_LIST, [ 639 m4_ifval(gl_LIBSOURCES_LIST, [
diff --git a/src/buffer.c b/src/buffer.c
index 0d0f43e937b..2d508f35cf6 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. */)
1085 genbase = name; 1085 genbase = name;
1086 else 1086 else
1087 { 1087 {
1088 /* Note fileio.c:make_temp_name does random differently. */
1089 char number[sizeof "-999999"]; 1088 char number[sizeof "-999999"];
1090 int i = XFASTINT (Frandom (make_number (999999))); 1089 int i = XFASTINT (Frandom (make_number (999999)));
1091 AUTO_STRING_WITH_LEN (lnumber, number, sprintf (number, "-%d", i)); 1090 AUTO_STRING_WITH_LEN (lnumber, number, sprintf (number, "-%d", i));
diff --git a/src/fileio.c b/src/fileio.c
index 31fd84512e1..b7e3b71a475 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/>. */
97#include <allocator.h> 97#include <allocator.h>
98#include <careadlinkat.h> 98#include <careadlinkat.h>
99#include <stat-time.h> 99#include <stat-time.h>
100#include <tempname.h>
100 101
101#include <binary-io.h> 102#include <binary-io.h>
102 103
@@ -655,149 +656,67 @@ In Unix-syntax, this function just removes the final slash. */)
655 return val; 656 return val;
656} 657}
657 658
658static const char make_temp_name_tbl[64] = 659DEFUN ("make-temp-file-internal", Fmake_temp_file_internal,
659{ 660 Smake_temp_file_internal, 3, 3, 0,
660 'A','B','C','D','E','F','G','H', 661 doc: /* Generate a new file whose name starts with PREFIX, a string.
661 'I','J','K','L','M','N','O','P', 662Return the name of the generated file. If DIR-FLAG is zero, do not
662 'Q','R','S','T','U','V','W','X', 663create the file, just its name. Otherwise, if DIR-FLAG is non-nil,
663 'Y','Z','a','b','c','d','e','f', 664create an empty directory. The file name should end in SUFFIX.
664 'g','h','i','j','k','l','m','n',
665 'o','p','q','r','s','t','u','v',
666 'w','x','y','z','0','1','2','3',
667 '4','5','6','7','8','9','-','_'
668};
669
670static unsigned make_temp_name_count, make_temp_name_count_initialized_p;
671
672/* Value is a temporary file name starting with PREFIX, a string.
673 665
674 The Emacs process number forms part of the result, so there is 666Signal an error if the file could not be created.
675 no danger of generating a name being used by another process.
676 In addition, this function makes an attempt to choose a name
677 which has no existing file. To make this work, PREFIX should be
678 an absolute file name.
679 667
680 BASE64_P means add the pid as 3 characters in base64 668This function does not grok magic file names. */)
681 encoding. In this case, 6 characters will be added to PREFIX to 669 (Lisp_Object prefix, Lisp_Object dir_flag, Lisp_Object suffix)
682 form the file name. Otherwise, if Emacs is running on a system
683 with long file names, add the pid as a decimal number.
684
685 This function signals an error if no unique file name could be
686 generated. */
687
688Lisp_Object
689make_temp_name (Lisp_Object prefix, bool base64_p)
690{ 670{
691 Lisp_Object val, encoded_prefix; 671 bool make_temp_name = EQ (dir_flag, make_number (0));
692 ptrdiff_t len; 672 CHECK_STRING (suffix);
693 printmax_t pid; 673 if (!make_temp_name)
694 char *p, *data; 674 prefix = Fexpand_file_name (prefix, Vtemporary_file_directory);
695 char pidbuf[INT_BUFSIZE_BOUND (printmax_t)]; 675
696 int pidlen; 676 Lisp_Object encoded_prefix = ENCODE_FILE (prefix);
697 677 Lisp_Object encoded_suffix = ENCODE_FILE (suffix);
698 CHECK_STRING (prefix); 678 ptrdiff_t prefix_len = SBYTES (encoded_prefix);
699 679 ptrdiff_t suffix_len = SBYTES (encoded_suffix);
700 /* VAL is created by adding 6 characters to PREFIX. The first 680 if (INT_MAX < suffix_len)
701 three are the PID of this process, in base 64, and the second 681 args_out_of_range (prefix, suffix);
702 three are incremented if the file already exists. This ensures 682 int nX = 6;
703 262144 unique file names per PID per PREFIX. */ 683 Lisp_Object val = make_uninit_string (prefix_len + nX + suffix_len);
704 684 char *data = SSDATA (val);
705 pid = getpid (); 685 memcpy (data, SSDATA (encoded_prefix), prefix_len);
706 686 memset (data + prefix_len, 'X', nX);
707 if (base64_p) 687 memcpy (data + prefix_len + nX, SSDATA (encoded_suffix), suffix_len);
708 { 688 int kind = (NILP (dir_flag) ? GT_FILE
709 pidbuf[0] = make_temp_name_tbl[pid & 63], pid >>= 6; 689 : make_temp_name ? GT_NOCREATE
710 pidbuf[1] = make_temp_name_tbl[pid & 63], pid >>= 6; 690 : GT_DIR);
711 pidbuf[2] = make_temp_name_tbl[pid & 63], pid >>= 6; 691 int fd = gen_tempname (data, suffix_len, O_BINARY | O_CLOEXEC, kind);
712 pidlen = 3; 692 if (fd < 0 || (NILP (dir_flag) && emacs_close (fd) != 0))
713 }
714 else
715 { 693 {
716#ifdef HAVE_LONG_FILE_NAMES 694 static char const kind_message[][32] =
717 pidlen = sprintf (pidbuf, "%"pMd, pid);
718#else
719 pidbuf[0] = make_temp_name_tbl[pid & 63], pid >>= 6;
720 pidbuf[1] = make_temp_name_tbl[pid & 63], pid >>= 6;
721 pidbuf[2] = make_temp_name_tbl[pid & 63], pid >>= 6;
722 pidlen = 3;
723#endif
724 }
725
726 encoded_prefix = ENCODE_FILE (prefix);
727 len = SBYTES (encoded_prefix);
728 val = make_uninit_string (len + 3 + pidlen);
729 data = SSDATA (val);
730 memcpy (data, SSDATA (encoded_prefix), len);
731 p = data + len;
732
733 memcpy (p, pidbuf, pidlen);
734 p += pidlen;
735
736 /* Here we try to minimize useless stat'ing when this function is
737 invoked many times successively with the same PREFIX. We achieve
738 this by initializing count to a random value, and incrementing it
739 afterwards.
740
741 We don't want make-temp-name to be called while dumping,
742 because then make_temp_name_count_initialized_p would get set
743 and then make_temp_name_count would not be set when Emacs starts. */
744
745 if (!make_temp_name_count_initialized_p)
746 {
747 make_temp_name_count = time (NULL);
748 make_temp_name_count_initialized_p = 1;
749 }
750
751 while (1)
752 {
753 unsigned num = make_temp_name_count;
754
755 p[0] = make_temp_name_tbl[num & 63], num >>= 6;
756 p[1] = make_temp_name_tbl[num & 63], num >>= 6;
757 p[2] = make_temp_name_tbl[num & 63], num >>= 6;
758
759 /* Poor man's congruential RN generator. Replace with
760 ++make_temp_name_count for debugging. */
761 make_temp_name_count += 25229;
762 make_temp_name_count %= 225307;
763
764 if (!check_existing (data))
765 { 695 {
766 /* We want to return only if errno is ENOENT. */ 696 [GT_FILE] = "Creating file with prefix",
767 if (errno == ENOENT) 697 [GT_DIR] = "Creating directory with prefix",
768 return DECODE_FILE (val); 698 [GT_NOCREATE] = "Creating file name with prefix"
769 else 699 };
770 /* The error here is dubious, but there is little else we 700 report_file_error (kind_message[kind], prefix);
771 can do. The alternatives are to return nil, which is
772 as bad as (and in many cases worse than) throwing the
773 error, or to ignore the error, which will likely result
774 in looping through 225307 stat's, which is not only
775 dog-slow, but also useless since eventually nil would
776 have to be returned anyway. */
777 report_file_error ("Cannot create temporary name for prefix",
778 prefix);
779 /* not reached */
780 }
781 } 701 }
702 return DECODE_FILE (val);
782} 703}
783 704
784 705
785DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0, 706DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0,
786 doc: /* Generate temporary file name (string) starting with PREFIX (a string). 707 doc: /* Generate temporary file name (string) starting with PREFIX (a string).
787The Emacs process number forms part of the result, so there is no
788danger of generating a name being used by another Emacs process
789\(so long as only a single host can access the containing directory...).
790 708
791This function tries to choose a name that has no existing file. 709This function tries to choose a name that has no existing file.
792For this to work, PREFIX should be an absolute file name, and PREFIX 710For this to work, PREFIX should be an absolute file name, and PREFIX
793and the returned string should both be non-magic. 711and the returned string should both be non-magic.
794 712
795There is a race condition between calling `make-temp-name' and creating the 713There is a race condition between calling `make-temp-name' and
796file, which opens all kinds of security holes. For that reason, you should 714later creating the file, which opens all kinds of security holes.
797normally use `make-temp-file' instead. */) 715For that reason, you should normally use `make-temp-file' instead. */)
798 (Lisp_Object prefix) 716 (Lisp_Object prefix)
799{ 717{
800 return make_temp_name (prefix, 0); 718 return Fmake_temp_file_internal (prefix, make_number (0),
719 empty_unibyte_string);
801} 720}
802 721
803DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0, 722DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
@@ -6168,6 +6087,7 @@ This includes interactive calls to `delete-file' and
6168 defsubr (&Sfile_name_as_directory); 6087 defsubr (&Sfile_name_as_directory);
6169 defsubr (&Sdirectory_name_p); 6088 defsubr (&Sdirectory_name_p);
6170 defsubr (&Sdirectory_file_name); 6089 defsubr (&Sdirectory_file_name);
6090 defsubr (&Smake_temp_file_internal);
6171 defsubr (&Smake_temp_name); 6091 defsubr (&Smake_temp_name);
6172 defsubr (&Sexpand_file_name); 6092 defsubr (&Sexpand_file_name);
6173 defsubr (&Ssubstitute_in_file_name); 6093 defsubr (&Ssubstitute_in_file_name);
diff --git a/src/filelock.c b/src/filelock.c
index dd8cb28c425..3d6941695ae 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -206,14 +206,11 @@ get_boot_time (void)
206 WTMP_FILE, counter); 206 WTMP_FILE, counter);
207 if (! NILP (Ffile_exists_p (tempname))) 207 if (! NILP (Ffile_exists_p (tempname)))
208 { 208 {
209 /* The utmp functions on mescaline.gnu.org accept only 209 /* The utmp functions on older systems accept only file
210 file names up to 8 characters long. Choose a 2 210 names up to 8 bytes long. Choose a 2 byte prefix, so
211 character long prefix, and call make_temp_file with 211 the 6-byte suffix does not make the name too long. */
212 second arg non-zero, so that it will add not more 212 filename = Fmake_temp_file_internal (build_string ("wt"), Qnil,
213 than 6 characters to the prefix. */ 213 empty_unibyte_string);
214 filename = Fexpand_file_name (build_string ("wt"),
215 Vtemporary_file_directory);
216 filename = make_temp_name (filename, 1);
217 CALLN (Fcall_process, build_string ("gzip"), Qnil, 214 CALLN (Fcall_process, build_string ("gzip"), Qnil,
218 list2 (QCfile, filename), Qnil, 215 list2 (QCfile, filename), Qnil,
219 build_string ("-cd"), tempname); 216 build_string ("-cd"), tempname);
diff --git a/src/lisp.h b/src/lisp.h
index 25be5c0ceea..48cf3b30709 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4014,7 +4014,6 @@ extern bool file_directory_p (const char *);
4014extern bool file_accessible_directory_p (Lisp_Object); 4014extern bool file_accessible_directory_p (Lisp_Object);
4015extern void init_fileio (void); 4015extern void init_fileio (void);
4016extern void syms_of_fileio (void); 4016extern void syms_of_fileio (void);
4017extern Lisp_Object make_temp_name (Lisp_Object, bool);
4018 4017
4019/* Defined in search.c. */ 4018/* Defined in search.c. */
4020extern void shrink_regexp_cache (void); 4019extern void shrink_regexp_cache (void);