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