39744959ad12401be77295e8f4ead9226a6152de
[musl] / src / passwd / getpw_r.c
1 #include "pwf.h"
2 #include <pthread.h>
3
4 #define FIX(x) (pw->pw_##x = pw->pw_##x-line+buf)
5
6 static int getpw_r(const char *name, uid_t uid, struct passwd *pw, char *buf, size_t size, struct passwd **res)
7 {
8         FILE *f;
9         char *line = 0;
10         size_t len = 0;
11         int rv = 0;
12         int cs;
13
14         pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
15
16         f = fopen("/etc/passwd", "rb");
17         if (!f) {
18                 rv = errno;
19                 goto done;
20         }
21
22         *res = 0;
23         while (__getpwent_a(f, pw, &line, &len)) {
24                 if (name && !strcmp(name, pw->pw_name)
25                 || !name && pw->pw_uid == uid) {
26                         if (size < len) {
27                                 rv = ERANGE;
28                                 break;
29                         }
30                         *res = pw;
31                         memcpy(buf, line, len);
32                         FIX(name);
33                         FIX(passwd);
34                         FIX(gecos);
35                         FIX(dir);
36                         FIX(shell);
37                         break;
38                 }
39         }
40         free(line);
41         fclose(f);
42 done:
43         pthread_setcancelstate(cs, 0);
44         return rv;
45 }
46
47 int getpwnam_r(const char *name, struct passwd *pw, char *buf, size_t size, struct passwd **res)
48 {
49         return getpw_r(name, 0, pw, buf, size, res);
50 }
51
52 int getpwuid_r(uid_t uid, struct passwd *pw, char *buf, size_t size, struct passwd **res)
53 {
54         return getpw_r(0, uid, pw, buf, size, res);
55 }