Commit 70743157 authored by Paul Eggert's avatar Paul Eggert

FILE's lock is now always .#FILE and may be a regular file.

* etc/NEWS: Document this.
* nt/inc/unistd.h (O_NOFOLLOW): New macro.
* src/filelock.c: Include <c-ctype.h>.
(MAX_LFINFO): New top-level constant.
(lock_info_type): Remove members pid, boot_time.  Add members at,
dot, colon.  Change user member to be the entire buffer, not a
pointer.  This allows us to handle the case where a foreign
pid or boot time exceeds the local range.  All uses changed.
(LINKS_MIGHT_NOT_WORK): New constant.
(FREE_LOCK_INFO): Remove, as the pieces no longer need freeing.
(defined_WINDOWSNT): Remove.
(MAKE_LOCK_NAME, file_in_lock_file_name):
Always use .#FILE (not .#-FILE) for the file lock,
even if it is a regular file.
(rename_lock_file): New function.
(create_lock_file): Use it.
(create_lock_file, read_lock_data):
Prefer a symbolic link for the lock file, falling back on a
regular file if symlinks don't work.  Do not try to create
symlinks on MS-Windows, due to security hassles.  Stick with
POSIXish functions (open, read, write, close, fchmod, readlink, symlink,
link, rename, unlink, mkstemp) when creating locks, as a GNUish
host may be using a Windowsish file system, and cannot use
MS-Windows-only system calls.  Fall back on mktemp if mkstemp
doesn't work.  Don't fail merely because of a symlink-contents
length limit in the current file system; fall back on regular
files.  Increase the symlink contents length limit to 8 KiB, this
should be big enough for any real use and doesn't crunch the
stack.
(create_lock_file, lock_file_1, read_lock_data):
Simplify allocation of lock file buffers now that they fit in 8 KiB.
(lock_file_1): Return error number, not bool.  All callers changed.
(ELOOP): New macro, if not already defined.
(read_lock_data): Return size of lock file contents, not Lisp object.
All callers changed.  Handle a race condition if some other process
replaces a regular-file lock with a symlink lock or vice versa,
while we're trying to read the lock.
(current_lock_owner): Parse contents more carefully, to help avoid
confusing a regular-file lock with some other application's use
of the file.  Check for lock file contents being too long, or
not parsing correctly.
(current_lock_owner, lock_file):
Allow foreign pid and boot times that exceed the local range.
(current_lock_owner, lock_if_free, lock_file):
Simplify allocation of lock file contents.
* src/w32.c (sys_rename_replace): New function, containing most of
the contents of the old sys_rename.
(sys_rename): Use it.
(fchmod): New dummy function.
* src/w32.h (sys_rename_replace, fchmod): New decls.

Fixes: debbugs:13807
parent 05e193f1
......@@ -594,7 +594,8 @@ else
test "x$NON_GCC_TEST_OPTIONS" != x && CC="$CC $NON_GCC_TEST_OPTIONS"
fi
# Avoid gnulib's tests for O_NOATIME and O_NOFOLLOW, as we don't use them.
# Avoid gnulib's tests for HAVE_WORKING_O_NOATIME and HAVE_WORKING_O_NOFOLLOW,
# as we don't use them.
AC_DEFUN([gl_FCNTL_O_FLAGS])
# Avoid gnulib's threadlib module, as we do threads our own way.
AC_DEFUN([gl_THREADLIB])
......
2013-03-05 Paul Eggert <eggert@cs.ucla.edu>
FILE's lock is now always .#FILE and may be a regular file (Bug#13807).
* NEWS: Document this.
2013-03-02 Bill Wohler <wohler@newt.com>
Release MH-E version 8.5.
......
......@@ -320,7 +320,7 @@ text-property on the first char.
** The `defalias-fset-function' property lets you catch calls to defalias
and redirect them to your own function instead of `fset'.
** The lock for 'DIR/FILE' is now 'DIR/.#FILE' or 'DIR/.#-FILE'.
** The lock for 'DIR/FILE' is now 'DIR/.#FILE' and may be a regular file.
When you edit DIR/FILE, Emacs normally creates a symbolic link
DIR/.#FILE as a lock that warns other instances of Emacs that DIR/FILE
is being edited. Formerly, if there was already a non-symlink file
......@@ -328,9 +328,8 @@ named DIR/.#FILE, Emacs fell back on the lock names DIR/.#FILE.0
through DIR/.#FILE.9. These fallbacks have been removed, so that
Emacs now no longer locks DIR/FILE in that case.
On MS-Windows the lock is a regular file DIR/.#-FILE, not a symlink.
MS-Windows and non-MS-Windows implementations of Emacs ignore each
other's locks.
On file systems that do not support symbolic links, the lock is now a
regular file with contents being what would have been in the symlink.
** The 9th element returned by `file-attributes' is now unspecified.
Formerly, it was t if the file's gid would change if file were deleted
......
2013-03-05 Paul Eggert <eggert@cs.ucla.edu>
FILE's lock is now always .#FILE and may be a regular file (Bug#13807).
* inc/unistd.h (O_NOFOLLOW): New macro.
2013-03-04 Juanma Barranquero <lekktu@gmail.com>
* config.nt: Sync with autogen/config.in.
......
......@@ -27,8 +27,9 @@ extern int faccessat (int, char const *, int, int);
#define AT_EACCESS 4
#define AT_SYMLINK_NOFOLLOW 4096
#define O_NOCTTY 0
#define O_IGNORE_CTTY 0
#define O_NOCTTY 0
#define O_NOFOLLOW 0
/* This is normally on stdlib.h, but we don't override that header. */
extern int unsetenv (const char *);
......
2013-03-05 Paul Eggert <eggert@cs.ucla.edu>
FILE's lock is now always .#FILE and may be a regular file (Bug#13807).
* filelock.c: Include <c-ctype.h>.
(MAX_LFINFO): New top-level constant.
(lock_info_type): Remove members pid, boot_time. Add members at,
dot, colon. Change user member to be the entire buffer, not a
pointer. This allows us to handle the case where a foreign
pid or boot time exceeds the local range. All uses changed.
(LINKS_MIGHT_NOT_WORK): New constant.
(FREE_LOCK_INFO): Remove, as the pieces no longer need freeing.
(defined_WINDOWSNT): Remove.
(MAKE_LOCK_NAME, file_in_lock_file_name):
Always use .#FILE (not .#-FILE) for the file lock,
even if it is a regular file.
(rename_lock_file): New function.
(create_lock_file): Use it.
(create_lock_file, read_lock_data):
Prefer a symbolic link for the lock file, falling back on a
regular file if symlinks don't work. Do not try to create
symlinks on MS-Windows, due to security hassles. Stick with
POSIXish functions (open, read, write, close, fchmod, readlink, symlink,
link, rename, unlink, mkstemp) when creating locks, as a GNUish
host may be using a Windowsish file system, and cannot use
MS-Windows-only system calls. Fall back on mktemp if mkstemp
doesn't work. Don't fail merely because of a symlink-contents
length limit in the current file system; fall back on regular
files. Increase the symlink contents length limit to 8 KiB, this
should be big enough for any real use and doesn't crunch the
stack.
(create_lock_file, lock_file_1, read_lock_data):
Simplify allocation of lock file buffers now that they fit in 8 KiB.
(lock_file_1): Return error number, not bool. All callers changed.
(ELOOP): New macro, if not already defined.
(read_lock_data): Return size of lock file contents, not Lisp object.
All callers changed. Handle a race condition if some other process
replaces a regular-file lock with a symlink lock or vice versa,
while we're trying to read the lock.
(current_lock_owner): Parse contents more carefully, to help avoid
confusing a regular-file lock with some other application's use
of the file. Check for lock file contents being too long, or
not parsing correctly.
(current_lock_owner, lock_file):
Allow foreign pid and boot times that exceed the local range.
(current_lock_owner, lock_if_free, lock_file):
Simplify allocation of lock file contents.
* w32.c (sys_rename_replace): New function, containing most of
the contents of the old sys_rename.
(sys_rename): Use it.
(fchmod): New dummy function.
* w32.h (sys_rename_replace, fchmod): New decls.
2013-03-05 Eli Zaretskii <eliz@gnu.org>
* bidi.c (bidi_resolve_explicit_1): Don't call CHAR_TO_BYTE or
......
......@@ -38,6 +38,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <c-ctype.h>
#include "lisp.h"
#include "character.h"
#include "buffer.h"
......@@ -64,7 +66,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define WTMP_FILE "/var/log/wtmp"
#endif
/* On non-MS-Windows systems, use a symbolic link to represent a lock.
/* Normally use a symbolic link to represent a lock.
The strategy: to lock a file FN, create a symlink .#FN in FN's
directory, with link data `user@host.pid'. This avoids a single
mount (== failure) point for lock files.
......@@ -100,10 +102,21 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
--karl@cs.umb.edu/karl@hq.ileaf.com.
On MS-Windows, symbolic links do not work well, so instead of a
symlink .#FN -> 'user@host.pid', the lock is a regular file .#-FN
with contents 'user@host.pid'. MS-Windows and non-MS-Windows
versions of Emacs ignore each other's locks. */
On some file systems, notably those of MS-Windows, symbolic links
do not work well, so instead of a symlink .#FN -> 'user@host.pid',
the lock is a regular file .#FN with contents 'user@host.pid'. To
establish a lock, a nonce file is created and then renamed to .#FN.
On MS-Windows this renaming is atomic unless the lock is forcibly
acquired. On other systems the renaming is atomic if the lock is
forcibly acquired; if not, the renaming is done via hard links,
which is good enough for lock-file purposes.
To summarize, race conditions can occur with either:
* Forced locks on MS-Windows systems.
* Non-forced locks on non-MS-Windows systems that support neither
hard nor symbolic links. */
/* Return the time of the last system boot. */
......@@ -284,30 +297,31 @@ get_boot_time_1 (const char *filename, bool newest)
}
#endif /* BOOT_TIME */
/* An arbitrary limit on lock contents length. 8 K should be plenty
big enough in practice. */
enum { MAX_LFINFO = 8 * 1024 };
/* Here is the structure that stores information about a lock. */
typedef struct
{
char *user;
char *host;
pid_t pid;
time_t boot_time;
} lock_info_type;
/* Free the two dynamically-allocated pieces in PTR. */
#define FREE_LOCK_INFO(i) do { xfree ((i).user); xfree ((i).host); } while (0)
/* Location of '@', '.', ':' in USER. If there's no colon, COLON
points to the end of USER. */
char *at, *dot, *colon;
#ifdef WINDOWSNT
enum { defined_WINDOWSNT = 1 };
#else
enum { defined_WINDOWSNT = 0 };
#endif
/* Lock file contents USER@HOST.PID with an optional :BOOT_TIME
appended. This memory is used as a lock file contents buffer, so
it needs room for MAX_LFINFO + 1 bytes. A string " (pid NNNN)"
may be appended to the USER@HOST while generating a diagnostic,
so make room for its extra bytes (as opposed to ".NNNN") too. */
char user[MAX_LFINFO + 1 + sizeof " (pid )" - sizeof "."];
} lock_info_type;
/* Write the name of the lock file for FNAME into LOCKNAME. Length
will be that of FNAME plus two more for the leading ".#",
plus one for "-" if MS-Windows, plus one for the null. */
will be that of FNAME plus two more for the leading ".#", plus one
for the null. */
#define MAKE_LOCK_NAME(lockname, fname) \
(lockname = SAFE_ALLOCA (SBYTES (fname) + 2 + defined_WINDOWSNT + 1), \
(lockname = SAFE_ALLOCA (SBYTES (fname) + 2 + 1), \
fill_in_lock_file_name (lockname, fname))
static void
......@@ -319,70 +333,131 @@ fill_in_lock_file_name (char *lockfile, Lisp_Object fn)
memcpy (lockfile, SSDATA (fn), dirlen);
lockfile[dirlen] = '.';
lockfile[dirlen + 1] = '#';
if (defined_WINDOWSNT)
lockfile[dirlen + 2] = '-';
strcpy (lockfile + dirlen + 2 + defined_WINDOWSNT, base);
strcpy (lockfile + dirlen + 2, base);
}
/* For some reason Linux kernels return EPERM on file systems that do
not support hard or symbolic links. This symbol documents the quirk.
There is no way to tell whether a symlink call fails due to
permissions issues or because links are not supported, but luckily
the lock file code should work either way. */
enum { LINKS_MIGHT_NOT_WORK = EPERM };
/* Rename OLD to NEW. If FORCE, replace any existing NEW.
It is OK if there are temporarily two hard links to OLD.
Return 0 if successful, -1 (setting errno) otherwise. */
static int
create_lock_file (char *lfname, char *lock_info_str, bool force)
rename_lock_file (char const *old, char const *new, bool force)
{
int err;
#ifdef WINDOWSNT
/* Symlinks are supported only by latest versions of Windows, and
creating them is a privileged operation that often triggers UAC
elevation prompts. Therefore, instead of using symlinks, we
create a regular file with the lock info written as its
contents. */
{
/* Deny everybody else any kind of access to the file until we are
done writing it and close the handle. This makes the entire
open/write/close operation atomic, as far as other WINDOWSNT
processes are concerned. */
int fd = _sopen (lfname,
_O_WRONLY | _O_BINARY | _O_CREAT | _O_EXCL | _O_NOINHERIT,
_SH_DENYRW, S_IREAD | S_IWRITE);
if (fd < 0 && errno == EEXIST && force)
fd = _sopen (lfname, _O_WRONLY | _O_BINARY | _O_TRUNC |_O_NOINHERIT,
_SH_DENYRW, S_IREAD | S_IWRITE);
if (fd >= 0)
{
ssize_t lock_info_len = strlen (lock_info_str);
return sys_rename_replace (old, new, force);
#else
if (! force)
{
struct stat st;
err = 0;
if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len)
err = -1;
if (emacs_close (fd))
err = -1;
}
else
err = -1;
}
if (link (old, new) == 0)
return unlink (old) == 0 || errno == ENOENT ? 0 : -1;
if (errno != ENOSYS && errno != LINKS_MIGHT_NOT_WORK)
return -1;
/* 'link' does not work on this file system. This can occur on
a GNU/Linux host mounting a FAT32 file system. Fall back on
'rename' after checking that NEW does not exist. There is a
potential race condition since some other process may create
NEW immediately after the existence check, but it's the best
we can portably do here. */
if (lstat (new, &st) == 0 || errno == EOVERFLOW)
{
errno = EEXIST;
return -1;
}
if (errno != ENOENT)
return -1;
}
return rename (old, new);
#endif
}
/* Create the lock file FILE with contents CONTENTS. Return 0 if
successful, an errno value on failure. If FORCE, remove any
existing FILE if necessary. */
static int
create_lock_file (char *lfname, char *lock_info_str, bool force)
{
#ifdef WINDOWSNT
/* Symlinks are supported only by later versions of Windows, and
creating them is a privileged operation that often triggers
User Account Control elevation prompts. Avoid the problem by
pretending that 'symlink' does not work. */
int err = ENOSYS;
#else
err = symlink (lock_info_str, lfname);
if (err != 0 && errno == EEXIST && force)
int err = symlink (lock_info_str, lfname) == 0 ? 0 : errno;
#endif
if (err == EEXIST && force)
{
unlink (lfname);
err = symlink (lock_info_str, lfname);
err = symlink (lock_info_str, lfname) == 0 ? 0 : errno;
}
if (err == ENOSYS || err == LINKS_MIGHT_NOT_WORK || err == ENAMETOOLONG)
{
static char const nonce_base[] = ".#-emacsXXXXXX";
char *last_slash = strrchr (lfname, '/');
ptrdiff_t lfdirlen = last_slash + 1 - lfname;
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
if (fd < 0)
err = errno;
else
{
ptrdiff_t 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))
err = errno;
if (emacs_close (fd) != 0)
err = errno;
if (!err && rename_lock_file (nonce, lfname, force) != 0)
err = errno;
if (err)
unlink (nonce);
}
SAFE_FREE ();
}
return err;
}
/* Lock the lock file named LFNAME.
If FORCE, do so even if it is already locked.
Return true if successful. */
Return 0 if successful, an error number on failure. */
static bool
static int
lock_file_1 (char *lfname, bool force)
{
int err;
int symlink_errno;
USE_SAFE_ALLOCA;
/* Call this first because it can GC. */
printmax_t boot = get_boot_time ();
......@@ -390,20 +465,16 @@ lock_file_1 (char *lfname, bool force)
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);
char lock_info_str[MAX_LFINFO + 1];
printmax_t pid = getpid ();
esprintf (lock_info_str, boot ? "%s@%s.%"pMd":%"pMd : "%s@%s.%"pMd,
user_name, host_name, pid, boot);
err = create_lock_file (lfname, lock_info_str, force);
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))
return ENAMETOOLONG;
symlink_errno = errno;
SAFE_FREE ();
errno = symlink_errno;
return err == 0;
return create_lock_file (lfname, lock_info_str, force);
}
/* Return true if times A and B are no more than one second apart. */
......@@ -414,32 +485,44 @@ within_one_second (time_t a, time_t b)
return (a - b >= -1 && a - b <= 1);
}
static Lisp_Object
read_lock_data (char *lfname)
{
#ifndef WINDOWSNT
return emacs_readlinkat (AT_FDCWD, lfname);
#else
int fd = emacs_open (lfname, O_RDONLY | O_BINARY, S_IREAD);
ssize_t nbytes;
/* 256 chars for user, 1024 chars for host, 10 digits for each of 2 int's. */
enum { MAX_LFINFO = 256 + 1024 + 10 + 10 + 2 };
char lfinfo[MAX_LFINFO + 1];
/* On systems lacking ELOOP, test for an errno value that shouldn't occur. */
#ifndef ELOOP
# define ELOOP (-1)
#endif
if (fd < 0)
return Qnil;
/* Read the data for the lock file LFNAME into LFINFO. Read at most
MAX_LFINFO + 1 bytes. Return the number of bytes read, or -1
(setting errno) on error. */
nbytes = emacs_read (fd, lfinfo, MAX_LFINFO);
emacs_close (fd);
static ptrdiff_t
read_lock_data (char *lfname, char lfinfo[MAX_LFINFO + 1])
{
ptrdiff_t nbytes;
if (nbytes > 0)
while ((nbytes = readlinkat (AT_FDCWD, lfname, lfinfo, MAX_LFINFO + 1)) < 0
&& errno == EINVAL)
{
lfinfo[nbytes] = '\0';
return build_string (lfinfo);
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);
int read_errno = errno;
if (emacs_close (fd) != 0)
return -1;
errno = read_errno;
return read_bytes;
}
if (errno != ELOOP)
return -1;
/* readlinkat saw a non-symlink, but emacs_open saw a symlink.
The former must have been removed and replaced by the latter.
Try again. */
QUIT;
}
else
return Qnil;
#endif
return nbytes;
}
/* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete,
......@@ -451,83 +534,78 @@ static int
current_lock_owner (lock_info_type *owner, char *lfname)
{
int ret;
ptrdiff_t len;
lock_info_type local_owner;
intmax_t n;
char *at, *dot, *colon;
Lisp_Object lfinfo_object = read_lock_data (lfname);
char *lfinfo;
struct gcpro gcpro1;
/* If nonexistent lock file, all is well; otherwise, got strange error. */
if (NILP (lfinfo_object))
return errno == ENOENT ? 0 : -1;
lfinfo = SSDATA (lfinfo_object);
ptrdiff_t lfinfolen;
intmax_t pid, boot_time;
char *at, *dot, *lfinfo_end;
/* Even if the caller doesn't want the owner info, we still have to
read it to determine return value. */
if (!owner)
owner = &local_owner;
/* If nonexistent lock file, all is well; otherwise, got strange error. */
lfinfolen = read_lock_data (lfname, owner->user);
if (lfinfolen < 0)
return errno == ENOENT ? 0 : -1;
if (MAX_LFINFO < lfinfolen)
return -1;
owner->user[lfinfolen] = 0;
/* Parse USER@HOST.PID:BOOT_TIME. If can't parse, return -1. */
/* The USER is everything before the last @. */
at = strrchr (lfinfo, '@');
dot = strrchr (lfinfo, '.');
if (!at || !dot)
owner->at = at = memrchr (owner->user, '@', lfinfolen);
if (!at)
return -1;
owner->dot = dot = strrchr (at, '.');
if (!dot)
return -1;
len = at - lfinfo;
GCPRO1 (lfinfo_object);
owner->user = xmalloc (len + 1);
memcpy (owner->user, lfinfo, len);
owner->user[len] = 0;
/* The PID is everything from the last `.' to the `:'. */
if (! c_isdigit (dot[1]))
return -1;
errno = 0;
n = strtoimax (dot + 1, NULL, 10);
owner->pid =
((0 <= n && n <= TYPE_MAXIMUM (pid_t)
&& (TYPE_MAXIMUM (pid_t) < INTMAX_MAX || errno != ERANGE))
? n : 0);
pid = strtoimax (dot + 1, &owner->colon, 10);
if (errno == ERANGE)
pid = -1;
colon = strchr (dot + 1, ':');
/* After the `:', if there is one, comes the boot time. */
n = 0;
if (colon)
switch (owner->colon[0])
{
errno = 0;
n = strtoimax (colon + 1, NULL, 10);
case 0:
boot_time = 0;
lfinfo_end = owner->colon;
break;
case ':':
if (! c_isdigit (owner->colon[1]))
return -1;
boot_time = strtoimax (owner->colon + 1, &lfinfo_end, 10);
break;
default:
return -1;
}
owner->boot_time =
((0 <= n && n <= TYPE_MAXIMUM (time_t)
&& (TYPE_MAXIMUM (time_t) < INTMAX_MAX || errno != ERANGE))
? n : 0);
/* The host is everything in between. */
len = dot - at - 1;
owner->host = xmalloc (len + 1);
memcpy (owner->host, at + 1, len);
owner->host[len] = 0;
/* We're done looking at the link info. */
UNGCPRO;
if (lfinfo_end != owner->user + lfinfolen)
return -1;
/* On current host? */
if (STRINGP (Fsystem_name ())
&& strcmp (owner->host, SSDATA (Fsystem_name ())) == 0)
if (STRINGP (Vsystem_name)
&& dot - (at + 1) == SBYTES (Vsystem_name)
&& memcmp (at + 1, SSDATA (Vsystem_name), SBYTES (Vsystem_name)) == 0)
{
if (owner->pid == getpid ())
if (pid == getpid ())
ret = 2; /* We own it. */
else if (owner->pid > 0
&& (kill (owner->pid, 0) >= 0 || errno == EPERM)
&& (owner->boot_time == 0
|| within_one_second (owner->boot_time, get_boot_time ())))
else if (0 < pid && pid <= TYPE_MAXIMUM (pid_t)
&& (kill (pid, 0) >= 0 || errno == EPERM)
&& (boot_time == 0
|| (boot_time <= TYPE_MAXIMUM (time_t)
&& within_one_second (boot_time, get_boot_time ()))))
ret = 1; /* An existing process on this machine owns it. */
/* The owner process is dead or has a strange pid (<=0), so try to
/* The owner process is dead or has a strange pid, so try to
zap the lockfile. */
else if (unlink (lfname) < 0)
ret = -1;
else
ret = 0;
return unlink (lfname);
}
else
{ /* If we wanted to support the check for stale locks on remote machines,
......@@ -535,11 +613,6 @@ current_lock_owner (lock_info_type *owner, char *lfname)
ret = 1;
}
/* Avoid garbage. */
if (owner == &local_owner || ret <= 0)
{
FREE_LOCK_INFO (*owner);
}
return ret;
}
......@@ -551,29 +624,25 @@ current_lock_owner (lock_info_type *owner, char *lfname)
Return -1 if cannot lock for any other reason. */
static int
lock_if_free (lock_info_type *clasher, register char *lfname)
lock_if_free (lock_info_type *clasher, char *lfname)
{
while (! lock_file_1 (lfname, 0))
int err;
while ((err = lock_file_1 (lfname, 0)) == EEXIST)
{
int locker;