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