]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lib: (pwdutils.c) improve error return protocol for callers
authorChristian Goeschel Ndjomouo <cgoesc2@wgu.edu>
Wed, 8 Apr 2026 04:47:49 +0000 (00:47 -0400)
committerChristian Goeschel Ndjomouo <cgoesc2@wgu.edu>
Thu, 9 Apr 2026 14:11:09 +0000 (10:11 -0400)
In some cases libc does not properly set errno when no passwd
or group entry was found by getpwnam or getgrnam like functions.
This becomes an issue when callers have to provide coherent error
messages with err(). Therefore, let us improve the errno protocol
in internal wrapper functions for the above mentioned and set errno
 when libc does not.

Signed-off-by: Christian Goeschel Ndjomouo <cgoesc2@wgu.edu>
lib/pwdutils.c

index 3f9b83b76923532445224ac4a363f18236b3e703..64a7af6f66eaaefc2de747c67ab2337817da673f 100644 (file)
@@ -166,34 +166,44 @@ char *xgetlogin(void)
  *
  * If @result is not NULL, it will always be set to the parsed GID on success
  * or (gid_t) -1 on failure.
+ *
+ * On failure NULL is returned and errno is set to indicate the error.
  */
 struct group *ul_getgrp_str(const char *str, gid_t *result)
 {
-        int rc;
-        uint64_t num;
-        struct group *gr;
-
-        if (result)
-                *result = (gid_t) -1;
-
-        rc = ul_strtou64(str, &num, 10);
-        if (rc == -ERANGE)
-                return NULL;
-        if (rc == -EINVAL) {
-                errno = 0;
-                gr = getgrnam(str);
-                if (gr && result)
-                        *result = gr->gr_gid;
-                return gr;
-        }
-        if (num > MAX_OF_UINT_TYPE(gid_t)) {
-                errno = ERANGE;
-                return NULL;
-        }
-
-        if (result)
-                *result = (gid_t) num;
-        return getgrgid((gid_t) num);
+       int rc;
+       uint64_t num;
+       struct group *gr;
+
+       if (result)
+               *result = (gid_t) -1;
+
+       rc = ul_strtou64(str, &num, 10);
+       if (rc == -ERANGE || num > MAX_OF_UINT_TYPE(gid_t)) {
+               errno = ERANGE;
+               return NULL;
+       }
+
+       /* maybe an actual name */
+       if (rc == -EINVAL) {
+               errno = 0;
+               gr = getgrnam(str);
+               if (gr && result)
+                       *result = gr->gr_gid;
+               else if (!gr && !errno)
+                       errno = EINVAL;
+               return gr;
+       }
+
+       if (result)
+               *result = (gid_t) num;
+
+       errno = 0;
+       gr = getgrgid((gid_t) num);
+       if (!gr && !errno)
+               errno = EINVAL;
+
+       return gr;
 }
 
 /*
@@ -201,34 +211,44 @@ struct group *ul_getgrp_str(const char *str, gid_t *result)
  *
  * If @result is not NULL, it will always be set to the parsed UID on success
  * or (uid_t) -1 on failure.
+ *
+ * On failure NULL is returned and errno is set to indicate the error.
  */
 struct passwd *ul_getuserpw_str(const char *str, uid_t *result)
 {
-        int rc;
-        uint64_t num;
-        struct passwd *pw;
-
-        if (result)
-                *result = (uid_t) -1;
-
-        rc = ul_strtou64(str, &num, 10);
-        if (rc == -ERANGE)
-                return NULL;
-        if (rc == -EINVAL) {
-                errno = 0;
-                pw = getpwnam(str);
-                if (pw && result)
-                        *result = pw->pw_uid;
-                return pw;
-        }
-        if (num > MAX_OF_UINT_TYPE(uid_t)) {
-                errno = ERANGE;
-                return NULL;
-        }
-
-        if (result)
-                *result = (uid_t) num;
-        return getpwuid((uid_t) num);
+       int rc;
+       uint64_t num;
+       struct passwd *pw;
+
+       if (result)
+               *result = (uid_t) -1;
+
+       rc = ul_strtou64(str, &num, 10);
+       if (rc == -ERANGE || num > MAX_OF_UINT_TYPE(uid_t)) {
+               errno = ERANGE;
+               return NULL;
+       }
+
+       /* maybe an actual name */
+       if (rc == -EINVAL) {
+               errno = 0;
+               pw = getpwnam(str);
+               if (pw && result)
+                       *result = pw->pw_uid;
+               else if (!pw && !errno)
+                       errno = EINVAL;
+               return pw;
+       }
+
+       if (result)
+               *result = (uid_t) num;
+
+       errno = 0;
+       pw = getpwuid((uid_t) num);
+       if (!pw && !errno)
+               errno = EINVAL;
+
+       return pw;
 }
 
 #ifdef TEST_PROGRAM