* grp.c, pwd.c: Clear errno before calling the actual calls, as errno may
[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 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         struct passwd **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, pwbufp)) && 
147                         recheck_range (r));
148
149         if (r == 0 && copy_passwd (pwbuf, &_pwbuf) == -1)
150                 r = errno = ENOMEM;
151         free (buf);
152
153         return r;
154 }
155 #endif /* ndef HAVE_GETPWNAM_R */
156
157 #ifdef HAVE_GETPWUID_R
158 gint32
159 Mono_Posix_Syscall_getpwuid_r (mph_uid_t uid,
160         struct Mono_Posix_Syscall__Passwd *pwbuf,
161         struct passwd **pwbufp)
162 {
163         char *buf, *buf2;
164         size_t buflen;
165         int r;
166         struct passwd _pwbuf;
167
168         if (pwbuf == NULL) {
169                 errno = EFAULT;
170                 return -1;
171         }
172
173         buf = buf2 = NULL;
174         buflen = 2;
175
176         do {
177                 buf2 = realloc (buf, buflen *= 2);
178                 if (buf2 == NULL) {
179                         free (buf);
180                         errno = ENOMEM;
181                         return -1;
182                 }
183                 buf = buf2;
184                 errno = 0;
185         } while ((r = getpwuid_r (uid, &_pwbuf, buf, buflen, pwbufp)) && 
186                         recheck_range (r));
187
188         if (r == 0 && copy_passwd (pwbuf, &_pwbuf) == -1)
189                 r = errno = ENOMEM;
190         free (buf);
191
192         return r;
193 }
194 #endif /* ndef HAVE_GETPWUID_R */
195
196 gint32
197 Mono_Posix_Syscall_getpwent (struct Mono_Posix_Syscall__Passwd *pwbuf)
198 {
199         struct passwd *pw;
200
201         if (pwbuf == NULL) {
202                 errno = EFAULT;
203                 return -1;
204         }
205
206         errno = 0;
207         pw = getpwent ();
208         if (pw == NULL)
209                 return -1;
210
211         if (copy_passwd (pwbuf, pw) == -1) {
212                 errno = ENOMEM;
213                 return -1;
214         }
215         return 0;
216 }
217
218 #ifdef HAVE_FGETPWENT
219 gint32
220 Mono_Posix_Syscall_fgetpwent (FILE *stream, struct Mono_Posix_Syscall__Passwd *pwbuf)
221 {
222         struct passwd *pw;
223
224         if (pwbuf == NULL) {
225                 errno = EFAULT;
226                 return -1;
227         }
228
229         errno = 0;
230         pw = fgetpwent (stream);
231         if (pw == NULL)
232                 return -1;
233
234         if (copy_passwd (pwbuf, pw) == -1) {
235                 errno = ENOMEM;
236                 return -1;
237         }
238         return 0;
239 }
240 #endif /* ndef HAVE_FGETPWENT */
241
242 G_END_DECLS
243
244 /*
245  * vim: noexpandtab
246  */