Merge remote-tracking branch 'origin/master' into llvm-fpm
[mono-project.git] / support / pwd.c
blob0e73af22bf9dac7825528da3a77a4f7e34ae4746
1 /*
2 * <pwd.h> wrapper functions.
4 * Authors:
5 * Jonathan Pryor (jonpryor@vt.edu)
7 * Copyright (C) 2004-2005 Jonathan Pryor
8 */
10 #include <pwd.h>
11 #include <errno.h>
12 #include <string.h>
13 #include <stdio.h>
14 #include <stdlib.h>
16 #include "mph.h" /* Don't remove or move after map.h! Works around issues with Android SDK unified headers */
17 #include "map.h"
19 G_BEGIN_DECLS
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)
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)
44 * Copy the native `passwd' structure to it's managed representation.
46 * To minimize separate mallocs, all the strings are allocated within the same
47 * memory block (stored in _pw_buf_).
49 static int
50 copy_passwd (struct Mono_Posix_Syscall__Passwd *to, struct passwd *from)
52 char *buf;
53 buf = _mph_copy_structure_strings (to, mph_passwd_offsets,
54 from, passwd_offsets, sizeof(passwd_offsets)/sizeof(passwd_offsets[0]));
56 to->pw_uid = from->pw_uid;
57 to->pw_gid = from->pw_gid;
59 to->_pw_buf_ = buf;
60 if (buf == NULL) {
61 return -1;
64 return 0;
67 gint32
68 Mono_Posix_Syscall_getpwnam (const char *name, struct Mono_Posix_Syscall__Passwd *pwbuf)
70 struct passwd *pw;
72 if (pwbuf == NULL) {
73 errno = EFAULT;
74 return -1;
77 errno = 0;
78 pw = getpwnam (name);
79 if (pw == NULL)
80 return -1;
82 if (copy_passwd (pwbuf, pw) == -1) {
83 errno = ENOMEM;
84 return -1;
86 return 0;
89 gint32
90 Mono_Posix_Syscall_getpwuid (mph_uid_t uid, struct Mono_Posix_Syscall__Passwd *pwbuf)
92 struct passwd *pw;
94 if (pwbuf == NULL) {
95 errno = EFAULT;
96 return -1;
99 errno = 0;
100 pw = getpwuid (uid);
101 if (pw == NULL) {
102 return -1;
105 if (copy_passwd (pwbuf, pw) == -1) {
106 errno = ENOMEM;
107 return -1;
109 return 0;
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)
118 char *buf, *buf2;
119 size_t buflen;
120 int r;
121 struct passwd _pwbuf;
123 if (pwbuf == NULL) {
124 errno = EFAULT;
125 return -1;
128 buf = buf2 = NULL;
129 buflen = 2;
131 do {
132 buf2 = realloc (buf, buflen *= 2);
133 if (buf2 == NULL) {
134 free (buf);
135 errno = ENOMEM;
136 return -1;
138 buf = buf2;
139 errno = 0;
140 } while ((r = getpwnam_r (name, &_pwbuf, buf, buflen, (struct passwd**) pwbufp)) &&
141 recheck_range (r));
143 if (r == 0 && !(*pwbufp))
144 /* On solaris, this function returns 0 even if the entry was not found */
145 r = errno = ENOENT;
147 if (r == 0 && copy_passwd (pwbuf, &_pwbuf) == -1)
148 r = errno = ENOMEM;
149 free (buf);
151 return r;
153 #endif /* ndef HAVE_GETPWNAM_R */
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)
161 char *buf, *buf2;
162 size_t buflen;
163 int r;
164 struct passwd _pwbuf;
166 if (pwbuf == NULL) {
167 errno = EFAULT;
168 return -1;
171 buf = buf2 = NULL;
172 buflen = 2;
174 do {
175 buf2 = realloc (buf, buflen *= 2);
176 if (buf2 == NULL) {
177 free (buf);
178 errno = ENOMEM;
179 return -1;
181 buf = buf2;
182 errno = 0;
183 } while ((r = getpwuid_r (uid, &_pwbuf, buf, buflen, (struct passwd**) pwbufp)) &&
184 recheck_range (r));
186 if (r == 0 && !(*pwbufp))
187 /* On solaris, this function returns 0 even if the entry was not found */
188 r = errno = ENOENT;
190 if (r == 0 && copy_passwd (pwbuf, &_pwbuf) == -1)
191 r = errno = ENOMEM;
192 free (buf);
194 return r;
196 #endif /* ndef HAVE_GETPWUID_R */
198 #if HAVE_GETPWENT
199 gint32
200 Mono_Posix_Syscall_getpwent (struct Mono_Posix_Syscall__Passwd *pwbuf)
202 struct passwd *pw;
204 if (pwbuf == NULL) {
205 errno = EFAULT;
206 return -1;
209 errno = 0;
210 pw = getpwent ();
211 if (pw == NULL)
212 return -1;
214 if (copy_passwd (pwbuf, pw) == -1) {
215 errno = ENOMEM;
216 return -1;
218 return 0;
220 #endif /* def HAVE_GETPWENT */
222 #ifdef HAVE_FGETPWENT
223 gint32
224 Mono_Posix_Syscall_fgetpwent (void *stream, struct Mono_Posix_Syscall__Passwd *pwbuf)
226 struct passwd *pw;
228 if (pwbuf == NULL) {
229 errno = EFAULT;
230 return -1;
233 errno = 0;
234 pw = fgetpwent ((FILE*) stream);
235 if (pw == NULL)
236 return -1;
238 if (copy_passwd (pwbuf, pw) == -1) {
239 errno = ENOMEM;
240 return -1;
242 return 0;
244 #endif /* ndef HAVE_FGETPWENT */
246 #if HAVE_SETPWENT
248 Mono_Posix_Syscall_setpwent (void)
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;
257 #endif /* def HAVE_SETPWENT */
259 #if HAVE_ENDPWENT
261 Mono_Posix_Syscall_endpwent (void)
263 errno = 0;
264 endpwent ();
265 if (errno == EIO)
266 return -1;
267 return 0;
269 #endif /* def HAVE_ENDPWENT */
271 G_END_DECLS
274 * vim: noexpandtab