Put stdio.h, sys/types.h and sys/stat.h after config.h.
[bpt/emacs.git] / src / filelock.c
index fad8dd1..68c1083 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.
 
@@ -19,7 +19,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include <sys/types.h>
 #include <sys/stat.h>
-#include "config.h"
+#include <config.h>
 
 #ifdef VMS
 #include "vms-pwd.h"
@@ -34,14 +34,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 ();
 
+#if defined (__bsdi__) || defined (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.
@@ -66,10 +89,53 @@ char *superlock_path;
 
 /* Set LOCK to the name of the lock file for the filename FILE.
    char *LOCK; Lisp_Object FILE;  */
+
+#ifndef HAVE_LONG_FILE_NAMES
+
+#define MAKE_LOCK_PATH(lock, file) \
+  (lock = (char *) alloca (14 + strlen (lock_path) + 1), \
+   fill_in_lock_short_file_name (lock, (file)))
+
+
+fill_in_lock_short_file_name (lockfile, fn)
+     register char *lockfile;
+     register Lisp_Object fn;
+{
+  register union
+    {
+      unsigned int  word [2];
+      unsigned char byte [8];
+    } crc;
+  register unsigned char *p, new;
+  
+  /* 7-bytes cyclic code for burst correction on byte-by-byte basis.
+     the used polynomial is D^7 + D^6 + D^3 +1. pot@cnuce.cnr.it */
+
+  crc.word[0] = crc.word[1] = 0;
+
+  for (p = XSTRING (fn)->data; new = *p++; )
+    {
+      new += crc.byte[6];
+      crc.byte[6] = crc.byte[5] + new;
+      crc.byte[5] = crc.byte[4];
+      crc.byte[4] = crc.byte[3];
+      crc.byte[3] = crc.byte[2] + new;
+      crc.byte[2] = crc.byte[1];
+      crc.byte[1] = crc.byte[0];
+      crc.byte[0] = new;
+    }
+  sprintf (lockfile, "%s%.2x%.2x%.2x%.2x%.2x%.2x%.2x", lock_path,
+          crc.byte[0], crc.byte[1], crc.byte[2], crc.byte[3],
+          crc.byte[4], crc.byte[5], crc.byte[6]);
+}
+
+#else /* defined HAVE_LONG_FILE_NAMES */
+
 #define MAKE_LOCK_PATH(lock, file) \
   (lock = (char *) alloca (XSTRING (file)->size + strlen (lock_path) + 1), \
    fill_in_lock_file_name (lock, (file)))
 
+
 fill_in_lock_file_name (lockfile, fn)
      register char *lockfile;
      register Lisp_Object fn;
@@ -88,6 +154,7 @@ fill_in_lock_file_name (lockfile, fn)
        *p = '!';
     }
 }
+#endif /* !defined HAVE_LONG_FILE_NAMES */
 
 static Lisp_Object
 lock_file_owner_name (lfname)
@@ -95,7 +162,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);
@@ -124,6 +190,11 @@ lock_file_owner_name (lfname)
    and put in the Emacs lock directory.  */
 /* (ie., /ka/king/junk.tex -> /!/!ka!king!junk.tex). */
 
+/* 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 -> /!/12a82c62f1c6da). */
+
 void
 lock_file (fn)
      register Lisp_Object fn;
@@ -136,7 +207,8 @@ lock_file (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 = Fget_file_buffer (fn);
     if (!NILP (subject_buf)
        && NILP (Fverify_visited_file_modtime (subject_buf))
        && !NILP (Ffile_exists_p (fn)))
@@ -271,6 +343,7 @@ lock_superlock (lfname)
      char *lfname;
 {
   register int i, fd;
+  DIR *lockdir;
 
   for (i = -20; i < 0 && (fd = open (superlock_path,
                                     O_WRONLY | O_EXCL | O_CREAT, 0666)) < 0;
@@ -278,6 +351,13 @@ lock_superlock (lfname)
     {
       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_path))
+       closedir (lockdir);
+
       sleep (1);
     }
   if (fd >= 0)
@@ -384,8 +464,9 @@ init_filelock ()
   /* 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);
+      char *new_path = (char *) xmalloc (strlen (lock_path) + 2);
+      strcpy (new_path, lock_path);
+      lock_path = new_path;
       strcat (lock_path, "/");
     }