Update FSF's address in the preamble.
[bpt/emacs.git] / src / filelock.c
index 5b31acb..27b4be4 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1985, 1986, 1987, 1993 Free Software Foundation, Inc.
+/* Copyright (C) 1985, 1986, 1987, 1993, 1994 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -14,12 +14,13 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 #include <sys/types.h>
 #include <sys/stat.h>
-#include "config.h"
+#include <config.h>
 
 #ifdef VMS
 #include "vms-pwd.h"
@@ -34,14 +35,37 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #endif /* USG */
 
 #include "lisp.h"
-#include "paths.h"
+#include <paths.h>
 #include "buffer.h"
 
+#ifdef SYSV_SYSTEM_DIR
+#include <dirent.h>
+#else /* not SYSV_SYSTEM_DIR */
+#ifdef NONSYSTEM_DIR_LIBRARY
+#include "ndir.h"
+#else /* not NONSYSTEM_DIR_LIBRARY */
+#ifdef MSDOS
+#include <dirent.h>
+#else
+#include <sys/dir.h>
+#endif
+#endif /* not NONSYSTEM_DIR_LIBRARY */
+#ifndef MSDOS
+extern DIR *opendir ();
+#endif /* not MSDOS */
+#endif /* not SYSV_SYSTEM_DIR */
+
 extern int errno;
 
 extern char *egetenv ();
 extern char *strcpy ();
 
+#ifdef DECLARE_GETPWUID_WITH_UID_T
+extern struct passwd *getpwuid (uid_t);
+#else
+extern struct passwd *getpwuid ();
+#endif
+
 #ifdef CLASH_DETECTION
   
 /* If system does not have symbolic links, it does not have lstat.
@@ -54,23 +78,23 @@ extern char *strcpy ();
 
 /* The name of the directory in which we keep lock files, with a '/'
    appended.  */  
-char *lock_path;
+char *lock_dir;
 
 /* The name of the file in the lock directory which is used to
    arbitrate access to the entire directory.  */
 #define SUPERLOCK_NAME "!!!SuperLock!!!"
 
-/* The path to the superlock file.  This is SUPERLOCK_NAME appended to
-   lock_path.  */
-char *superlock_path;
+/* The name of the superlock file.  This is SUPERLOCK_NAME appended to
+   lock_dir.  */
+char *superlock_file;
 
 /* Set LOCK to the name of the lock file for the filename FILE.
    char *LOCK; Lisp_Object FILE;  */
 
-#ifdef SHORT_FILE_NAMES
+#ifndef HAVE_LONG_FILE_NAMES
 
-#define MAKE_LOCK_PATH(lock, file) \
-  (lock = (char *) alloca (14 + strlen (lock_path) + 1), \
+#define MAKE_LOCK_NAME(lock, file) \
+  (lock = (char *) alloca (14 + strlen (lock_dir) + 1), \
    fill_in_lock_short_file_name (lock, (file)))
 
 
@@ -92,8 +116,7 @@ fill_in_lock_short_file_name (lockfile, fn)
 
   for (p = XSTRING (fn)->data; new = *p++; )
     {
-      new += crc.byte[7];
-      crc.byte[7] = crc.byte[6];
+      new += crc.byte[6];
       crc.byte[6] = crc.byte[5] + new;
       crc.byte[5] = crc.byte[4];
       crc.byte[4] = crc.byte[3];
@@ -102,15 +125,15 @@ fill_in_lock_short_file_name (lockfile, fn)
       crc.byte[1] = crc.byte[0];
       crc.byte[0] = new;
     }
-  sprintf (lockfile, "%s%.2x%.2x%.2x%.2x%.2x%.2x%.2x", lock_path,
+  sprintf (lockfile, "%s%.2x%.2x%.2x%.2x%.2x%.2x%.2x", lock_dir,
           crc.byte[0], crc.byte[1], crc.byte[2], crc.byte[3],
           crc.byte[4], crc.byte[5], crc.byte[6]);
 }
 
-#else /* !defined SHORT_FILE_NAMES */
+#else /* defined HAVE_LONG_FILE_NAMES */
 
-#define MAKE_LOCK_PATH(lock, file) \
-  (lock = (char *) alloca (XSTRING (file)->size + strlen (lock_path) + 1), \
+#define MAKE_LOCK_NAME(lock, file) \
+  (lock = (char *) alloca (XSTRING (file)->size + strlen (lock_dir) + 1), \
    fill_in_lock_file_name (lock, (file)))
 
 
@@ -120,7 +143,7 @@ fill_in_lock_file_name (lockfile, fn)
 {
   register char *p;
 
-  strcpy (lockfile, lock_path);
+  strcpy (lockfile, lock_dir);
 
   p = lockfile + strlen (lockfile);
 
@@ -132,7 +155,7 @@ fill_in_lock_file_name (lockfile, fn)
        *p = '!';
     }
 }
-#endif /* SHORT_FILE_NAMES */
+#endif /* !defined HAVE_LONG_FILE_NAMES */
 
 static Lisp_Object
 lock_file_owner_name (lfname)
@@ -140,7 +163,6 @@ lock_file_owner_name (lfname)
 {
   struct stat s;
   struct passwd *the_pw;
-  extern struct passwd *getpwuid ();
 
   if (lstat (lfname, &s) == 0)
     the_pw = getpwuid (s.st_uid);
@@ -169,24 +191,28 @@ lock_file_owner_name (lfname)
    and put in the Emacs lock directory.  */
 /* (ie., /ka/king/junk.tex -> /!/!ka!king!junk.tex). */
 
-/* If SHORT_FILE_NAMES is defined, the lock file name is the hex
+/* If HAVE_LONG_FILE_NAMES is not defined, the lock file name is the hex
    representation of a 14-bytes CRC generated from the file name
    and put in the Emacs lock directory (not very nice, but it works).
-   (ie., /ka/king/junk.tex -> /!/ec92d3ed24a8f0). */
+   (ie., /ka/king/junk.tex -> /!/12a82c62f1c6da). */
 
 void
 lock_file (fn)
      register Lisp_Object fn;
 {
-  register Lisp_Object attack;
+  register Lisp_Object attack, orig_fn;
   register char *lfname;
 
-  MAKE_LOCK_PATH (lfname, fn);
+  orig_fn = fn;
+  fn = Fexpand_file_name (fn, Qnil);
+
+  MAKE_LOCK_NAME (lfname, fn);
 
   /* See if this file is visited and has changed on disk since it was
      visited.  */
   {
-    register Lisp_Object subject_buf = Fget_file_buffer (fn);
+    register Lisp_Object subject_buf;
+    subject_buf = get_truename_buffer (orig_fn);
     if (!NILP (subject_buf)
        && NILP (Fverify_visited_file_modtime (subject_buf))
        && !NILP (Ffile_exists_p (fn)))
@@ -206,7 +232,7 @@ lock_file (fn)
     {
       lock_superlock (lfname);
       lock_file_1 (lfname, O_WRONLY) ;
-      unlink (superlock_path);
+      unlink (superlock_file);
       return;
     }
   /* User says ignore the lock */
@@ -307,33 +333,43 @@ unlock_file (fn)
 {
   register char *lfname;
 
-  MAKE_LOCK_PATH (lfname, fn);
+  fn = Fexpand_file_name (fn, Qnil);
+
+  MAKE_LOCK_NAME (lfname, fn);
 
   lock_superlock (lfname);
 
   if (current_lock_owner_1 (lfname) == getpid ())
     unlink (lfname);
 
-  unlink (superlock_path);
+  unlink (superlock_file);
 }
 
 lock_superlock (lfname)
      char *lfname;
 {
   register int i, fd;
+  DIR *lockdir;
 
-  for (i = -20; i < 0 && (fd = open (superlock_path,
+  for (i = -20; i < 0 && (fd = open (superlock_file,
                                     O_WRONLY | O_EXCL | O_CREAT, 0666)) < 0;
        i++)
     {
       if (errno != EEXIST)
        return;
+
+      /* This seems to be necessary to prevent Emacs from hanging when the
+        competing process has already deleted the superlock, but it's still
+        in the NFS cache.  So we force NFS to synchronize the cache.  */
+      if (lockdir = opendir (lock_dir))
+       closedir (lockdir);
+
       sleep (1);
     }
   if (fd >= 0)
     {
 #ifdef USG
-      chmod (superlock_path, 0666);
+      chmod (superlock_file, 0666);
 #else
       fchmod (fd, 0666);
 #endif
@@ -348,13 +384,11 @@ unlock_all_files ()
   register Lisp_Object tail;
   register struct buffer *b;
 
-  for (tail = Vbuffer_alist; XGCTYPE (tail) == Lisp_Cons;
-       tail = XCONS (tail)->cdr)
+  for (tail = Vbuffer_alist; GC_CONSP (tail); tail = XCONS (tail)->cdr)
     {
       b = XBUFFER (XCONS (XCONS (tail)->car)->cdr);
-      if (XTYPE (b->filename) == Lisp_String &&
-         b->save_modified < BUF_MODIFF (b))
-       unlock_file (b->filename);
+      if (STRINGP (b->file_truename) && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b))
+       unlock_file (b->file_truename);
     }
 }
 
@@ -364,16 +398,16 @@ DEFUN ("lock-buffer", Flock_buffer, Slock_buffer,
   "Lock FILE, if current buffer is modified.\n\
 FILE defaults to current buffer's visited file,\n\
 or else nothing is done if current buffer isn't visiting a file.")
-  (fn)
-     Lisp_Object fn;
+  (file)
+     Lisp_Object file;
 {
-  if (NILP (fn))
-    fn = current_buffer->filename;
+  if (NILP (file))
+    file = current_buffer->file_truename;
   else
-    CHECK_STRING (fn, 0);
-  if (current_buffer->save_modified < MODIFF
-      && !NILP (fn))
-    lock_file (fn);
+    CHECK_STRING (file, 0);
+  if (SAVE_MODIFF < MODIFF
+      && !NILP (file))
+    lock_file (file);
   return Qnil;    
 }
 
@@ -383,9 +417,9 @@ DEFUN ("unlock-buffer", Funlock_buffer, Sunlock_buffer,
 if it should normally be locked.")
   ()
 {
-  if (current_buffer->save_modified < MODIFF &&
-      XTYPE (current_buffer->filename) == Lisp_String)
-    unlock_file (current_buffer->filename);
+  if (SAVE_MODIFF < MODIFF
+      && STRINGP (current_buffer->file_truename))
+    unlock_file (current_buffer->file_truename);
   return Qnil;
 }
 
@@ -395,23 +429,23 @@ if it should normally be locked.")
 unlock_buffer (buffer)
      struct buffer *buffer;
 {
-  if (buffer->save_modified < BUF_MODIFF (buffer) &&
-      XTYPE (buffer->filename) == Lisp_String)
-    unlock_file (buffer->filename);
+  if (BUF_SAVE_MODIFF (buffer) < BUF_MODIFF (buffer)
+      && STRINGP (buffer->file_truename))
+    unlock_file (buffer->file_truename);
 }
 
 DEFUN ("file-locked-p", Ffile_locked_p, Sfile_locked_p, 0, 1, 0,
   "Return nil if the FILENAME is not locked,\n\
 t if it is locked by you, else a string of the name of the locker.")
-  (fn)
-  Lisp_Object fn;
+  (filename)
+  Lisp_Object filename;
 {
   register char *lfname;
   int owner;
 
-  fn = Fexpand_file_name (fn, Qnil);
+  filename = Fexpand_file_name (filename, Qnil);
 
-  MAKE_LOCK_PATH (lfname, fn);
+  MAKE_LOCK_NAME (lfname, filename);
 
   owner = current_lock_owner (lfname);
   if (owner <= 0)
@@ -427,22 +461,25 @@ t if it is locked by you, else a string of the name of the locker.")
 
 init_filelock ()
 {
-  lock_path = egetenv ("EMACSLOCKDIR");
-  if (! lock_path)
-    lock_path = PATH_LOCK;
+  char *new_name;
+
+  lock_dir = egetenv ("EMACSLOCKDIR");
+  if (! lock_dir)
+    lock_dir = PATH_LOCK;
+
+  /* Copy the name in case egetenv got it from a Lisp string.  */
+  new_name = (char *) xmalloc (strlen (lock_dir) + 2);
+  strcpy (new_name, lock_dir);
+  lock_dir = new_name;
 
   /* Make sure it ends with a slash.  */
-  if (lock_path[strlen (lock_path) - 1] != '/')
-    {
-      lock_path = strcpy ((char *) xmalloc (strlen (lock_path) + 2),
-                         lock_path);
-      strcat (lock_path, "/");
-    }
+  if (lock_dir[strlen (lock_dir) - 1] != '/')
+    strcat (lock_dir, "/");
 
-  superlock_path = (char *) xmalloc ((strlen (lock_path)
+  superlock_file = (char *) xmalloc ((strlen (lock_dir)
                                      + sizeof (SUPERLOCK_NAME)));
-  strcpy (superlock_path, lock_path);
-  strcat (superlock_path, SUPERLOCK_NAME);
+  strcpy (superlock_file, lock_dir);
+  strcat (superlock_file, SUPERLOCK_NAME);
 }
 
 syms_of_filelock ()