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 }