/* 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.
+ directory, with link data USER@HOST.PID:BOOT. This avoids a single
+ mount (== failure) point for lock files. The :BOOT is omitted if
+ the boot time is not available.
When the host in the lock data is the current host, we can check if
the pid is valid with kill.
This is compatible with the locking scheme used by Interleaf (which
has contributed this implementation for Emacs), and was designed by
- Ethan Jacobson, Kimbo Mundy, and others.
-
- --karl@cs.umb.edu/karl@hq.ileaf.com.
+ Karl Berry, Ethan Jacobson, Kimbo Mundy, and others.
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
+ do not work well, so instead of a symlink .#FN -> USER@HOST.PID:BOOT,
+ the lock is a regular file .#FN with contents USER@HOST.PID:BOOT. 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
typedef struct
{
- /* Location of '@', '.', ':' in USER. If there's no colon, COLON
- points to the end of USER. */
+ /* Location of '@', '.', and ':' (or equivalent) in USER. If there's
+ no colon or equivalent, COLON points to the end of USER. */
char *at, *dot, *colon;
/* Lock file contents USER@HOST.PID with an optional :BOOT_TIME
if (!dot)
return -1;
- /* The PID is everything from the last `.' to the `:'. */
+ /* The PID is everything from the last '.' to the ':' or equivalent. */
if (! c_isdigit (dot[1]))
return -1;
errno = 0;
if (errno == ERANGE)
pid = -1;
- /* After the `:', if there is one, comes the boot time. */
+ /* After the ':' or equivalent, if there is one, comes the boot time. */
+ char *boot = owner->colon + 1;
switch (owner->colon[0])
{
case 0:
lfinfo_end = owner->colon;
break;
+ case '\357':
+ /* Treat "\357\200\242" (U+F022 in UTF-8) as if it were ":".
+ This works around a bug in Samba, which can mistakenly
+ transliterate ':' to U+F022 in symlink contents (Bug#24656).
+ See <https://bugzilla.redhat.com/show_bug.cgi?id=1271407#c8>. */
+ if (! (boot[0] == '\200' && boot[1] == '\242'))
+ return -1;
+ boot += 2;
+ /* Fall through. */
case ':':
- if (! c_isdigit (owner->colon[1]))
+ if (! c_isdigit (boot[0]))
return -1;
- boot_time = strtoimax (owner->colon + 1, &lfinfo_end, 10);
+ boot_time = strtoimax (boot, &lfinfo_end, 10);
break;
default: