]> git.eshelyaron.com Git - emacs.git/commitdiff
Refactor current_lock_owner
authorPaul Eggert <eggert@cs.ucla.edu>
Thu, 15 Aug 2024 20:17:24 +0000 (13:17 -0700)
committerEshel Yaron <me@eshelyaron.com>
Fri, 16 Aug 2024 14:04:45 +0000 (16:04 +0200)
* src/filelock.c (current_lock_owner): Refactor to make further
changes easier.  This should not affect behavior.

(cherry picked from commit 775fa8443faa3d7f5ce7f7d0aa6e6fb53321715a)

src/filelock.c

index cdf9e6f0ffcfd578fd03944d1d83522ea96acb56..c68aacc46fbc3b1c276a8e4d4ec866e9c18844d3 100644 (file)
@@ -386,9 +386,6 @@ static int
 current_lock_owner (lock_info_type *owner, Lisp_Object lfname)
 {
   lock_info_type local_owner;
-  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.  */
@@ -396,104 +393,112 @@ current_lock_owner (lock_info_type *owner, Lisp_Object lfname)
     owner = &local_owner;
 
   /* If nonexistent lock file, all is well; otherwise, got strange error. */
-  lfinfolen = read_lock_data (SSDATA (lfname), owner->user);
+  ptrdiff_t lfinfolen = read_lock_data (SSDATA (lfname), owner->user);
   if (lfinfolen < 0)
     return errno == ENOENT || errno == ENOTDIR ? 0 : errno;
-  if (MAX_LFINFO < lfinfolen)
-    return ENAMETOOLONG;
-  owner->user[lfinfolen] = 0;
-
-  /* Parse USER@HOST.PID:BOOT_TIME.  If can't parse, return EINVAL.  */
-  /* The USER is everything before the last @.  */
-  owner->at = at = memrchr (owner->user, '@', lfinfolen);
-  if (!at)
-    return EINVAL;
-  owner->dot = dot = strrchr (at, '.');
-  if (!dot)
-    return EINVAL;
-
-  /* The PID is everything from the last '.' to the ':' or equivalent.  */
-  if (! integer_prefixed (dot + 1))
-    return EINVAL;
-  errno = 0;
-  pid = strtoimax (dot + 1, &owner->colon, 10);
-  if (errno == ERANGE)
-    pid = -1;
-
-  /* After the ':' or equivalent, if there is one, comes the boot time.  */
-  char *boot = owner->colon + 1;
-  switch (owner->colon[0])
+
+  /* Examine lock file contents.  */
+  if (true)
     {
-    case 0:
-      boot_time = 0;
-      lfinfo_end = owner->colon;
-      break;
+      if (MAX_LFINFO < lfinfolen)
+       return ENAMETOOLONG;
+      owner->user[lfinfolen] = 0;
 
-    case '\357':
-      /* Treat "\357\200\242" (U+F022 in UTF-8) as if it were ":" (Bug#24656).
-        This works around a bug in the Linux CIFS kernel client, which can
-        mistakenly transliterate ':' to U+F022 in symlink contents.
-        See <https://bugzilla.redhat.com/show_bug.cgi?id=1384153>.  */
-      if (! (boot[0] == '\200' && boot[1] == '\242'))
+      /* Parse USER@HOST.PID:BOOT_TIME.  If can't parse, return EINVAL.  */
+      /* The USER is everything before the last @.  */
+      char *at = memrchr (owner->user, '@', lfinfolen);
+      if (!at)
        return EINVAL;
-      boot += 2;
-      FALLTHROUGH;
-    case ':':
-      if (! integer_prefixed (boot))
+      owner->at = at;
+      char *dot = strrchr (at, '.');
+      if (!dot)
        return EINVAL;
-      boot_time = strtoimax (boot, &lfinfo_end, 10);
-      break;
+      owner->dot = dot;
 
-    default:
-      return EINVAL;
-    }
-  if (lfinfo_end != owner->user + lfinfolen)
-    return EINVAL;
-
-  char *linkhost = at + 1;
-  ptrdiff_t linkhostlen = dot - linkhost;
-  Lisp_Object system_name = Fsystem_name ();
-  /* If `system-name' returns nil, that means we're in a
-     --no-build-details Emacs, and the name part of the link (e.g.,
-     .#test.txt -> larsi@.118961:1646577954) is an empty string.  */
-  bool on_current_host;
-  if (NILP (system_name))
-    on_current_host = linkhostlen == 0;
-  else
-    {
-      on_current_host = linkhostlen == SBYTES (system_name);
-      if (on_current_host)
+      /* The PID is everything from the last '.' to the ':' or equivalent.  */
+      if (! integer_prefixed (dot + 1))
+       return EINVAL;
+      errno = 0;
+      intmax_t pid = strtoimax (dot + 1, &owner->colon, 10);
+      if (errno == ERANGE)
+       pid = -1;
+
+      /* After the ':' or equivalent, if there is one, comes the boot time.  */
+      intmax_t boot_time;
+      char *boot = owner->colon + 1, *lfinfo_end;
+      switch (owner->colon[0])
        {
-         /* Protect against the extremely unlikely case of the host
-            name containing '@'.  */
-         char *sysname = SSDATA (system_name);
-         for (ptrdiff_t i = 0; i < linkhostlen; i++)
-           if (linkhost[i] != (sysname[i] == '@' ? '-' : sysname[i]))
-             {
-               on_current_host = false;
-               break;
-             }
+       case 0:
+         boot_time = 0;
+         lfinfo_end = owner->colon;
+         break;
+
+       case '\357':
+         /* Treat "\357\200\242" (U+F022 in UTF-8) like ":" (Bug#24656).
+            This works around a bug in the Linux CIFS kernel client, which can
+            mistakenly transliterate ':' to U+F022 in symlink contents.
+            See <https://bugzilla.redhat.com/show_bug.cgi?id=1384153>.  */
+         if (! (boot[0] == '\200' && boot[1] == '\242'))
+           return EINVAL;
+         boot += 2;
+         FALLTHROUGH;
+       case ':':
+         if (! integer_prefixed (boot))
+           return EINVAL;
+         boot_time = strtoimax (boot, &lfinfo_end, 10);
+         break;
+
+       default:
+         return EINVAL;
        }
-    }
-  if (on_current_host)
-    {
-      if (pid == getpid ())
-        return I_OWN_IT;
-      else if (VALID_PROCESS_ID (pid)
-               && (kill (pid, 0) >= 0 || errno == EPERM)
-              && (boot_time == 0
-                  || within_one_second (boot_time, get_boot_sec ())))
-        return ANOTHER_OWNS_IT;
-      /* The owner process is dead or has a strange pid, so try to
-         zap the lockfile.  */
+      if (lfinfo_end != owner->user + lfinfolen)
+       return EINVAL;
+
+      char *linkhost = at + 1;
+      ptrdiff_t linkhostlen = dot - linkhost;
+      Lisp_Object system_name = Fsystem_name ();
+      /* If `system-name' returns nil, that means we're in a
+        --no-build-details Emacs, and the name part of the link (e.g.,
+        .#test.txt -> larsi@.118961:1646577954) is an empty string.  */
+      bool on_current_host;
+      if (NILP (system_name))
+       on_current_host = linkhostlen == 0;
       else
-        return emacs_unlink (SSDATA (lfname)) < 0 ? errno : 0;
-    }
-  else
-    { /* If we wanted to support the check for stale locks on remote machines,
-         here's where we'd do it.  */
-      return ANOTHER_OWNS_IT;
+       {
+         on_current_host = linkhostlen == SBYTES (system_name);
+         if (on_current_host)
+           {
+             /* Protect against the extremely unlikely case of the host
+                name containing '@'.  */
+             char *sysname = SSDATA (system_name);
+             for (ptrdiff_t i = 0; i < linkhostlen; i++)
+               if (linkhost[i] != (sysname[i] == '@' ? '-' : sysname[i]))
+                 {
+                   on_current_host = false;
+                   break;
+                 }
+           }
+       }
+      if (!on_current_host)
+       {
+         /* Not on current host.  If we wanted to support the check for
+            stale locks on remote machines, here's where we'd do it.  */
+         return ANOTHER_OWNS_IT;
+       }
+
+      if (pid == getpid ())
+       return I_OWN_IT;
+
+      if (VALID_PROCESS_ID (pid)
+         && ! (kill (pid, 0) < 0 && errno != EPERM)
+         && (boot_time == 0
+             || within_one_second (boot_time, get_boot_sec ())))
+       return ANOTHER_OWNS_IT;
     }
+
+  /* The owner process is dead or has a strange pid.
+     Try to zap the lockfile.  */
+  return emacs_unlink (SSDATA (lfname)) < 0 ? errno : 0;
 }
 
 \f