Work around Samba bug with ':' in symlink contents

* src/filelock.c (current_lock_owner): When reading the contents
of a lock, treat the UTF-8 for U+F022 as if it were ':' (Bug#24656).
This commit is contained in:
Paul Eggert 2016-10-11 13:06:42 -07:00
parent 5cc3c13d16
commit 1dd54e3eef

View file

@ -72,8 +72,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* 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.
@ -102,13 +103,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
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
@ -289,8 +288,8 @@ enum { MAX_LFINFO = 8 * 1024 };
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
@ -548,7 +547,7 @@ current_lock_owner (lock_info_type *owner, char *lfname)
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;
@ -556,7 +555,8 @@ current_lock_owner (lock_info_type *owner, char *lfname)
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:
@ -564,10 +564,19 @@ current_lock_owner (lock_info_type *owner, char *lfname)
lfinfo_end = owner->colon;
break;
case ':':
if (! c_isdigit (owner->colon[1]))
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_time = strtoimax (owner->colon + 1, &lfinfo_end, 10);
boot += 2;
/* Fall through. */
case ':':
if (! c_isdigit (boot[0]))
return -1;
boot_time = strtoimax (boot, &lfinfo_end, 10);
break;
default: