Simplify redefinition of 'abort' (Bug#12316).
[bpt/emacs.git] / src / filelock.c
index c28ee78..d21d8e7 100644 (file)
@@ -1,5 +1,5 @@
 /* Lock files for editing.
-   Copyright (C) 1985-1987, 1993-1994, 1996, 1998-2011
+   Copyright (C) 1985-1987, 1993-1994, 1996, 1998-2012
                  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -40,8 +40,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <errno.h>
 
 #include "lisp.h"
-#include "buffer.h"
 #include "character.h"
+#include "buffer.h"
 #include "coding.h"
 #include "systime.h"
 
@@ -174,14 +174,14 @@ get_boot_time (void)
 
       filename = Qnil;
 
-      sprintf (cmd_string, "%s.%d", WTMP_FILE, counter);
-      tempname = build_string (cmd_string);
+      tempname = make_formatted_string
+       (cmd_string, "%s.%d", WTMP_FILE, counter);
       if (! NILP (Ffile_exists_p (tempname)))
        filename = tempname;
       else
        {
-         sprintf (cmd_string, "%s.%d.gz", WTMP_FILE, counter);
-         tempname = build_string (cmd_string);
+         tempname = make_formatted_string (cmd_string, "%s.%d.gz",
+                                           WTMP_FILE, counter);
          if (! NILP (Ffile_exists_p (tempname)))
            {
              Lisp_Object args[6];
@@ -294,12 +294,13 @@ typedef struct
    trailing period plus one for the digit after it plus one for the
    null.  */
 #define MAKE_LOCK_NAME(lock, file) \
-  (lock = (char *) alloca (SBYTES (file) + 2 + 1 + 1 + 1), \
+  (lock = alloca (SBYTES (file) + 2 + 1 + 1 + 1), \
    fill_in_lock_file_name (lock, (file)))
 
 static void
 fill_in_lock_file_name (register char *lockfile, register Lisp_Object fn)
 {
+  ptrdiff_t length = SBYTES (fn);
   register char *p;
   struct stat st;
   int count = 0;
@@ -309,14 +310,14 @@ fill_in_lock_file_name (register char *lockfile, register Lisp_Object fn)
   /* Shift the nondirectory part of the file name (including the null)
      right two characters.  Here is one of the places where we'd have to
      do something to support 14-character-max file names.  */
-  for (p = lockfile + strlen (lockfile); p != lockfile && *p != '/'; p--)
+  for (p = lockfile + length; p != lockfile && *p != '/'; p--)
     p[2] = *p;
 
   /* Insert the `.#'.  */
   p[1] = '.';
   p[2] = '#';
 
-  p = p + strlen (p);
+  p = p + length + 2;
 
   while (lstat (lockfile, &st) == 0 && !S_ISLNK (st.st_mode))
     {
@@ -336,34 +337,25 @@ fill_in_lock_file_name (register char *lockfile, register Lisp_Object fn)
 static int
 lock_file_1 (char *lfname, int force)
 {
-  register int err;
-  printmax_t boot, pid;
-  const char *user_name;
-  const char *host_name;
-  char *lock_info_str;
+  int err;
+  int symlink_errno;
+  USE_SAFE_ALLOCA;
 
   /* Call this first because it can GC.  */
-  boot = get_boot_time ();
+  printmax_t boot = get_boot_time ();
 
-  if (STRINGP (Fuser_login_name (Qnil)))
-    user_name = SSDATA (Fuser_login_name (Qnil));
-  else
-    user_name = "";
-  if (STRINGP (Fsystem_name ()))
-    host_name = SSDATA (Fsystem_name ());
-  else
-    host_name = "";
-  lock_info_str = (char *)alloca (strlen (user_name) + strlen (host_name)
-                                 + 2 * INT_STRLEN_BOUND (printmax_t)
-                                 + sizeof "@.:");
-  pid = getpid ();
-
-  if (boot)
-    sprintf (lock_info_str, "%s@%s.%"pMd":%"pMd,
-            user_name, host_name, pid, boot);
-  else
-    sprintf (lock_info_str, "%s@%s.%"pMd,
-            user_name, host_name, pid);
+  Lisp_Object luser_name = Fuser_login_name (Qnil);
+  char const *user_name = STRINGP (luser_name) ? SSDATA (luser_name) : "";
+  Lisp_Object lhost_name = Fsystem_name ();
+  char const *host_name = STRINGP (lhost_name) ? SSDATA (lhost_name) : "";
+  ptrdiff_t lock_info_size = (strlen (user_name) + strlen (host_name)
+                             + 2 * INT_STRLEN_BOUND (printmax_t)
+                             + sizeof "@.:");
+  char *lock_info_str = SAFE_ALLOCA (lock_info_size);
+  printmax_t pid = getpid ();
+
+  esprintf (lock_info_str, boot ? "%s@%s.%"pMd":%"pMd : "%s@%s.%"pMd,
+           user_name, host_name, pid, boot);
 
   err = symlink (lock_info_str, lfname);
   if (errno == EEXIST && force)
@@ -372,6 +364,9 @@ lock_file_1 (char *lfname, int force)
       err = symlink (lock_info_str, lfname);
     }
 
+  symlink_errno = errno;
+  SAFE_FREE ();
+  errno = symlink_errno;
   return err == 0;
 }
 
@@ -419,7 +414,7 @@ current_lock_owner (lock_info_type *owner, char *lfname)
       return -1;
     }
   len = at - lfinfo;
-  owner->user = (char *) xmalloc (len + 1);
+  owner->user = xmalloc (len + 1);
   memcpy (owner->user, lfinfo, len);
   owner->user[len] = 0;
 
@@ -446,7 +441,7 @@ current_lock_owner (lock_info_type *owner, char *lfname)
 
   /* The host is everything in between.  */
   len = dot - at - 1;
-  owner->host = (char *) xmalloc (len + 1);
+  owner->host = xmalloc (len + 1);
   memcpy (owner->host, at + 1, len);
   owner->host[len] = 0;
 
@@ -541,9 +536,15 @@ lock_file (Lisp_Object fn)
 {
   register Lisp_Object attack, orig_fn, encoded_fn;
   register char *lfname, *locker;
+  ptrdiff_t locker_size;
   lock_info_type lock_info;
   printmax_t pid;
   struct gcpro gcpro1;
+  USE_SAFE_ALLOCA;
+
+  /* Don't do locking if the user has opted out.  */
+  if (! create_lockfiles)
+    return;
 
   /* Don't do locking while dumping Emacs.
      Uncompressing wtmp files uses call-process, which does not work
@@ -580,15 +581,17 @@ lock_file (Lisp_Object fn)
     return;
 
   /* Else consider breaking the lock */
-  locker = (char *) alloca (strlen (lock_info.user) + strlen (lock_info.host)
-                           + INT_STRLEN_BOUND (printmax_t)
-                           + sizeof "@ (pid )");
+  locker_size = (strlen (lock_info.user) + strlen (lock_info.host)
+                + INT_STRLEN_BOUND (printmax_t)
+                + sizeof "@ (pid )");
+  locker = SAFE_ALLOCA (locker_size);
   pid = lock_info.pid;
-  sprintf (locker, "%s@%s (pid %"pMd")",
-          lock_info.user, lock_info.host, pid);
+  esprintf (locker, "%s@%s (pid %"pMd")",
+           lock_info.user, lock_info.host, pid);
   FREE_LOCK_INFO (lock_info);
 
   attack = call2 (intern ("ask-user-about-lock"), fn, build_string (locker));
+  SAFE_FREE ();
   if (!NILP (attack))
     /* User says take the lock */
     {
@@ -623,7 +626,7 @@ unlock_all_files (void)
       b = XBUFFER (XCDR (XCAR (tail)));
       if (STRINGP (BVAR (b, file_truename)) && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b))
        {
-         unlock_file(BVAR (b, file_truename));
+         unlock_file (BVAR (b, file_truename));
        }
     }
 }
@@ -696,15 +699,6 @@ t if it is locked by you, else a string saying which user has locked it.  */)
 
   return ret;
 }
-\f
-/* Initialization functions.  */
-
-void
-init_filelock (void)
-{
-  boot_time = 0;
-  boot_time_initialized = 0;
-}
 
 #endif /* CLASH_DETECTION */
 
@@ -715,6 +709,10 @@ syms_of_filelock (void)
               doc: /* The directory for writing temporary files.  */);
   Vtemporary_file_directory = Qnil;
 
+  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);