* marshal.c: Iter usage.
[mono-project.git] / support / grp.c
blobf6c4832cc0cb4c9202e2b97b091d7640d5b389c0
1 /*
2 * <grp.h> wrapper functions.
4 * Authors:
5 * Jonathan Pryor (jonpryor@vt.edu)
7 * Copyright (C) 2004 Jonathan Pryor
8 */
10 #include <sys/types.h>
11 #include <sys/param.h>
12 #include <grp.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <errno.h>
16 #include <string.h>
17 #include <unistd.h> /* for setgroups on Mac OS X */
19 #include "mph.h"
21 G_BEGIN_DECLS
23 struct Mono_Posix_Syscall__Group {
24 /* string */ char *gr_name;
25 /* string */ char *gr_passwd;
26 /* gid_t */ mph_gid_t gr_gid;
27 /* int */ int _gr_nmem_;
28 /* string */ char **gr_mem;
29 /* string */ char *_gr_buf_; /* holds all but gr_mem */
32 static void
33 count_members (char **gr_mem, int *count, size_t *mem)
35 char *cur;
36 *count = 0;
38 // ensure that later (*mem)+1 doesn't result in integer overflow
39 if (*mem > INT_MAX - 1)
40 return;
42 for (cur = *gr_mem; cur != NULL; cur = *++gr_mem) {
43 size_t len;
44 len = strlen (cur);
46 if (!(len < INT_MAX - ((*mem) + 1)))
47 break;
49 ++(*count);
50 *mem += (len + 1);
54 static int
55 copy_group (struct Mono_Posix_Syscall__Group *to, struct group *from)
57 size_t nlen, plen, buflen;
58 int i, count;
59 char *cur;
61 to->gr_gid = from->gr_gid;
63 to->gr_name = NULL;
64 to->gr_passwd = NULL;
65 to->gr_mem = NULL;
66 to->_gr_buf_ = NULL;
68 nlen = strlen (from->gr_name);
69 plen = strlen (from->gr_passwd);
71 buflen = 2;
73 if (!(nlen < INT_MAX - buflen))
74 return -1;
75 buflen += nlen;
77 if (!(plen < INT_MAX - buflen))
78 return -1;
79 buflen += plen;
81 count = 0;
82 count_members (from->gr_mem, &count, &buflen);
84 to->_gr_nmem_ = count;
85 cur = to->_gr_buf_ = (char*) malloc (buflen);
86 to->gr_mem = (char **) malloc (sizeof(char*)*(count+1));
87 if (to->_gr_buf_ == NULL || to->gr_mem == NULL) {
88 free (to->_gr_buf_);
89 free (to->gr_mem);
90 return -1;
93 to->gr_name = strcpy (cur, from->gr_name);
94 cur += (nlen + 1);
95 to->gr_passwd = strcpy (cur, from->gr_passwd);
96 cur += (plen + 1);
98 for (i = 0; i != count; ++i) {
99 to->gr_mem[i] = strcpy (cur, from->gr_mem[i]);
100 cur += (strlen (from->gr_mem[i])+1);
102 to->gr_mem[i] = NULL;
104 return 0;
107 gint32
108 Mono_Posix_Syscall_getgrnam (const char *name, struct Mono_Posix_Syscall__Group *gbuf)
110 struct group *_gbuf;
112 if (gbuf == NULL) {
113 errno = EFAULT;
114 return -1;
117 _gbuf = getgrnam (name);
118 if (_gbuf == NULL)
119 return -1;
121 if (copy_group (gbuf, _gbuf) == -1) {
122 errno = ENOMEM;
123 return -1;
125 return 0;
128 gint32
129 Mono_Posix_Syscall_getgrgid (mph_gid_t gid, struct Mono_Posix_Syscall__Group *gbuf)
131 struct group *_gbuf;
133 if (gbuf == NULL) {
134 errno = EFAULT;
135 return -1;
138 _gbuf = getgrgid (gid);
139 if (_gbuf == NULL)
140 return -1;
142 if (copy_group (gbuf, _gbuf) == -1) {
143 errno = ENOMEM;
144 return -1;
146 return 0;
149 #ifdef HAVE_GETGRNAM_R
150 gint32
151 Mono_Posix_Syscall_getgrnam_r (const char *name,
152 struct Mono_Posix_Syscall__Group *gbuf,
153 struct group **gbufp)
155 char *buf, *buf2;
156 size_t buflen;
157 int r;
158 struct group _grbuf;
160 if (gbuf == NULL) {
161 errno = EFAULT;
162 return -1;
165 buf = buf2 = NULL;
166 buflen = 2;
168 do {
169 buf2 = realloc (buf, buflen *= 2);
170 if (buf2 == NULL) {
171 free (buf);
172 errno = ENOMEM;
173 return -1;
175 buf = buf2;
176 } while ((r = getgrnam_r (name, &_grbuf, buf, buflen, gbufp)) &&
177 recheck_range (r));
179 if (r == 0 && copy_group (gbuf, &_grbuf) == -1)
180 r = errno = ENOMEM;
181 free (buf);
183 return r;
185 #endif /* ndef HAVE_GETGRNAM_R */
187 #ifdef HAVE_GETGRGID_R
188 gint32
189 Mono_Posix_Syscall_getgrgid_r (mph_gid_t gid,
190 struct Mono_Posix_Syscall__Group *gbuf,
191 struct group **gbufp)
193 char *buf, *buf2;
194 size_t buflen;
195 int r;
196 struct group _grbuf;
198 if (gbuf == NULL) {
199 errno = EFAULT;
200 return -1;
203 buf = buf2 = NULL;
204 buflen = 2;
206 do {
207 buf2 = realloc (buf, buflen *= 2);
208 if (buf2 == NULL) {
209 free (buf);
210 errno = ENOMEM;
211 return -1;
213 buf = buf2;
214 } while ((r = getgrgid_r (gid, &_grbuf, buf, buflen, gbufp)) &&
215 recheck_range (r));
217 if (r == 0 && copy_group (gbuf, &_grbuf) == -1)
218 r = errno = ENOMEM;
219 free (buf);
221 return r;
223 #endif /* ndef HAVE_GETGRGID_R */
225 gint32
226 Mono_Posix_Syscall_getgrent (struct Mono_Posix_Syscall__Group *grbuf)
228 struct group *gr;
230 if (grbuf == NULL) {
231 errno = EFAULT;
232 return -1;
235 gr = getgrent ();
236 if (gr == NULL)
237 return -1;
239 if (copy_group (grbuf, gr) == -1) {
240 errno = ENOMEM;
241 return -1;
243 return 0;
246 #ifdef HAVE_FGETGRENT
247 gint32
248 Mono_Posix_Syscall_fgetgrent (FILE *stream, struct Mono_Posix_Syscall__Group *grbuf)
250 struct group *gr;
252 if (grbuf == NULL) {
253 errno = EFAULT;
254 return -1;
257 gr = fgetgrent (stream);
258 if (gr == NULL)
259 return -1;
261 if (copy_group (grbuf, gr) == -1) {
262 errno = ENOMEM;
263 return -1;
265 return 0;
267 #endif /* ndef HAVE_FGETGRENT */
269 gint32
270 Mono_Posix_Syscall_setgroups (mph_size_t size, mph_gid_t *list)
272 mph_return_if_size_t_overflow (size);
273 return setgroups ((size_t) size, list);
276 G_END_DECLS
279 * vim: noexpandtab