From d02608170e599b1ffbc7c9a22062bae2579d6e36 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 25 Oct 2015 23:20:05 +0100 Subject: util: remove lookup_uid(), replace by uid_to_name() So far we had two pretty much identical calls in user-util.[ch]: lookup_uid() and uid_to_name(). Get rid of the former, in favour of the latter, and while we are at it, rewrite it, to use getpwuid_r() correctly, inside an allocation loop, as POSIX intended. --- src/basic/user-util.c | 102 +++++++++++++++++++++++++++------------------- src/basic/user-util.h | 1 - src/login/logind-dbus.c | 2 +- src/login/logind-utmp.c | 2 +- src/test/test-user-util.c | 53 ++++++++++++++++++++++++ 5 files changed, 114 insertions(+), 46 deletions(-) create mode 100644 src/test/test-user-util.c (limited to 'src') diff --git a/src/basic/user-util.c b/src/basic/user-util.c index ebeac99d31..b5e6ce8a8a 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -64,33 +64,6 @@ int parse_uid(const char *s, uid_t *ret) { return 0; } -char *lookup_uid(uid_t uid) { - long bufsize; - char *name; - _cleanup_free_ char *buf = NULL; - struct passwd pwbuf, *pw = NULL; - - /* Shortcut things to avoid NSS lookups */ - if (uid == 0) - return strdup("root"); - - bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); - if (bufsize <= 0) - bufsize = 4096; - - buf = malloc(bufsize); - if (!buf) - return NULL; - - if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw) - return strdup(pw->pw_name); - - if (asprintf(&name, UID_FMT, uid) < 0) - return NULL; - - return name; -} - char* getlogname_malloc(void) { uid_t uid; struct stat st; @@ -100,7 +73,7 @@ char* getlogname_malloc(void) { else uid = getuid(); - return lookup_uid(uid); + return uid_to_name(uid); } char *getusername_malloc(void) { @@ -110,7 +83,7 @@ char *getusername_malloc(void) { if (e) return strdup(e); - return lookup_uid(getuid()); + return uid_to_name(getuid()); } int get_user_creds( @@ -219,37 +192,80 @@ int get_group_creds(const char **groupname, gid_t *gid) { } char* uid_to_name(uid_t uid) { - struct passwd *p; - char *r; + char *ret; + int r; + /* Shortcut things to avoid NSS lookups */ if (uid == 0) return strdup("root"); - p = getpwuid(uid); - if (p) - return strdup(p->pw_name); + if (uid_is_valid(uid)) { + long bufsize; + + bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (bufsize <= 0) + bufsize = 4096; + + for (;;) { + struct passwd pwbuf, *pw = NULL; + _cleanup_free_ char *buf = NULL; + + buf = malloc(bufsize); + if (!buf) + return NULL; + + r = getpwuid_r(uid, &pwbuf, buf, (size_t) bufsize, &pw); + if (r == 0 && pw) + return strdup(pw->pw_name); + if (r != ERANGE) + break; + + bufsize *= 2; + } + } - if (asprintf(&r, UID_FMT, uid) < 0) + if (asprintf(&ret, UID_FMT, uid) < 0) return NULL; - return r; + return ret; } char* gid_to_name(gid_t gid) { - struct group *p; - char *r; + char *ret; + int r; if (gid == 0) return strdup("root"); - p = getgrgid(gid); - if (p) - return strdup(p->gr_name); + if (gid_is_valid(gid)) { + long bufsize; + + bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); + if (bufsize <= 0) + bufsize = 4096; + + for (;;) { + struct group grbuf, *gr = NULL; + _cleanup_free_ char *buf = NULL; + + buf = malloc(bufsize); + if (!buf) + return NULL; + + r = getgrgid_r(gid, &grbuf, buf, (size_t) bufsize, &gr); + if (r == 0 && gr) + return strdup(gr->gr_name); + if (r != ERANGE) + break; + + bufsize *= 2; + } + } - if (asprintf(&r, GID_FMT, gid) < 0) + if (asprintf(&ret, GID_FMT, gid) < 0) return NULL; - return r; + return ret; } int in_gid(gid_t gid) { diff --git a/src/basic/user-util.h b/src/basic/user-util.h index 9263ede741..7995698f27 100644 --- a/src/basic/user-util.h +++ b/src/basic/user-util.h @@ -36,7 +36,6 @@ static inline int parse_gid(const char *s, gid_t *ret_gid) { return parse_uid(s, (uid_t*) ret_gid); } -char* lookup_uid(uid_t uid); char* getlogname_malloc(void); char* getusername_malloc(void); diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 6da1398b7d..61c2c9ba40 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -2028,7 +2028,7 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd } utmp_wall("The system shutdown has been cancelled", - lookup_uid(uid), tty, logind_wall_tty_filter, m); + uid_to_name(uid), tty, logind_wall_tty_filter, m); } return sd_bus_reply_method_return(message, "b", cancelled); diff --git a/src/login/logind-utmp.c b/src/login/logind-utmp.c index 80e461f2dc..9c766bcb25 100644 --- a/src/login/logind-utmp.c +++ b/src/login/logind-utmp.c @@ -96,7 +96,7 @@ static int warn_wall(Manager *m, usec_t n) { return 0; } - utmp_wall(l, lookup_uid(m->scheduled_shutdown_uid), + utmp_wall(l, uid_to_name(m->scheduled_shutdown_uid), m->scheduled_shutdown_tty, logind_wall_tty_filter, m); return 1; diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c new file mode 100644 index 0000000000..dfd2031998 --- /dev/null +++ b/src/test/test-user-util.c @@ -0,0 +1,53 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2015 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include "macro.h" +#include "string-util.h" +#include "user-util.h" +#include "util.h" + +static void test_uid_to_name_one(uid_t uid, const char *name) { + _cleanup_free_ char *t = NULL; + + assert_se(t = uid_to_name(uid)); + assert_se(streq_ptr(t, name)); +} + +static void test_gid_to_name_one(gid_t gid, const char *name) { + _cleanup_free_ char *t = NULL; + + assert_se(t = gid_to_name(gid)); + assert_se(streq_ptr(t, name)); +} + +int main(int argc, char*argv[]) { + + test_uid_to_name_one(0, "root"); + test_uid_to_name_one(0xFFFF, "65535"); + test_uid_to_name_one(0xFFFFFFFF, "4294967295"); + + test_gid_to_name_one(0, "root"); + test_gid_to_name_one(TTY_GID, "tty"); + test_gid_to_name_one(0xFFFF, "65535"); + test_gid_to_name_one(0xFFFFFFFF, "4294967295"); + + return 0; +} -- cgit v1.2.3-54-g00ecf