source: azure_iot_hub/trunk/musl-1.1.18/src/passwd/getgr_a.c@ 389

Last change on this file since 389 was 389, checked in by coas-nagasima, 5 years ago

ビルドが通るよう更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 3.3 KB
Line 
1#include <pthread.h>
2#include <byteswap.h>
3#include <string.h>
4#include <unistd.h>
5#include "pwf.h"
6#include "nscd.h"
7
8static char *itoa(char *p, uint32_t x)
9{
10 // number of digits in a uint32_t + NUL
11 p += 11;
12 *--p = 0;
13 do {
14 *--p = '0' + x % 10;
15 x /= 10;
16 } while (x);
17 return p;
18}
19
20int __getgr_a(const char *name, gid_t gid, struct group *gr, char **buf, size_t *size, char ***mem, size_t *nmem, struct group **res)
21{
22 FILE *f;
23 int rv = 0;
24 int cs;
25
26 *res = 0;
27
28 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
29 f = fopen("/etc/group", "rbe");
30 if (!f) {
31 rv = errno;
32 goto done;
33 }
34
35 while (!(rv = __getgrent_a(f, gr, buf, size, mem, nmem, res)) && *res) {
36 if (name && !strcmp(name, (*res)->gr_name)
37 || !name && (*res)->gr_gid == gid) {
38 break;
39 }
40 }
41 fclose(f);
42
43 if (!*res && (rv == 0 || rv == ENOENT || rv == ENOTDIR)) {
44 int32_t req = name ? GETGRBYNAME : GETGRBYGID;
45 int32_t i;
46 const char *key;
47 int32_t groupbuf[GR_LEN] = {0};
48 size_t len = 0;
49 size_t grlist_len = 0;
50 char gidbuf[11] = {0};
51 int swap = 0;
52 char *ptr;
53
54 if (name) {
55 key = name;
56 } else {
57 if (gid < 0 || gid > UINT32_MAX) {
58 rv = 0;
59 goto done;
60 }
61 key = itoa(gidbuf, gid);
62 }
63
64 f = __nscd_query(req, key, groupbuf, sizeof groupbuf, &swap);
65 if (!f) { rv = errno; goto done; }
66
67 if (!groupbuf[GRFOUND]) { rv = 0; goto cleanup_f; }
68
69 if (!groupbuf[GRNAMELEN] || !groupbuf[GRPASSWDLEN]) {
70 rv = EIO;
71 goto cleanup_f;
72 }
73
74 if (groupbuf[GRNAMELEN] > SIZE_MAX - groupbuf[GRPASSWDLEN]) {
75 rv = ENOMEM;
76 goto cleanup_f;
77 }
78 len = groupbuf[GRNAMELEN] + groupbuf[GRPASSWDLEN];
79
80 for (i = 0; i < groupbuf[GRMEMCNT]; i++) {
81 uint32_t name_len;
82 if (fread(&name_len, sizeof name_len, 1, f) < 1) {
83 rv = ferror(f) ? errno : EIO;
84 goto cleanup_f;
85 }
86 if (swap) {
87 name_len = bswap_32(name_len);
88 }
89 if (name_len > SIZE_MAX - grlist_len
90 || name_len > SIZE_MAX - len) {
91 rv = ENOMEM;
92 goto cleanup_f;
93 }
94 len += name_len;
95 grlist_len += name_len;
96 }
97
98 if (len > *size || !*buf) {
99 char *tmp = realloc(*buf, len);
100 if (!tmp) {
101 rv = errno;
102 goto cleanup_f;
103 }
104 *buf = tmp;
105 *size = len;
106 }
107
108 if (!fread(*buf, len, 1, f)) {
109 rv = ferror(f) ? errno : EIO;
110 goto cleanup_f;
111 }
112
113 if (groupbuf[GRMEMCNT] + 1 > *nmem) {
114 if (groupbuf[GRMEMCNT] + 1 > SIZE_MAX/sizeof(char*)) {
115 rv = ENOMEM;
116 goto cleanup_f;
117 }
118 char **tmp = realloc(*mem, (groupbuf[GRMEMCNT]+1)*sizeof(char*));
119 if (!tmp) {
120 rv = errno;
121 goto cleanup_f;
122 }
123 *mem = tmp;
124 *nmem = groupbuf[GRMEMCNT] + 1;
125 }
126
127 if (groupbuf[GRMEMCNT]) {
128 mem[0][0] = *buf + groupbuf[GRNAMELEN] + groupbuf[GRPASSWDLEN];
129 for (ptr = mem[0][0], i = 0; ptr != mem[0][0]+grlist_len; ptr++)
130 if (!*ptr) mem[0][++i] = ptr+1;
131 mem[0][i] = 0;
132
133 if (i != groupbuf[GRMEMCNT]) {
134 rv = EIO;
135 goto cleanup_f;
136 }
137 } else {
138 mem[0][0] = 0;
139 }
140
141 gr->gr_name = *buf;
142 gr->gr_passwd = gr->gr_name + groupbuf[GRNAMELEN];
143 gr->gr_gid = groupbuf[GRGID];
144 gr->gr_mem = *mem;
145
146 if (gr->gr_passwd[-1]
147 || gr->gr_passwd[groupbuf[GRPASSWDLEN]-1]) {
148 rv = EIO;
149 goto cleanup_f;
150 }
151
152 if (name && strcmp(name, gr->gr_name)
153 || !name && gid != gr->gr_gid) {
154 rv = EIO;
155 goto cleanup_f;
156 }
157
158 *res = gr;
159
160cleanup_f:
161 fclose(f);
162 goto done;
163 }
164
165done:
166 pthread_setcancelstate(cs, 0);
167 if (rv) errno = rv;
168 return rv;
169}
Note: See TracBrowser for help on using the repository browser.