From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Paul Eggert Newsgroups: gmane.emacs.bugs Subject: bug#28023: fix make-temp-file race on local host Date: Tue, 8 Aug 2017 22:38:05 -0700 Organization: UCLA Computer Science Department Message-ID: <8c2c16ff-94ec-a691-57b1-bab8f5b39dfb@cs.ucla.edu> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------A5C1402735518A92680D3BE1" X-Trace: blaine.gmane.org 1502257164 23721 195.159.176.226 (9 Aug 2017 05:39:24 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Wed, 9 Aug 2017 05:39:24 +0000 (UTC) User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 To: 28023@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Wed Aug 09 07:39:16 2017 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dfJi8-0005bi-Bv for geb-bug-gnu-emacs@m.gmane.org; Wed, 09 Aug 2017 07:39:16 +0200 Original-Received: from localhost ([::1]:45730 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dfJiC-0001lE-E8 for geb-bug-gnu-emacs@m.gmane.org; Wed, 09 Aug 2017 01:39:20 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:52120) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dfJhy-0001ig-Fd for bug-gnu-emacs@gnu.org; Wed, 09 Aug 2017 01:39:09 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dfJhv-0006f1-17 for bug-gnu-emacs@gnu.org; Wed, 09 Aug 2017 01:39:06 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:43825) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dfJhu-0006et-S6 for bug-gnu-emacs@gnu.org; Wed, 09 Aug 2017 01:39:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1dfJhu-0002Q7-Lh for bug-gnu-emacs@gnu.org; Wed, 09 Aug 2017 01:39:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Paul Eggert Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 09 Aug 2017 05:39:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 28023 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch X-Debbugs-Original-To: Emacs bug reports and feature requests Original-Received: via spool by submit@debbugs.gnu.org id=B.15022571179265 (code B ref -1); Wed, 09 Aug 2017 05:39:02 +0000 Original-Received: (at submit) by debbugs.gnu.org; 9 Aug 2017 05:38:37 +0000 Original-Received: from localhost ([127.0.0.1]:52506 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dfJhP-0002PJ-S7 for submit@debbugs.gnu.org; Wed, 09 Aug 2017 01:38:36 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:32801) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dfJhN-0002P5-2U for submit@debbugs.gnu.org; Wed, 09 Aug 2017 01:38:30 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dfJhF-0006Nc-0H for submit@debbugs.gnu.org; Wed, 09 Aug 2017 01:38:23 -0400 Original-Received: from lists.gnu.org ([2001:4830:134:3::11]:57277) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dfJhE-0006NC-Rg for submit@debbugs.gnu.org; Wed, 09 Aug 2017 01:38:20 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:51986) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dfJhB-0001cA-Db for bug-gnu-emacs@gnu.org; Wed, 09 Aug 2017 01:38:20 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dfJh8-0006Kv-0y for bug-gnu-emacs@gnu.org; Wed, 09 Aug 2017 01:38:17 -0400 Original-Received: from zimbra.cs.ucla.edu ([131.179.128.68]:47942) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dfJh7-0006JM-JH for bug-gnu-emacs@gnu.org; Wed, 09 Aug 2017 01:38:13 -0400 Original-Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id E68C5160736 for ; Tue, 8 Aug 2017 22:38:09 -0700 (PDT) Original-Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id RFwn-vx_Pl8n for ; Tue, 8 Aug 2017 22:38:06 -0700 (PDT) Original-Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id 3C2A816073B for ; Tue, 8 Aug 2017 22:38:06 -0700 (PDT) X-Virus-Scanned: amavisd-new at zimbra.cs.ucla.edu Original-Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id g4PCQUMSjXAd for ; Tue, 8 Aug 2017 22:38:06 -0700 (PDT) Original-Received: from [192.168.1.9] (unknown [47.153.184.153]) by zimbra.cs.ucla.edu (Postfix) with ESMTPSA id 12653160736 for ; Tue, 8 Aug 2017 22:38:06 -0700 (PDT) Content-Language: en-US X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:135587 Archived-At: This is a multi-part message in MIME format. --------------A5C1402735518A92680D3BE1 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: quoted-printable Tags: patch Severity: important I plan to install the attached patch in master soon, and am sending it fo= r=20 review to bug-gnu-emacs first in case there's some problem with it on=20 MS-Windows. Although this patch does not fix all instances of the race in= Gnu=20 Emacs (notably, Tramp access is still affected) it's a good start. --------------A5C1402735518A92680D3BE1 Content-Type: text/x-patch; name="0001-Fix-make-temp-file-race-on-local-files.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="0001-Fix-make-temp-file-race-on-local-files.patch" =46rom 0f536834ae618adc38883fc331f75a2847a8411c Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 8 Aug 2017 22:22:48 -0700 Subject: [PATCH] Fix make-temp-file race on local files For the motivation behind this patch, please see: 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 | 8 +-- lisp/files.el | 15 +++++ m4/gnulib-comp.m4 | 34 +++-------- src/buffer.c | 1 - src/fileio.c | 170 ++++++++++++++---------------------------------= ------ src/filelock.c | 11 ++-- src/lisp.h | 1 - 10 files changed, 75 insertions(+), 173 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 c23e8a40ea..c7a7a1d7c9 100755 --- a/admin/merge-gnulib +++ b/admin/merge-gnulib @@ -39,8 +39,8 @@ GNULIB_MODULES=3D 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-s= ub + stpcpy strtoimax symlink sys_stat sys_time + tempname time time_r time_rz timegm timer-time timespec-add timespec-s= ub 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) =20 -dnl checks for operating system services -AC_SYS_LONG_FILE_NAMES - #### Choose a window system. =20 ## We leave window_system equal to none if diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index a385c8c838..8b34ee6354 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=3Dlibgnu --source-base=3Dlib = --m4-base=3Dm4 --doc-base=3Ddoc --tests-base=3Dtests --aux-dir=3Dbuild-au= x --avoid=3Dclose --avoid=3Ddup --avoid=3Dfchdir --avoid=3Dfstat --avoid=3D= malloc-posix --avoid=3Dmsvc-inval --avoid=3Dmsvc-nothrow --avoid=3Dopen -= -avoid=3Dopenat-die --avoid=3Dopendir --avoid=3Draise --avoid=3Dsave-cwd = --avoid=3Dselect --avoid=3Dsetenv --avoid=3Dsigprocmask --avoid=3Dstat --= avoid=3Dstdarg --avoid=3Dstdbool --avoid=3Dthreadlib --avoid=3Dtzset --av= oid=3Dunsetenv --avoid=3Dutime --avoid=3Dutime-h --gnu-make --makefile-na= me=3Dgnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=3D= gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadli= nkat close-stream count-leading-zeros count-one-bits count-trailing-zeros= crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 d-type diffseq dtoast= r dtotimespec dup2 environ execinfo explicit_bzero faccessat fcntl fcntl-= h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloa= davg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value int= props largefile lstat manywarnings memrchr minmax mkostemp mktime nstrfti= me pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig= 2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strtoimax s= ymlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-a= dd timespec-sub unlocked-io update-copyright utimens vla warnings +# Reproduce by: gnulib-tool --import --lib=3Dlibgnu --source-base=3Dlib = --m4-base=3Dm4 --doc-base=3Ddoc --tests-base=3Dtests --aux-dir=3Dbuild-au= x --avoid=3Dclose --avoid=3Ddup --avoid=3Dfchdir --avoid=3Dfstat --avoid=3D= malloc-posix --avoid=3Dmsvc-inval --avoid=3Dmsvc-nothrow --avoid=3Dopen -= -avoid=3Dopenat-die --avoid=3Dopendir --avoid=3Draise --avoid=3Dsave-cwd = --avoid=3Dselect --avoid=3Dsetenv --avoid=3Dsigprocmask --avoid=3Dstat --= avoid=3Dstdarg --avoid=3Dstdbool --avoid=3Dthreadlib --avoid=3Dtzset --av= oid=3Dunsetenv --avoid=3Dutime --avoid=3Dutime-h --gnu-make --makefile-na= me=3Dgnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=3D= gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadli= nkat close-stream count-leading-zeros count-one-bits count-trailing-zeros= crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 d-type diffseq dtoast= r dtotimespec dup2 environ execinfo explicit_bzero faccessat fcntl fcntl-= h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloa= davg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value int= props largefile lstat manywarnings memrchr minmax mkostemp mktime nstrfti= me pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig= 2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strtoimax s= ymlink sys_stat sys_time tempname time time_r time_rz timegm timer-time t= imespec-add timespec-sub unlocked-io update-copyright utimens vla warning= s =20 =20 MOSTLYCLEANFILES +=3D core *.stackdump @@ -903,9 +903,7 @@ gl_GNULIB_ENABLED_dosname =3D @gl_GNULIB_ENABLED_dosn= ame@ gl_GNULIB_ENABLED_euidaccess =3D @gl_GNULIB_ENABLED_euidaccess@ gl_GNULIB_ENABLED_getdtablesize =3D @gl_GNULIB_ENABLED_getdtablesize@ gl_GNULIB_ENABLED_getgroups =3D @gl_GNULIB_ENABLED_getgroups@ -gl_GNULIB_ENABLED_secure_getenv =3D @gl_GNULIB_ENABLED_secure_getenv@ gl_GNULIB_ENABLED_strtoll =3D @gl_GNULIB_ENABLED_strtoll@ -gl_GNULIB_ENABLED_tempname =3D @gl_GNULIB_ENABLED_tempname@ gl_LIBOBJS =3D @gl_LIBOBJS@ gl_LTLIBOBJS =3D @gl_LTLIBOBJS@ gltests_LIBOBJS =3D @gltests_LIBOBJS@ @@ -1915,9 +1913,7 @@ endif ## begin gnulib module secure_getenv ifeq (,$(OMIT_GNULIB_MODULE_secure_getenv)) =20 -ifneq (,$(gl_GNULIB_ENABLED_secure_getenv)) =20 -endif EXTRA_DIST +=3D secure_getenv.c =20 EXTRA_libgnu_a_SOURCES +=3D secure_getenv.c @@ -2715,10 +2711,8 @@ endif ## begin gnulib module tempname ifeq (,$(OMIT_GNULIB_MODULE_tempname)) =20 -ifneq (,$(gl_GNULIB_ENABLED_tempname)) libgnu_a_SOURCES +=3D tempname.c =20 -endif EXTRA_DIST +=3D tempname.h =20 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. =20 If SUFFIX is non-nil, add that at the end of the file name." + (let ((absolute-prefix (expand-file-name prefix temporary-file-directo= ry))) + ;; 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 188c116c85..fc86237ee9 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -347,6 +347,12 @@ AC_DEFUN AC_LIBOBJ([readlinkat]) fi gl_UNISTD_MODULE_INDICATOR([readlinkat]) + gl_FUNC_SECURE_GETENV + if test $HAVE_SECURE_GETENV =3D 0; then + AC_LIBOBJ([secure_getenv]) + gl_PREREQ_SECURE_GETENV + fi + gl_STDLIB_MODULE_INDICATOR([secure_getenv]) gl_FUNC_SIG2STR if test $ac_cv_func_sig2str =3D no; then AC_LIBOBJ([sig2str]) @@ -388,6 +394,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 =3D 0 || test $REPLACE_LOCALTIME_R =3D 1; th= en @@ -424,9 +431,7 @@ AC_DEFUN gl_gnulib_enabled_5264294aa0a5557541b53c8c741f7f31=3Dfalse gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7=3Dfalse gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=3Dfalse - gl_gnulib_enabled_secure_getenv=3Dfalse gl_gnulib_enabled_strtoll=3Dfalse - gl_gnulib_enabled_tempname=3Dfalse gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec=3Dfalse func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b () { @@ -550,18 +555,6 @@ AC_DEFUN gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=3Dtrue fi } - func_gl_gnulib_m4code_secure_getenv () - { - if ! $gl_gnulib_enabled_secure_getenv; then - gl_FUNC_SECURE_GETENV - if test $HAVE_SECURE_GETENV =3D 0; then - AC_LIBOBJ([secure_getenv]) - gl_PREREQ_SECURE_GETENV - fi - gl_STDLIB_MODULE_INDICATOR([secure_getenv]) - gl_gnulib_enabled_secure_getenv=3Dtrue - fi - } func_gl_gnulib_m4code_strtoll () { if ! $gl_gnulib_enabled_strtoll; then @@ -574,14 +567,6 @@ AC_DEFUN gl_gnulib_enabled_strtoll=3Dtrue fi } - func_gl_gnulib_m4code_tempname () - { - if ! $gl_gnulib_enabled_tempname; then - gl_FUNC_GEN_TEMPNAME - gl_gnulib_enabled_tempname=3Dtrue - func_gl_gnulib_m4code_secure_getenv - fi - } func_gl_gnulib_m4code_682e609604ccaac6be382e4ee3a4eaec () { if ! $gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec; then @@ -627,9 +612,6 @@ AC_DEFUN if test $REPLACE_LSTAT =3D 1; then func_gl_gnulib_m4code_dosname fi - if test $HAVE_MKOSTEMP =3D 0; then - func_gl_gnulib_m4code_tempname - fi if test $HAVE_READLINKAT =3D 0; then func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b fi @@ -658,9 +640,7 @@ AC_DEFUN AM_CONDITIONAL([gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31], [= $gl_gnulib_enabled_5264294aa0a5557541b53c8c741f7f31]) 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_secure_getenv], [$gl_gnulib_enabled_= secure_getenv]) AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoll], [$gl_gnulib_enabled_strtol= l]) - AM_CONDITIONAL([gl_GNULIB_ENABLED_tempname], [$gl_gnulib_enabled_tempn= ame]) 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 no= n-existent buffer. */) genbase =3D name; else { - /* Note fileio.c:make_temp_name does random differently. */ char number[sizeof "-999999"]; int i =3D 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 . */ #include #include #include +#include =20 #include =20 @@ -623,149 +624,67 @@ In Unix-syntax, this function just removes the fin= al slash. */) return val; } =20 -static const char make_temp_name_tbl[64] =3D -{ - '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 stri= ng. +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. =20 - 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. =20 - 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 =3D getpid (); - - if (base64_p) - { - pidbuf[0] =3D make_temp_name_tbl[pid & 63], pid >>=3D 6; - pidbuf[1] =3D make_temp_name_tbl[pid & 63], pid >>=3D 6; - pidbuf[2] =3D make_temp_name_tbl[pid & 63], pid >>=3D 6; - pidlen =3D 3; - } - else + bool make_temp_name =3D EQ (dir_flag, make_number (0)); + CHECK_STRING (suffix); + if (!make_temp_name) + prefix =3D Fexpand_file_name (prefix, Vtemporary_file_directory); + + Lisp_Object encoded_prefix =3D ENCODE_FILE (prefix); + Lisp_Object encoded_suffix =3D ENCODE_FILE (suffix); + ptrdiff_t prefix_len =3D SBYTES (encoded_prefix); + ptrdiff_t suffix_len =3D SBYTES (encoded_suffix); + if (INT_MAX < suffix_len) + args_out_of_range (prefix, suffix); + int nX =3D 6; + Lisp_Object val =3D make_uninit_string (prefix_len + nX + suffix_len);= + char *data =3D 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 =3D (NILP (dir_flag) ? GT_FILE + : make_temp_name ? GT_NOCREATE + : GT_DIR); + int fd =3D gen_tempname (data, suffix_len, O_BINARY | O_CLOEXEC, kind)= ; + if (fd < 0 || (NILP (dir_flag) && emacs_close (fd) !=3D 0)) { -#ifdef HAVE_LONG_FILE_NAMES - pidlen =3D sprintf (pidbuf, "%"pMd, pid); -#else - pidbuf[0] =3D make_temp_name_tbl[pid & 63], pid >>=3D 6; - pidbuf[1] =3D make_temp_name_tbl[pid & 63], pid >>=3D 6; - pidbuf[2] =3D make_temp_name_tbl[pid & 63], pid >>=3D 6; - pidlen =3D 3; -#endif - } - - encoded_prefix =3D ENCODE_FILE (prefix); - len =3D SBYTES (encoded_prefix); - val =3D make_uninit_string (len + 3 + pidlen); - data =3D SSDATA (val); - memcpy (data, SSDATA (encoded_prefix), len); - p =3D data + len; - - memcpy (p, pidbuf, pidlen); - p +=3D 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 =3D time (NULL); - make_temp_name_count_initialized_p =3D 1; - } - - while (1) - { - unsigned num =3D make_temp_name_count; - - p[0] =3D make_temp_name_tbl[num & 63], num >>=3D 6; - p[1] =3D make_temp_name_tbl[num & 63], num >>=3D 6; - p[2] =3D make_temp_name_tbl[num & 63], num >>=3D 6; - - /* Poor man's congruential RN generator. Replace with - ++make_temp_name_count for debugging. */ - make_temp_name_count +=3D 25229; - make_temp_name_count %=3D 225307; - - if (!check_existing (data)) + static char const kind_message[][32] =3D { - /* We want to return only if errno is ENOENT. */ - if (errno =3D=3D 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] =3D "Creating file with prefix", + [GT_DIR] =3D "Creating directory with prefix", + [GT_NOCREATE] =3D "Creating file name with prefix" + }; + report_file_error (kind_message[kind], prefix); } + return DECODE_FILE (val); } =20 =20 DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0, doc: /* Generate temporary file name (string) starting with PREFI= X (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...).= =20 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. =20 -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 sho= uld -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); } =20 DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0= , @@ -6167,6 +6086,7 @@ This includes interactive calls to `delete-file' an= d 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..de0ca01052 100644 --- a/src/filelock.c +++ b/src/filelock.c @@ -206,14 +206,13 @@ 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. */ + /* 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 =3D Fexpand_file_name (build_string ("wt"), Vtemporary_file_directory); - filename =3D make_temp_name (filename, 1); + filename =3D Ffileio__make_temp_file (filename, 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); =20 /* Defined in search.c. */ extern void shrink_regexp_cache (void); --=20 2.13.3 --------------A5C1402735518A92680D3BE1--