1dc5f7e0e38df9398eaadbdb5e0291a546b599b8
[musl] / src / passwd / getgr_r.c
1 #include "pwf.h"
2 #include <pthread.h>
3
4 #define FIX(x) (gr->gr_##x = gr->gr_##x-line+buf)
5
6 static int getgr_r(const char *name, gid_t gid, struct group *gr, char *buf, size_t size, struct group **res)
7 {
8         FILE *f;
9         char *line = 0;
10         size_t len = 0;
11         char **mem = 0;
12         size_t nmem = 0;
13         int rv = 0;
14         size_t i;
15         int cs;
16
17         pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
18
19         f = fopen("/etc/group", "rb");
20         if (!f) {
21                 rv = errno;
22                 goto done;
23         }
24
25         *res = 0;
26         while (__getgrent_a(f, gr, &line, &len, &mem, &nmem)) {
27                 if (name && !strcmp(name, gr->gr_name)
28                 || !name && gr->gr_gid == gid) {
29                         if (size < len + nmem*sizeof(char *) + 32) {
30                                 rv = ERANGE;
31                                 break;
32                         }
33                         *res = gr;
34                         buf += (16-(uintptr_t)buf)%16;
35                         gr->gr_mem = (void *)buf;
36                         buf += nmem*sizeof(char *);
37                         memcpy(buf, line, len);
38                         FIX(name);
39                         FIX(passwd);
40                         for (i=0; mem[i]; i++)
41                                 gr->gr_mem[i] = mem[i]-line+buf;
42                         gr->gr_mem[i] = 0;
43                         break;
44                 }
45         }
46         free(mem);
47         free(line);
48         fclose(f);
49 done:
50         pthread_setcancelstate(cs, 0);
51         return rv;
52 }
53
54 int getgrnam_r(const char *name, struct group *gr, char *buf, size_t size, struct group **res)
55 {
56         return getgr_r(name, 0, gr, buf, size, res);
57 }
58
59 int getgrgid_r(gid_t gid, struct group *gr, char *buf, size_t size, struct group **res)
60 {
61         return getgr_r(0, gid, gr, buf, size, res);
62 }