Subject: bug#53631: coreutils id(1) incorrect behavior

From: Pádraig Brady <[email-masked]>
Date: Sat, 12 Feb 2022 21:30:15 +0000

On 04/02/2022 22:59, Paul Eggert wrote:
> Thanks for the bug report. I installed the attached patch, which I hope
> fixes things for you, and am boldly closing the bug report.
> 
> This fix depends on the latest lib/userspec.c from Gnulib; see
> <https://lists.gnu.org/r/bug-gnulib/2022-02/msg00000.html>.

I'll apply the following later to ensure
chown --verbose continues to list numeric ID info.

cheers,
Pádraig

From 8113e620d950cc4beab38dfab8354852b778c583 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <[email-masked]>
Date: Sat, 12 Feb 2022 21:20:21 +0000
Subject: [PATCH] chown,chgrp: reinstate numeric id output in -v messages

since gnulib commit ff208d546a,
related to coreutils commit v9.0-143-gabde15969
we no longer maintain numeric IDs through chopt->{user,group}_name.
Therefore we need to adjust to ensure tests/chown/basic.sh passes.

* src/chown-core.c (uid_to_str, gid_to_str): New helper functions
to convert numeric id to string.
(change_file_owner): Use the above new functions to pass
numeric ids to describe_change().
---
 src/chown-core.c | 44 +++++++++++++++++++++++++++++++++++---------
 1 file changed, 35 insertions(+), 9 deletions(-)

diff --git a/src/chown-core.c b/src/chown-core.c
index f7d03297e..428c96de9 100644
--- a/src/chown-core.c
+++ b/src/chown-core.c
@@ -73,6 +73,28 @@ chopt_free (struct Chown_option *chopt)
   free (chopt->group_name);
 }
 
+/* Convert the numeric user-id, UID, to a string stored in xmalloc'd memory,
+   and return it.  Use the decimal representation of the ID.  */
+
+static char *
+uid_to_str (uid_t uid)
+{
+  char buf[INT_BUFSIZE_BOUND (intmax_t)];
+  return xstrdup (TYPE_SIGNED (uid_t) ? imaxtostr (uid, buf)
+                  : umaxtostr (uid, buf));
+}
+
+/* Convert the numeric group-id, GID, to a string stored in xmalloc'd memory,
+   and return it.  Use the decimal representation of the ID.  */
+
+static char *
+gid_to_str (gid_t gid)
+{
+  char buf[INT_BUFSIZE_BOUND (intmax_t)];
+  return xstrdup (TYPE_SIGNED (gid_t) ? imaxtostr (gid, buf)
+                  : umaxtostr (gid, buf));
+}
+
 /* Convert the numeric group-id, GID, to a string stored in xmalloc'd memory,
    and return it.  If there's no corresponding group name, use the decimal
    representation of the ID.  */
@@ -80,11 +102,8 @@ chopt_free (struct Chown_option *chopt)
 extern char *
 gid_to_name (gid_t gid)
 {
-  char buf[INT_BUFSIZE_BOUND (intmax_t)];
   struct group *grp = getgrgid (gid);
-  return xstrdup (grp ? grp->gr_name
-                  : TYPE_SIGNED (gid_t) ? imaxtostr (gid, buf)
-                  : umaxtostr (gid, buf));
+  return grp ? xstrdup (grp->gr_name) : gid_to_str (gid);
 }
 
 /* Convert the numeric user-id, UID, to a string stored in xmalloc'd memory,
@@ -94,11 +113,8 @@ gid_to_name (gid_t gid)
 extern char *
 uid_to_name (uid_t uid)
 {
-  char buf[INT_BUFSIZE_BOUND (intmax_t)];
   struct passwd *pwd = getpwuid (uid);
-  return xstrdup (pwd ? pwd->pw_name
-                  : TYPE_SIGNED (uid_t) ? imaxtostr (uid, buf)
-                  : umaxtostr (uid, buf));
+  return pwd ? xstrdup (pwd->pw_name) : uid_to_str (uid);
 }
 
 /* Allocate a string representing USER and GROUP.  */
@@ -484,11 +500,21 @@ change_file_owner (FTS *fts, FTSENT *ent,
              : CH_SUCCEEDED);
           char *old_usr = file_stats ? uid_to_name (file_stats->st_uid) : NULL;
           char *old_grp = file_stats ? gid_to_name (file_stats->st_gid) : NULL;
+          char *new_usr = chopt->user_name
+                          ? chopt->user_name : uid != -1
+                                               ? uid_to_str (uid) : NULL;
+          char *new_grp = chopt->group_name
+                          ? chopt->group_name : gid != -1
+                                               ? gid_to_str (gid) : NULL;
           describe_change (file_full_name, ch_status,
                            old_usr, old_grp,
-                           chopt->user_name, chopt->group_name);
+                           new_usr, new_grp);
           free (old_usr);
           free (old_grp);
+          if (new_usr != chopt->user_name)
+            free (new_usr);
+          if (new_grp != chopt->group_name)
+            free (new_grp);
         }
     }
 
-- 
2.26.2