From 700e08993c3f6a808773d56424aa7e633da13e2e Mon Sep 17 00:00:00 2001 From: Josiah Worcester Date: Tue, 10 Feb 2015 18:32:55 -0600 Subject: [PATCH] refactor passwd file access code this allows getpwnam and getpwuid to share code with the _r versions in preparation for alternate backend support. --- src/passwd/fgetpwent.c | 4 +++- src/passwd/getpw_a.c | 31 +++++++++++++++++++++++++++++++ src/passwd/getpw_r.c | 36 +++++++++++------------------------- src/passwd/getpwent.c | 32 ++++++++++++-------------------- src/passwd/getpwent_a.c | 8 ++++++-- src/passwd/pwf.h | 3 ++- 6 files changed, 65 insertions(+), 49 deletions(-) create mode 100644 src/passwd/getpw_a.c diff --git a/src/passwd/fgetpwent.c b/src/passwd/fgetpwent.c index eb47b2a1..fd472a07 100644 --- a/src/passwd/fgetpwent.c +++ b/src/passwd/fgetpwent.c @@ -6,5 +6,7 @@ struct passwd *fgetpwent(FILE *f) static char *line; static struct passwd pw; size_t size=0; - return __getpwent_a(f, &pw, &line, &size); + struct passwd *res; + __getpwent_a(f, &pw, &line, &size, &res); + return res; } diff --git a/src/passwd/getpw_a.c b/src/passwd/getpw_a.c new file mode 100644 index 00000000..21efc5ca --- /dev/null +++ b/src/passwd/getpw_a.c @@ -0,0 +1,31 @@ +#include "pwf.h" +#include + +int __getpw_a(const char *name, uid_t uid, struct passwd *pw, char **buf, size_t *size, struct passwd **res) +{ + FILE *f; + int cs; + int rv = 0; + + *res = 0; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + + f = fopen("/etc/passwd", "rbe"); + if (!f) { + rv = errno; + goto done; + } + + while (!(rv = __getpwent_a(f, pw, buf, size, res)) && *res) { + if (name && !strcmp(name, (*res)->pw_name) + || !name && (*res)->pw_uid == uid) + break; + } + fclose(f); + +done: + pthread_setcancelstate(cs, 0); + if (rv) errno = rv; + return rv; +} diff --git a/src/passwd/getpw_r.c b/src/passwd/getpw_r.c index 28552572..0e71e43f 100644 --- a/src/passwd/getpw_r.c +++ b/src/passwd/getpw_r.c @@ -5,7 +5,6 @@ static int getpw_r(const char *name, uid_t uid, struct passwd *pw, char *buf, size_t size, struct passwd **res) { - FILE *f; char *line = 0; size_t len = 0; int rv = 0; @@ -13,33 +12,20 @@ static int getpw_r(const char *name, uid_t uid, struct passwd *pw, char *buf, si pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); - f = fopen("/etc/passwd", "rbe"); - if (!f) { - rv = errno; - goto done; + rv = __getpw_a(name, uid, pw, &line, &len, res); + if (!rv && size < len) { + *res = 0; + rv = ERANGE; } - - *res = 0; - while (__getpwent_a(f, pw, &line, &len)) { - if (name && !strcmp(name, pw->pw_name) - || !name && pw->pw_uid == uid) { - if (size < len) { - rv = ERANGE; - break; - } - *res = pw; - memcpy(buf, line, len); - FIX(name); - FIX(passwd); - FIX(gecos); - FIX(dir); - FIX(shell); - break; - } + if (!rv) { + memcpy(buf, line, len); + FIX(name); + FIX(passwd); + FIX(gecos); + FIX(dir); + FIX(shell); } free(line); - fclose(f); -done: pthread_setcancelstate(cs, 0); return rv; } diff --git a/src/passwd/getpwent.c b/src/passwd/getpwent.c index c655135e..f2bd516e 100644 --- a/src/passwd/getpwent.c +++ b/src/passwd/getpwent.c @@ -1,6 +1,9 @@ #include "pwf.h" static FILE *f; +static char *line; +static struct passwd pw; +static size_t size; void setpwent() { @@ -12,34 +15,23 @@ weak_alias(setpwent, endpwent); struct passwd *getpwent() { - static char *line; - static struct passwd pw; - size_t size=0; + struct passwd *res; if (!f) f = fopen("/etc/passwd", "rbe"); if (!f) return 0; - return __getpwent_a(f, &pw, &line, &size); + __getpwent_a(f, &pw, &line, &size, &res); + return res; } struct passwd *getpwuid(uid_t uid) { - struct passwd *pw; - int errno_saved; - setpwent(); - while ((pw=getpwent()) && pw->pw_uid != uid); - errno_saved = errno; - endpwent(); - errno = errno_saved; - return pw; + struct passwd *res; + __getpw_a(0, uid, &pw, &line, &size, &res); + return res; } struct passwd *getpwnam(const char *name) { - struct passwd *pw; - int errno_saved; - setpwent(); - while ((pw=getpwent()) && strcmp(pw->pw_name, name)); - errno_saved = errno; - endpwent(); - errno = errno_saved; - return pw; + struct passwd *res; + __getpw_a(name, 0, &pw, &line, &size, &res); + return res; } diff --git a/src/passwd/getpwent_a.c b/src/passwd/getpwent_a.c index 34842a07..4d84f0d5 100644 --- a/src/passwd/getpwent_a.c +++ b/src/passwd/getpwent_a.c @@ -8,14 +8,16 @@ static unsigned atou(char **s) return x; } -struct passwd *__getpwent_a(FILE *f, struct passwd *pw, char **line, size_t *size) +int __getpwent_a(FILE *f, struct passwd *pw, char **line, size_t *size, struct passwd **res) { ssize_t l; char *s; + int rv = 0; int cs; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); for (;;) { if ((l=getline(line, size, f)) < 0) { + rv = errno; free(*line); *line = 0; pw = 0; @@ -46,5 +48,7 @@ struct passwd *__getpwent_a(FILE *f, struct passwd *pw, char **line, size_t *siz break; } pthread_setcancelstate(cs, 0); - return pw; + *res = pw; + if (rv) errno = rv; + return rv; } diff --git a/src/passwd/pwf.h b/src/passwd/pwf.h index 2d813ada..806ffd31 100644 --- a/src/passwd/pwf.h +++ b/src/passwd/pwf.h @@ -8,6 +8,7 @@ #include #include "libc.h" -struct passwd *__getpwent_a(FILE *f, struct passwd *pw, char **line, size_t *size); +int __getpwent_a(FILE *f, struct passwd *pw, char **line, size_t *size, struct passwd **res); +int __getpw_a(const char *name, uid_t uid, struct passwd *pw, char **buf, size_t *size, struct passwd **res); struct group *__getgrent_a(FILE *f, struct group *gr, char **line, size_t *size, char ***mem, size_t *nmem); int __parsespent(char *s, struct spwd *sp); -- GitLab