X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/f46305c86cd247b2396e73ce8bb064f69373834d..HEAD:/src/filelock.c
diff --git a/src/filelock.c b/src/filelock.c
index de6aba8385..3a268148ea 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -1,6 +1,10 @@
/* Lock files for editing.
- Copyright (C) 1985-1987, 1993-1994, 1996, 1998-2013 Free Software
- Foundation, Inc.
+
+Copyright (C) 1985-1987, 1993-1994, 1996, 1998-2014
+ Free Software Foundation, Inc.
+
+Author: Richard King
+ (according to authors.el)
This file is part of GNU Emacs.
@@ -47,11 +51,10 @@ along with GNU Emacs. If not, see . */
#include "systime.h"
#ifdef WINDOWSNT
#include
+#include /* for fcntl */
#include "w32.h" /* for dostounix_filename */
#endif
-#ifdef CLASH_DETECTION
-
#ifdef HAVE_UTMP_H
#include
#endif
@@ -180,7 +183,7 @@ get_boot_time (void)
since utmp is typically much smaller than wtmp.
Passing a null pointer causes get_boot_time_1
to inspect the default file, namely utmp. */
- get_boot_time_1 ((char *) 0, 0);
+ get_boot_time_1 (0, 0);
if (boot_time)
return boot_time;
@@ -256,18 +259,14 @@ void
get_boot_time_1 (const char *filename, bool newest)
{
struct utmp ut, *utp;
- int desc;
if (filename)
{
/* On some versions of IRIX, opening a nonexistent file name
is likely to crash in the utmp routines. */
- desc = emacs_open (filename, O_RDONLY, 0);
- if (desc < 0)
+ if (faccessat (AT_FDCWD, filename, R_OK, AT_EACCESS) != 0)
return;
- emacs_close (desc);
-
utmpname (filename);
}
@@ -380,9 +379,9 @@ rename_lock_file (char const *old, char const *new, bool force)
#endif
}
-/* Create the lock file FILE with contents CONTENTS. Return 0 if
+/* Create the lock file LFNAME with contents LOCK_INFO_STR. Return 0 if
successful, an errno value on failure. If FORCE, remove any
- existing FILE if necessary. */
+ existing LFNAME if necessary. */
static int
create_lock_file (char *lfname, char *lock_info_str, bool force)
@@ -411,31 +410,23 @@ create_lock_file (char *lfname, char *lock_info_str, bool force)
USE_SAFE_ALLOCA;
char *nonce = SAFE_ALLOCA (lfdirlen + sizeof nonce_base);
int fd;
- bool need_fchmod;
- mode_t world_readable = S_IRUSR | S_IRGRP | S_IROTH;
memcpy (nonce, lfname, lfdirlen);
strcpy (nonce + lfdirlen, nonce_base);
-#if HAVE_MKSTEMP
- /* Prefer mkstemp if available, as it avoids a race between
- mktemp and emacs_open. */
- fd = mkstemp (nonce);
- need_fchmod = 1;
-#else
- mktemp (nonce);
- fd = emacs_open (nonce, O_WRONLY | O_CREAT | O_EXCL | O_BINARY,
- world_readable);
- need_fchmod = 0;
-#endif
-
+ fd = mkostemp (nonce, O_BINARY | O_CLOEXEC);
if (fd < 0)
err = errno;
else
{
- ptrdiff_t lock_info_len = strlen (lock_info_str);
+ ptrdiff_t lock_info_len;
+ if (! O_CLOEXEC)
+ fcntl (fd, F_SETFD, FD_CLOEXEC);
+ lock_info_len = strlen (lock_info_str);
err = 0;
- if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len
- || (need_fchmod && fchmod (fd, world_readable) != 0))
+ /* Use 'write', not 'emacs_write', as garbage collection
+ might signal an error, which would leak FD. */
+ if (write (fd, lock_info_str, lock_info_len) != lock_info_len
+ || fchmod (fd, S_IRUSR | S_IRGRP | S_IROTH) != 0)
err = errno;
/* There is no need to call fsync here, as the contents of
the lock file need not survive system crashes. */
@@ -470,10 +461,18 @@ lock_file_1 (char *lfname, bool force)
char lock_info_str[MAX_LFINFO + 1];
printmax_t pid = getpid ();
- if (sizeof lock_info_str
- <= snprintf (lock_info_str, sizeof lock_info_str,
- boot ? "%s@%s.%"pMd":%"pMd : "%s@%s.%"pMd,
- user_name, host_name, pid, boot))
+ if (boot)
+ {
+ if (sizeof lock_info_str
+ <= snprintf (lock_info_str, sizeof lock_info_str,
+ "%s@%s.%"pMd":%"pMd,
+ user_name, host_name, pid, boot))
+ return ENAMETOOLONG;
+ }
+ else if (sizeof lock_info_str
+ <= snprintf (lock_info_str, sizeof lock_info_str,
+ "%s@%s.%"pMd,
+ user_name, host_name, pid))
return ENAMETOOLONG;
return create_lock_file (lfname, lock_info_str, force);
@@ -507,7 +506,8 @@ read_lock_data (char *lfname, char lfinfo[MAX_LFINFO + 1])
int fd = emacs_open (lfname, O_RDONLY | O_BINARY | O_NOFOLLOW, 0);
if (0 <= fd)
{
- ptrdiff_t read_bytes = emacs_read (fd, lfinfo, MAX_LFINFO + 1);
+ /* Use read, not emacs_read, since FD isn't unwind-protected. */
+ ptrdiff_t read_bytes = read (fd, lfinfo, MAX_LFINFO + 1);
int read_errno = errno;
if (emacs_close (fd) != 0)
return -1;
@@ -691,7 +691,7 @@ lock_file (Lisp_Object fn)
/* Ensure we have only '/' separators, to avoid problems with
looking (inside fill_in_lock_file_name) for backslashes in file
names encoded by some DBCS codepage. */
- dostounix_filename (SSDATA (fn), 1);
+ dostounix_filename (SSDATA (fn));
#endif
encoded_fn = ENCODE_FILE (fn);
@@ -755,16 +755,15 @@ unlock_file (Lisp_Object fn)
void
unlock_all_files (void)
{
- register Lisp_Object tail;
+ register Lisp_Object tail, buf;
register struct buffer *b;
- for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_LIVE_BUFFER (tail, buf)
{
- b = XBUFFER (XCDR (XCAR (tail)));
- if (STRINGP (BVAR (b, file_truename)) && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b))
- {
- unlock_file (BVAR (b, file_truename));
- }
+ b = XBUFFER (buf);
+ if (STRINGP (BVAR (b, file_truename))
+ && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b))
+ unlock_file (BVAR (b, file_truename));
}
}
@@ -772,7 +771,9 @@ DEFUN ("lock-buffer", Flock_buffer, Slock_buffer,
0, 1, 0,
doc: /* Lock FILE, if current buffer is modified.
FILE defaults to current buffer's visited file,
-or else nothing is done if current buffer isn't visiting a file. */)
+or else nothing is done if current buffer isn't visiting a file.
+
+If the option `create-lockfiles' is nil, this does nothing. */)
(Lisp_Object file)
{
if (NILP (file))
@@ -836,11 +837,11 @@ t if it is locked by you, else a string saying which user has locked it. */)
return ret;
}
-#endif /* CLASH_DETECTION */
-
void
syms_of_filelock (void)
{
+#include "filelock.x"
+
DEFVAR_LISP ("temporary-file-directory", Vtemporary_file_directory,
doc: /* The directory for writing temporary files. */);
Vtemporary_file_directory = Qnil;
@@ -848,10 +849,4 @@ syms_of_filelock (void)
DEFVAR_BOOL ("create-lockfiles", create_lockfiles,
doc: /* Non-nil means use lockfiles to avoid editing collisions. */);
create_lockfiles = 1;
-
-#ifdef CLASH_DETECTION
- defsubr (&Sunlock_buffer);
- defsubr (&Slock_buffer);
- defsubr (&Sfile_locked_p);
-#endif
}