New test.
[mono.git] / support / pwd.c
1 /*
2  * <pwd.h> wrapper functions.
3  *
4  * Authors:
5  *   Jonathan Pryor (jonpryor@vt.edu)
6  *
7  * Copyright (C) 2004-2005 Jonathan Pryor
8  */
9
10 #include <pwd.h>
11 #include <errno.h>
12 #include <string.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15
16 #include "mph.h"
17
18 G_BEGIN_DECLS
19
20 struct Mono_Posix_Syscall__Passwd {
21         /* string */ char      *pw_name;
22         /* string */ char      *pw_passwd;
23         /* uid_t  */ mph_uid_t  pw_uid;
24         /* gid_t  */ mph_gid_t  pw_gid;
25         /* string */ char      *pw_gecos;
26         /* string */ char      *pw_dir;
27         /* string */ char      *pw_shell;
28         /* string */ char      *_pw_buf_;
29 };
30
31 static const size_t
32 passwd_offsets[] = {
33         offsetof (struct passwd, pw_name),
34         offsetof (struct passwd, pw_passwd),
35         offsetof (struct passwd, pw_gecos),
36         offsetof (struct passwd, pw_dir),
37         offsetof (struct passwd, pw_shell)
38 };
39
40 static const size_t
41 mph_passwd_offsets[] = {
42         offsetof (struct Mono_Posix_Syscall__Passwd, pw_name),
43         offsetof (struct Mono_Posix_Syscall__Passwd, pw_passwd),
44         offsetof (struct Mono_Posix_Syscall__Passwd, pw_gecos),
45         offsetof (struct Mono_Posix_Syscall__Passwd, pw_dir),
46         offsetof (struct Mono_Posix_Syscall__Passwd, pw_shell)
47 };
48
49 /*
50  * Copy the native `passwd' structure to it's managed representation.
51  *
52  * To minimize separate mallocs, all the strings are allocated within the same
53  * memory block (stored in _pw_buf_).
54  */
55 static int
56 copy_passwd (struct Mono_Posix_Syscall__Passwd *to, struct passwd *from)
57 {
58         char *buf;
59         buf = _mph_copy_structure_strings (to, mph_passwd_offsets,
60                         from, passwd_offsets, sizeof(passwd_offsets)/sizeof(passwd_offsets[0]));
61
62         to->pw_uid    = from->pw_uid;
63         to->pw_gid    = from->pw_gid;
64
65         to->_pw_buf_ = buf;
66         if (buf == NULL) {
67                 return -1;
68         }
69
70         return 0;
71 }
72
73 gint32
74 Mono_Posix_Syscall_getpwnam (const char *name, struct Mono_Posix_Syscall__Passwd *pwbuf)
75 {
76         struct passwd *pw;
77
78         if (pwbuf == NULL) {
79                 errno = EFAULT;
80                 return -1;
81         }
82
83         errno = 0;
84         pw = getpwnam (name);
85         if (pw == NULL)
86                 return -1;
87
88         if (copy_passwd (pwbuf, pw) == -1) {
89                 errno = ENOMEM;
90                 return -1;
91         }
92         return 0;
93 }
94
95 gint32
96 Mono_Posix_Syscall_getpwuid (mph_uid_t uid, struct Mono_Posix_Syscall__Passwd *pwbuf)
97 {
98         struct passwd *pw;
99
100         if (pwbuf == NULL) {
101                 errno = EFAULT;
102                 return -1;
103         }
104
105         errno = 0;
106         pw = getpwuid (uid);
107         if (pw == NULL) {
108                 return -1;
109         }
110
111         if (copy_passwd (pwbuf, pw) == -1) {
112                 errno = ENOMEM;
113                 return -1;
114         }
115         return 0;
116 }
117
118 #ifdef HAVE_GETPWNAM_R
119 gint32
120 Mono_Posix_Syscall_getpwnam_r (const char *name, 
121         struct Mono_Posix_Syscall__Passwd *pwbuf,
122         void **pwbufp)
123 {
124         char *buf, *buf2;
125         size_t buflen;
126         int r;
127         struct passwd _pwbuf;
128
129         if (pwbuf == NULL) {
130                 errno = EFAULT;
131                 return -1;
132         }
133
134         buf = buf2 = NULL;
135         buflen = 2;
136
137         do {
138                 buf2 = realloc (buf, buflen *= 2);
139                 if (buf2 == NULL) {
140                         free (buf);
141                         errno = ENOMEM;
142                         return -1;
143                 }
144                 buf = buf2;
145                 errno = 0;
146         } while ((r = getpwnam_r (name, &_pwbuf, buf, buflen, (struct passwd**) pwbufp)) && 
147                         recheck_range (r));
148
149         if (r == 0 && !(*pwbufp))
150                 /* On solaris, this function returns 0 even if the entry was not found */
151                 r = errno = ENOENT;
152
153         if (r == 0 && copy_passwd (pwbuf, &_pwbuf) == -1)
154                 r = errno = ENOMEM;
155         free (buf);
156
157         return r;
158 }
159 #endif /* ndef HAVE_GETPWNAM_R */
160
161 #ifdef HAVE_GETPWUID_R
162 gint32
163 Mono_Posix_Syscall_getpwuid_r (mph_uid_t uid,
164         struct Mono_Posix_Syscall__Passwd *pwbuf,
165         void **pwbufp)
166 {
167         char *buf, *buf2;
168         size_t buflen;
169         int r;
170         struct passwd _pwbuf;
171
172         if (pwbuf == NULL) {
173                 errno = EFAULT;
174                 return -1;
175         }
176
177         buf = buf2 = NULL;
178         buflen = 2;
179
180         do {
181                 buf2 = realloc (buf, buflen *= 2);
182                 if (buf2 == NULL) {
183                         free (buf);
184                         errno = ENOMEM;
185                         return -1;
186                 }
187                 buf = buf2;
188                 errno = 0;
189         } while ((r = getpwuid_r (uid, &_pwbuf, buf, buflen, (struct passwd**) pwbufp)) && 
190                         recheck_range (r));
191
192         if (r == 0 && copy_passwd (pwbuf, &_pwbuf) == -1)
193                 r = errno = ENOMEM;
194         free (buf);
195
196         return r;
197 }
198 #endif /* ndef HAVE_GETPWUID_R */
199
200 gint32
201 Mono_Posix_Syscall_getpwent (struct Mono_Posix_Syscall__Passwd *pwbuf)
202 {
203         struct passwd *pw;
204
205         if (pwbuf == NULL) {
206                 errno = EFAULT;
207                 return -1;
208         }
209
210         errno = 0;
211         pw = getpwent ();
212         if (pw == NULL)
213                 return -1;
214
215         if (copy_passwd (pwbuf, pw) == -1) {
216                 errno = ENOMEM;
217                 return -1;
218         }
219         return 0;
220 }
221
222 #ifdef HAVE_FGETPWENT
223 gint32
224 Mono_Posix_Syscall_fgetpwent (void *stream, struct Mono_Posix_Syscall__Passwd *pwbuf)
225 {
226         struct passwd *pw;
227
228         if (pwbuf == NULL) {
229                 errno = EFAULT;
230                 return -1;
231         }
232
233         errno = 0;
234         pw = fgetpwent ((FILE*) stream);
235         if (pw == NULL)
236                 return -1;
237
238         if (copy_passwd (pwbuf, pw) == -1) {
239                 errno = ENOMEM;
240                 return -1;
241         }
242         return 0;
243 }
244 #endif /* ndef HAVE_FGETPWENT */
245
246 int
247 Mono_Posix_Syscall_setpwent (void)
248 {
249         errno = 0;
250         setpwent ();
251         return errno == 0 ? 0 : -1;
252 }
253
254 int
255 Mono_Posix_Syscall_endpwent (void)
256 {
257         errno = 0;
258         endpwent ();
259         return errno == 0 ? 0 : -1;
260 }
261
262 G_END_DECLS
263
264 /*
265  * vim: noexpandtab
266  */