* fstab.c: Added; wrap <fstab.h> functions: getfsent(3), getfsfile(3),
[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         pw = getpwnam (name);
84         if (pw == NULL)
85                 return -1;
86
87         if (copy_passwd (pwbuf, pw) == -1) {
88                 errno = ENOMEM;
89                 return -1;
90         }
91         return 0;
92 }
93
94 gint32
95 Mono_Posix_Syscall_getpwuid (mph_uid_t uid, struct Mono_Posix_Syscall__Passwd *pwbuf)
96 {
97         struct passwd *pw;
98
99         if (pwbuf == NULL) {
100                 errno = EFAULT;
101                 return -1;
102         }
103
104         errno = 0;
105         pw = getpwuid (uid);
106         if (pw == NULL) {
107                 return -1;
108         }
109
110         if (copy_passwd (pwbuf, pw) == -1) {
111                 errno = ENOMEM;
112                 return -1;
113         }
114         return 0;
115 }
116
117 #ifdef HAVE_GETPWNAM_R
118 gint32
119 Mono_Posix_Syscall_getpwnam_r (const char *name, 
120         struct Mono_Posix_Syscall__Passwd *pwbuf,
121         struct passwd **pwbufp)
122 {
123         char *buf, *buf2;
124         size_t buflen;
125         int r;
126         struct passwd _pwbuf;
127
128         if (pwbuf == NULL) {
129                 errno = EFAULT;
130                 return -1;
131         }
132
133         buf = buf2 = NULL;
134         buflen = 2;
135
136         do {
137                 buf2 = realloc (buf, buflen *= 2);
138                 if (buf2 == NULL) {
139                         free (buf);
140                         errno = ENOMEM;
141                         return -1;
142                 }
143                 buf = buf2;
144         } while ((r = getpwnam_r (name, &_pwbuf, buf, buflen, pwbufp)) && 
145                         recheck_range (r));
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         struct passwd **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         } while ((r = getpwuid_r (uid, &_pwbuf, buf, buflen, pwbufp)) && 
183                         recheck_range (r));
184
185         if (r == 0 && copy_passwd (pwbuf, &_pwbuf) == -1)
186                 r = errno = ENOMEM;
187         free (buf);
188
189         return r;
190 }
191 #endif /* ndef HAVE_GETPWUID_R */
192
193 gint32
194 Mono_Posix_Syscall_getpwent (struct Mono_Posix_Syscall__Passwd *pwbuf)
195 {
196         struct passwd *pw;
197
198         if (pwbuf == NULL) {
199                 errno = EFAULT;
200                 return -1;
201         }
202
203         pw = getpwent ();
204         if (pw == NULL)
205                 return -1;
206
207         if (copy_passwd (pwbuf, pw) == -1) {
208                 errno = ENOMEM;
209                 return -1;
210         }
211         return 0;
212 }
213
214 #ifdef HAVE_FGETPWENT
215 gint32
216 Mono_Posix_Syscall_fgetpwent (FILE *stream, struct Mono_Posix_Syscall__Passwd *pwbuf)
217 {
218         struct passwd *pw;
219
220         if (pwbuf == NULL) {
221                 errno = EFAULT;
222                 return -1;
223         }
224
225         pw = fgetpwent (stream);
226         if (pw == NULL)
227                 return -1;
228
229         if (copy_passwd (pwbuf, pw) == -1) {
230                 errno = ENOMEM;
231                 return -1;
232         }
233         return 0;
234 }
235 #endif /* ndef HAVE_FGETPWENT */
236
237 G_END_DECLS
238
239 /*
240  * vim: noexpandtab
241  */