-/* Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
+/* Copyright (C) 1985, 1986, 1987, 1993 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Emacs is distributed in the hope that it will be useful,
#include <sys/types.h>
#include <sys/stat.h>
-#include "config.h"
+#include <config.h>
#ifdef VMS
-#include "pwd.h"
+#include "vms-pwd.h"
#else
#include <pwd.h>
#endif
#include <fcntl.h>
#endif /* USG */
-#undef NULL
#include "lisp.h"
-#include "paths.h"
+#include <paths.h>
#include "buffer.h"
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.
#define lstat stat
#endif
+
+/* The name of the directory in which we keep lock files, with a '/'
+ appended. */
+char *lock_path;
+
+/* 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;
+
+/* 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;
+{
+ register char *p;
+
+ strcpy (lockfile, lock_path);
+
+ p = lockfile + strlen (lockfile);
+
+ strcpy (p, XSTRING (fn)->data);
+
+ for (; *p; p++)
+ {
+ if (*p == '/')
+ *p = '!';
+ }
+}
+#endif /* !defined HAVE_LONG_FILE_NAMES */
+
static Lisp_Object
lock_file_owner_name (lfname)
char *lfname;
{
struct stat s;
struct passwd *the_pw;
- extern struct passwd *getpwuid ();
if (lstat (lfname, &s) == 0)
the_pw = getpwuid (s.st_uid);
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;
register Lisp_Object attack;
register char *lfname;
- /* Create the name of the lock-file for file fn */
- lfname = (char *) alloca (XSTRING (fn)->size + strlen (PATH_LOCK) + 1);
- fill_in_lock_file_name (lfname, fn);
+ MAKE_LOCK_PATH (lfname, fn);
- /* See if this file is visited and has changed on disk since it was visited. */
+ /* See if this file is visited and has changed on disk since it was
+ visited. */
{
register Lisp_Object subject_buf = Fget_file_buffer (fn);
- if (!NULL (subject_buf)
- && NULL (Fverify_visited_file_modtime (subject_buf))
- && !NULL (Ffile_exists_p (fn)))
+ if (!NILP (subject_buf)
+ && NILP (Fverify_visited_file_modtime (subject_buf))
+ && !NILP (Ffile_exists_p (fn)))
call1 (intern ("ask-user-about-supersession-threat"), fn);
}
/* Else consider breaking the lock */
attack = call2 (intern ("ask-user-about-lock"), fn,
lock_file_owner_name (lfname));
- if (!NULL (attack))
+ if (!NILP (attack))
/* User says take the lock */
{
lock_superlock (lfname);
lock_file_1 (lfname, O_WRONLY) ;
- unlink (PATH_SUPERLOCK);
+ unlink (superlock_path);
return;
}
/* User says ignore the lock */
}
-fill_in_lock_file_name (lockfile, fn)
- register char *lockfile;
- register Lisp_Object fn;
-{
- register char *p;
-
- strcpy (lockfile, PATH_LOCK);
-
- p = lockfile + strlen (lockfile);
-
- strcpy (p, XSTRING (fn)->data);
-
- for (; *p; p++)
- {
- if (*p == '/')
- *p = '!';
- }
-}
-
/* Lock the lock file named LFNAME.
If MODE is O_WRONLY, we do so even if it is already locked.
If MODE is O_WRONLY | O_EXCL | O_CREAT, we do so only if it is free.
{
register char *lfname;
- lfname = (char *) alloca (XSTRING (fn)->size + strlen (PATH_LOCK) + 1);
- fill_in_lock_file_name (lfname, fn);
+ MAKE_LOCK_PATH (lfname, fn);
lock_superlock (lfname);
if (current_lock_owner_1 (lfname) == getpid ())
unlink (lfname);
- unlink (PATH_SUPERLOCK);
+ unlink (superlock_path);
}
lock_superlock (lfname)
{
register int i, fd;
- for (i = -20; i < 0 && (fd = open (PATH_SUPERLOCK,
+ for (i = -20; i < 0 && (fd = open (superlock_path,
O_WRONLY | O_EXCL | O_CREAT, 0666)) < 0;
i++)
{
if (fd >= 0)
{
#ifdef USG
- chmod (PATH_SUPERLOCK, 0666);
+ chmod (superlock_path, 0666);
#else
fchmod (fd, 0666);
#endif
(fn)
Lisp_Object fn;
{
- if (NULL (fn))
+ if (NILP (fn))
fn = current_buffer->filename;
else
CHECK_STRING (fn, 0);
if (current_buffer->save_modified < MODIFF
- && !NULL (fn))
+ && !NILP (fn))
lock_file (fn);
return Qnil;
}
fn = Fexpand_file_name (fn, Qnil);
- /* Create the name of the lock-file for file filename */
- lfname = (char *) alloca (XSTRING (fn)->size + strlen (PATH_LOCK) + 1);
- fill_in_lock_file_name (lfname, fn);
+ MAKE_LOCK_PATH (lfname, fn);
owner = current_lock_owner (lfname);
if (owner <= 0)
return (lock_file_owner_name (lfname));
}
+\f
+/* Initialization functions. */
+
+init_filelock ()
+{
+ lock_path = egetenv ("EMACSLOCKDIR");
+ if (! lock_path)
+ lock_path = PATH_LOCK;
+
+ /* Make sure it ends with a slash. */
+ if (lock_path[strlen (lock_path) - 1] != '/')
+ {
+ char *new_path = (char *) xmalloc (strlen (lock_path) + 2);
+ strcpy (new_path, lock_path);
+ lock_path = new_path;
+ strcat (lock_path, "/");
+ }
+
+ superlock_path = (char *) xmalloc ((strlen (lock_path)
+ + sizeof (SUPERLOCK_NAME)));
+ strcpy (superlock_path, lock_path);
+ strcat (superlock_path, SUPERLOCK_NAME);
+}
+
syms_of_filelock ()
{
defsubr (&Sunlock_buffer);