diff options
Diffstat (limited to 'sysdeps/unix/sysv/linux/getlogin_r.c')
-rw-r--r-- | sysdeps/unix/sysv/linux/getlogin_r.c | 51 |
1 files changed, 26 insertions, 25 deletions
diff --git a/sysdeps/unix/sysv/linux/getlogin_r.c b/sysdeps/unix/sysv/linux/getlogin_r.c index 408907f162..14587712a7 100644 --- a/sysdeps/unix/sysv/linux/getlogin_r.c +++ b/sysdeps/unix/sysv/linux/getlogin_r.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2016 Free Software Foundation, Inc. +/* Copyright (C) 2010-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -18,6 +18,7 @@ #include <pwd.h> #include <unistd.h> #include <not-cancel.h> +#include <scratch_buffer.h> #define STATIC static static int getlogin_r_fd0 (char *name, size_t namesize); @@ -34,16 +35,16 @@ int attribute_hidden __getlogin_r_loginuid (char *name, size_t namesize) { - int fd = open_not_cancel_2 ("/proc/self/loginuid", O_RDONLY); + int fd = __open_nocancel ("/proc/self/loginuid", O_RDONLY); if (fd == -1) return -1; /* We are reading a 32-bit number. 12 bytes are enough for the text representation. If not, something is wrong. */ char uidbuf[12]; - ssize_t n = TEMP_FAILURE_RETRY (read_not_cancel (fd, uidbuf, + ssize_t n = TEMP_FAILURE_RETRY (__read_nocancel (fd, uidbuf, sizeof (uidbuf))); - close_not_cancel_no_status (fd); + __close_nocancel_nostatus (fd); uid_t uid; char *endp; @@ -54,29 +55,31 @@ __getlogin_r_loginuid (char *name, size_t namesize) endp == uidbuf || *endp != '\0')) return -1; - size_t buflen = 1024; - char *buf = alloca (buflen); - bool use_malloc = false; + /* If there is no login uid, linux sets /proc/self/loginid to the sentinel + value of, (uid_t) -1, so check if that value is set and return early to + avoid making unneeded nss lookups. */ + if (uid == (uid_t) -1) + { + __set_errno (ENXIO); + return ENXIO; + } + struct passwd pwd; struct passwd *tpwd; int result = 0; int res; + struct scratch_buffer tmpbuf; + scratch_buffer_init (&tmpbuf); - while ((res = __getpwuid_r (uid, &pwd, buf, buflen, &tpwd)) == ERANGE) - if (__libc_use_alloca (2 * buflen)) - buf = extend_alloca (buf, buflen, 2 * buflen); - else - { - buflen *= 2; - char *newp = realloc (use_malloc ? buf : NULL, buflen); - if (newp == NULL) - { - result = ENOMEM; - goto out; - } - buf = newp; - use_malloc = true; - } + while ((res = __getpwuid_r (uid, &pwd, + tmpbuf.data, tmpbuf.length, &tpwd)) == ERANGE) + { + if (!scratch_buffer_grow (&tmpbuf)) + { + result = ENOMEM; + goto out; + } + } if (res != 0 || tpwd == NULL) { @@ -95,9 +98,7 @@ __getlogin_r_loginuid (char *name, size_t namesize) memcpy (name, pwd.pw_name, needed); out: - if (use_malloc) - free (buf); - + scratch_buffer_free (&tmpbuf); return result; } |