mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 09:14:18 +00:00
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.
This commit is contained in:
parent
9eb30cb036
commit
a6ad98ad66
10 changed files with 64 additions and 158 deletions
|
|
@ -205,7 +205,6 @@ HAVE_LIBXML2
|
||||||
HAVE_LIBXMU
|
HAVE_LIBXMU
|
||||||
HAVE_LOCALTIME_R
|
HAVE_LOCALTIME_R
|
||||||
HAVE_LOCAL_SOCKETS
|
HAVE_LOCAL_SOCKETS
|
||||||
HAVE_LONG_FILE_NAMES
|
|
||||||
HAVE_LONG_LONG_INT
|
HAVE_LONG_LONG_INT
|
||||||
HAVE_LRAND48
|
HAVE_LRAND48
|
||||||
HAVE_LSTAT
|
HAVE_LSTAT
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,8 @@ GNULIB_MODULES='
|
||||||
manywarnings memrchr minmax mkostemp mktime nstrftime
|
manywarnings memrchr minmax mkostemp mktime nstrftime
|
||||||
pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat
|
pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat
|
||||||
sig2str socklen stat-time std-gnu11 stdalign stddef stdio
|
sig2str socklen stat-time std-gnu11 stdalign stddef stdio
|
||||||
stpcpy strtoimax symlink sys_stat
|
stpcpy strtoimax symlink sys_stat sys_time
|
||||||
sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub
|
tempname time time_r time_rz timegm timer-time timespec-add timespec-sub
|
||||||
update-copyright unlocked-io utimens
|
update-copyright unlocked-io utimens
|
||||||
vla warnings
|
vla warnings
|
||||||
'
|
'
|
||||||
|
|
|
||||||
|
|
@ -1779,9 +1779,6 @@ if test "$GCC" = yes && test "$ac_enable_autodepend" = yes; then
|
||||||
fi
|
fi
|
||||||
AC_SUBST(AUTO_DEPEND)
|
AC_SUBST(AUTO_DEPEND)
|
||||||
|
|
||||||
dnl checks for operating system services
|
|
||||||
AC_SYS_LONG_FILE_NAMES
|
|
||||||
|
|
||||||
#### Choose a window system.
|
#### Choose a window system.
|
||||||
|
|
||||||
## We leave window_system equal to none if
|
## We leave window_system equal to none if
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
# the same distribution terms as the rest of that program.
|
# the same distribution terms as the rest of that program.
|
||||||
#
|
#
|
||||||
# Generated by gnulib-tool.
|
# 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
|
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_getdtablesize = @gl_GNULIB_ENABLED_getdtablesize@
|
||||||
gl_GNULIB_ENABLED_getgroups = @gl_GNULIB_ENABLED_getgroups@
|
gl_GNULIB_ENABLED_getgroups = @gl_GNULIB_ENABLED_getgroups@
|
||||||
gl_GNULIB_ENABLED_strtoll = @gl_GNULIB_ENABLED_strtoll@
|
gl_GNULIB_ENABLED_strtoll = @gl_GNULIB_ENABLED_strtoll@
|
||||||
gl_GNULIB_ENABLED_tempname = @gl_GNULIB_ENABLED_tempname@
|
|
||||||
gl_LIBOBJS = @gl_LIBOBJS@
|
gl_LIBOBJS = @gl_LIBOBJS@
|
||||||
gl_LTLIBOBJS = @gl_LTLIBOBJS@
|
gl_LTLIBOBJS = @gl_LTLIBOBJS@
|
||||||
gltests_LIBOBJS = @gltests_LIBOBJS@
|
gltests_LIBOBJS = @gltests_LIBOBJS@
|
||||||
|
|
@ -2701,10 +2700,8 @@ endif
|
||||||
## begin gnulib module tempname
|
## begin gnulib module tempname
|
||||||
ifeq (,$(OMIT_GNULIB_MODULE_tempname))
|
ifeq (,$(OMIT_GNULIB_MODULE_tempname))
|
||||||
|
|
||||||
ifneq (,$(gl_GNULIB_ENABLED_tempname))
|
|
||||||
libgnu_a_SOURCES += tempname.c
|
libgnu_a_SOURCES += tempname.c
|
||||||
|
|
||||||
endif
|
|
||||||
EXTRA_DIST += tempname.h
|
EXTRA_DIST += tempname.h
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
|
|
@ -1407,6 +1407,15 @@ You can then use `write-region' to write new data into the file.
|
||||||
If DIR-FLAG is non-nil, create a new empty directory instead of a 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."
|
If SUFFIX is non-nil, add that at the end of the file name."
|
||||||
|
(let ((absolute-prefix (expand-file-name prefix temporary-file-directory)))
|
||||||
|
(if (find-file-name-handler absolute-prefix 'write-region)
|
||||||
|
(files--make-magic-temp-file prefix dir-flag suffix)
|
||||||
|
(make-temp-file-internal 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).
|
||||||
|
This implementation works on magic file names."
|
||||||
;; Create temp files with strict access rights. It's easy to
|
;; Create temp files with strict access rights. It's easy to
|
||||||
;; loosen them later, whereas it's impossible to close the
|
;; loosen them later, whereas it's impossible to close the
|
||||||
;; time-window of loose permissions otherwise.
|
;; time-window of loose permissions otherwise.
|
||||||
|
|
|
||||||
|
|
@ -387,6 +387,7 @@ AC_DEFUN([gl_INIT],
|
||||||
AC_PROG_MKDIR_P
|
AC_PROG_MKDIR_P
|
||||||
gl_SYS_TYPES_H
|
gl_SYS_TYPES_H
|
||||||
AC_PROG_MKDIR_P
|
AC_PROG_MKDIR_P
|
||||||
|
gl_FUNC_GEN_TEMPNAME
|
||||||
gl_HEADER_TIME_H
|
gl_HEADER_TIME_H
|
||||||
gl_TIME_R
|
gl_TIME_R
|
||||||
if test $HAVE_LOCALTIME_R = 0 || test $REPLACE_LOCALTIME_R = 1; then
|
if test $HAVE_LOCALTIME_R = 0 || test $REPLACE_LOCALTIME_R = 1; then
|
||||||
|
|
@ -424,7 +425,6 @@ AC_DEFUN([gl_INIT],
|
||||||
gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7=false
|
gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7=false
|
||||||
gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=false
|
gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=false
|
||||||
gl_gnulib_enabled_strtoll=false
|
gl_gnulib_enabled_strtoll=false
|
||||||
gl_gnulib_enabled_tempname=false
|
|
||||||
gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec=false
|
gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec=false
|
||||||
func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b ()
|
func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b ()
|
||||||
{
|
{
|
||||||
|
|
@ -560,13 +560,6 @@ AC_DEFUN([gl_INIT],
|
||||||
gl_gnulib_enabled_strtoll=true
|
gl_gnulib_enabled_strtoll=true
|
||||||
fi
|
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 ()
|
func_gl_gnulib_m4code_682e609604ccaac6be382e4ee3a4eaec ()
|
||||||
{
|
{
|
||||||
if ! $gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec; then
|
if ! $gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec; then
|
||||||
|
|
@ -612,9 +605,6 @@ AC_DEFUN([gl_INIT],
|
||||||
if test $REPLACE_LSTAT = 1; then
|
if test $REPLACE_LSTAT = 1; then
|
||||||
func_gl_gnulib_m4code_dosname
|
func_gl_gnulib_m4code_dosname
|
||||||
fi
|
fi
|
||||||
if test $HAVE_MKOSTEMP = 0; then
|
|
||||||
func_gl_gnulib_m4code_tempname
|
|
||||||
fi
|
|
||||||
if test $HAVE_READLINKAT = 0; then
|
if test $HAVE_READLINKAT = 0; then
|
||||||
func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b
|
func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b
|
||||||
fi
|
fi
|
||||||
|
|
@ -644,7 +634,6 @@ AC_DEFUN([gl_INIT],
|
||||||
AM_CONDITIONAL([gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7], [$gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7])
|
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_6099e9737f757db36c47fa9d9f02e88c], [$gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c])
|
||||||
AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoll], [$gl_gnulib_enabled_strtoll])
|
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])
|
AM_CONDITIONAL([gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec], [$gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec])
|
||||||
# End of code from modules
|
# End of code from modules
|
||||||
m4_ifval(gl_LIBSOURCES_LIST, [
|
m4_ifval(gl_LIBSOURCES_LIST, [
|
||||||
|
|
|
||||||
|
|
@ -1085,7 +1085,6 @@ is first appended to NAME, to speed up finding a non-existent buffer. */)
|
||||||
genbase = name;
|
genbase = name;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Note fileio.c:make_temp_name does random differently. */
|
|
||||||
char number[sizeof "-999999"];
|
char number[sizeof "-999999"];
|
||||||
int i = XFASTINT (Frandom (make_number (999999)));
|
int i = XFASTINT (Frandom (make_number (999999)));
|
||||||
AUTO_STRING_WITH_LEN (lnumber, number, sprintf (number, "-%d", i));
|
AUTO_STRING_WITH_LEN (lnumber, number, sprintf (number, "-%d", i));
|
||||||
|
|
|
||||||
172
src/fileio.c
172
src/fileio.c
|
|
@ -97,6 +97,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
#include <allocator.h>
|
#include <allocator.h>
|
||||||
#include <careadlinkat.h>
|
#include <careadlinkat.h>
|
||||||
#include <stat-time.h>
|
#include <stat-time.h>
|
||||||
|
#include <tempname.h>
|
||||||
|
|
||||||
#include <binary-io.h>
|
#include <binary-io.h>
|
||||||
|
|
||||||
|
|
@ -655,149 +656,67 @@ In Unix-syntax, this function just removes the final slash. */)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char make_temp_name_tbl[64] =
|
DEFUN ("make-temp-file-internal", Fmake_temp_file_internal,
|
||||||
|
Smake_temp_file_internal, 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.
|
||||||
|
|
||||||
|
Signal an error if the file could not be created.
|
||||||
|
|
||||||
|
This function does not grok magic file names. */)
|
||||||
|
(Lisp_Object prefix, Lisp_Object dir_flag, Lisp_Object suffix)
|
||||||
{
|
{
|
||||||
'A','B','C','D','E','F','G','H',
|
bool make_temp_name = EQ (dir_flag, make_number (0));
|
||||||
'I','J','K','L','M','N','O','P',
|
CHECK_STRING (suffix);
|
||||||
'Q','R','S','T','U','V','W','X',
|
if (!make_temp_name)
|
||||||
'Y','Z','a','b','c','d','e','f',
|
prefix = Fexpand_file_name (prefix, Vtemporary_file_directory);
|
||||||
'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;
|
Lisp_Object encoded_prefix = ENCODE_FILE (prefix);
|
||||||
|
Lisp_Object encoded_suffix = ENCODE_FILE (suffix);
|
||||||
/* Value is a temporary file name starting with PREFIX, a string.
|
ptrdiff_t prefix_len = SBYTES (encoded_prefix);
|
||||||
|
ptrdiff_t suffix_len = SBYTES (encoded_suffix);
|
||||||
The Emacs process number forms part of the result, so there is
|
if (INT_MAX < suffix_len)
|
||||||
no danger of generating a name being used by another process.
|
args_out_of_range (prefix, suffix);
|
||||||
In addition, this function makes an attempt to choose a name
|
int nX = 6;
|
||||||
which has no existing file. To make this work, PREFIX should be
|
Lisp_Object val = make_uninit_string (prefix_len + nX + suffix_len);
|
||||||
an absolute file name.
|
char *data = SSDATA (val);
|
||||||
|
memcpy (data, SSDATA (encoded_prefix), prefix_len);
|
||||||
BASE64_P means add the pid as 3 characters in base64
|
memset (data + prefix_len, 'X', nX);
|
||||||
encoding. In this case, 6 characters will be added to PREFIX to
|
memcpy (data + prefix_len + nX, SSDATA (encoded_suffix), suffix_len);
|
||||||
form the file name. Otherwise, if Emacs is running on a system
|
int kind = (NILP (dir_flag) ? GT_FILE
|
||||||
with long file names, add the pid as a decimal number.
|
: make_temp_name ? GT_NOCREATE
|
||||||
|
: GT_DIR);
|
||||||
This function signals an error if no unique file name could be
|
int fd = gen_tempname (data, suffix_len, O_BINARY | O_CLOEXEC, kind);
|
||||||
generated. */
|
if (fd < 0 || (NILP (dir_flag) && emacs_close (fd) != 0))
|
||||||
|
|
||||||
Lisp_Object
|
|
||||||
make_temp_name (Lisp_Object prefix, bool base64_p)
|
|
||||||
{
|
|
||||||
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;
|
static char const kind_message[][32] =
|
||||||
pidbuf[1] = make_temp_name_tbl[pid & 63], pid >>= 6;
|
|
||||||
pidbuf[2] = make_temp_name_tbl[pid & 63], pid >>= 6;
|
|
||||||
pidlen = 3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#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))
|
|
||||||
{
|
{
|
||||||
/* We want to return only if errno is ENOENT. */
|
[GT_FILE] = "Creating file with prefix",
|
||||||
if (errno == ENOENT)
|
[GT_DIR] = "Creating directory with prefix",
|
||||||
return DECODE_FILE (val);
|
[GT_NOCREATE] = "Creating file name with prefix"
|
||||||
else
|
};
|
||||||
/* The error here is dubious, but there is little else we
|
report_file_error (kind_message[kind], prefix);
|
||||||
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 */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return DECODE_FILE (val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0,
|
DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0,
|
||||||
doc: /* Generate temporary file name (string) starting with PREFIX (a string).
|
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.
|
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
|
For this to work, PREFIX should be an absolute file name, and PREFIX
|
||||||
and the returned string should both be non-magic.
|
and the returned string should both be non-magic.
|
||||||
|
|
||||||
There is a race condition between calling `make-temp-name' and creating the
|
There is a race condition between calling `make-temp-name' and
|
||||||
file, which opens all kinds of security holes. For that reason, you should
|
later creating the file, which opens all kinds of security holes.
|
||||||
normally use `make-temp-file' instead. */)
|
For that reason, you should normally use `make-temp-file' instead. */)
|
||||||
(Lisp_Object prefix)
|
(Lisp_Object prefix)
|
||||||
{
|
{
|
||||||
return make_temp_name (prefix, 0);
|
return Fmake_temp_file_internal (prefix, make_number (0),
|
||||||
|
empty_unibyte_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
|
DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
|
||||||
|
|
@ -6168,6 +6087,7 @@ This includes interactive calls to `delete-file' and
|
||||||
defsubr (&Sfile_name_as_directory);
|
defsubr (&Sfile_name_as_directory);
|
||||||
defsubr (&Sdirectory_name_p);
|
defsubr (&Sdirectory_name_p);
|
||||||
defsubr (&Sdirectory_file_name);
|
defsubr (&Sdirectory_file_name);
|
||||||
|
defsubr (&Smake_temp_file_internal);
|
||||||
defsubr (&Smake_temp_name);
|
defsubr (&Smake_temp_name);
|
||||||
defsubr (&Sexpand_file_name);
|
defsubr (&Sexpand_file_name);
|
||||||
defsubr (&Ssubstitute_in_file_name);
|
defsubr (&Ssubstitute_in_file_name);
|
||||||
|
|
|
||||||
|
|
@ -206,14 +206,11 @@ get_boot_time (void)
|
||||||
WTMP_FILE, counter);
|
WTMP_FILE, counter);
|
||||||
if (! NILP (Ffile_exists_p (tempname)))
|
if (! NILP (Ffile_exists_p (tempname)))
|
||||||
{
|
{
|
||||||
/* The utmp functions on mescaline.gnu.org accept only
|
/* The utmp functions on older systems accept only file
|
||||||
file names up to 8 characters long. Choose a 2
|
names up to 8 bytes long. Choose a 2 byte prefix, so
|
||||||
character long prefix, and call make_temp_file with
|
the 6-byte suffix does not make the name too long. */
|
||||||
second arg non-zero, so that it will add not more
|
filename = Fmake_temp_file_internal (build_string ("wt"), Qnil,
|
||||||
than 6 characters to the prefix. */
|
empty_unibyte_string);
|
||||||
filename = Fexpand_file_name (build_string ("wt"),
|
|
||||||
Vtemporary_file_directory);
|
|
||||||
filename = make_temp_name (filename, 1);
|
|
||||||
CALLN (Fcall_process, build_string ("gzip"), Qnil,
|
CALLN (Fcall_process, build_string ("gzip"), Qnil,
|
||||||
list2 (QCfile, filename), Qnil,
|
list2 (QCfile, filename), Qnil,
|
||||||
build_string ("-cd"), tempname);
|
build_string ("-cd"), tempname);
|
||||||
|
|
|
||||||
|
|
@ -4014,7 +4014,6 @@ extern bool file_directory_p (const char *);
|
||||||
extern bool file_accessible_directory_p (Lisp_Object);
|
extern bool file_accessible_directory_p (Lisp_Object);
|
||||||
extern void init_fileio (void);
|
extern void init_fileio (void);
|
||||||
extern void syms_of_fileio (void);
|
extern void syms_of_fileio (void);
|
||||||
extern Lisp_Object make_temp_name (Lisp_Object, bool);
|
|
||||||
|
|
||||||
/* Defined in search.c. */
|
/* Defined in search.c. */
|
||||||
extern void shrink_regexp_cache (void);
|
extern void shrink_regexp_cache (void);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue