+/* On systems lacking ELOOP, test for an errno value that shouldn't occur. */
+#ifndef ELOOP
+# define ELOOP (-1)
+#endif
+
+/* 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. */
+
+static ptrdiff_t
+read_lock_data (char *lfname, char lfinfo[MAX_LFINFO + 1])
+{
+ ptrdiff_t nbytes;
+
+ while ((nbytes = readlinkat (AT_FDCWD, lfname, lfinfo, MAX_LFINFO + 1)) < 0
+ && errno == EINVAL)
+ {
+ int fd = emacs_open (lfname, O_RDONLY | O_BINARY | O_NOFOLLOW, 0);
+ if (0 <= fd)
+ {
+ /* Use read, not emacs_read, since FD isn't unwind-protected. */
+ ptrdiff_t read_bytes = 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;
+ }
+
+ return nbytes;
+}
+