New test.
[mono.git] / support / fstab.c
1 /*
2  * <fstab.h> wrapper functions.
3  *
4  * Authors:
5  *   Jonathan Pryor (jonpryor@vt.edu)
6  *
7  * Copyright (C) 2004-2005 Jonathan Pryor
8  */
9
10 #include <errno.h>
11 #include <string.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <stddef.h>
15
16 #include "mph.h"
17
18 #if defined (HAVE_CHECKLIST_H)
19 #include <checklist.h>
20 #elif defined (HAVE_FSTAB_H)
21 #include <fstab.h>
22 #endif /* def HAVE_FSTAB_H */
23
24 #ifdef HAVE_SYS_VFSTAB_H
25 #include <sys/vfstab.h>
26 #endif /* def HAVE_SYS_VFSTAB_H */
27
28 G_BEGIN_DECLS
29
30 struct Mono_Posix_Syscall__Fstab {
31         char  *fs_spec;     /* block device name */
32         char  *fs_file;     /* mount point */
33         char  *fs_vfstype;      /* filesystem type */
34         char  *fs_mntops;   /* mount options */
35         char  *fs_type;     /* rw/rq/ro/sw/xx option */
36         int    fs_freq;     /* dump frequency, in days */
37         int    fs_passno;   /* pass number on parallel dump */
38
39         char  *_fs_buf_;
40 };
41
42 #ifdef HAVE_CHECKLIST_H
43
44 typedef struct checklist mph_fstab;
45
46 static const size_t
47 fstab_offsets[] = {
48         offsetof (struct checklist, fs_spec),
49         offsetof (struct checklist, fs_dir),
50         offsetof (struct checklist, fs_type)
51 };
52
53 static const size_t
54 mph_fstab_offsets[] = {
55         offsetof (struct Mono_Posix_Syscall__Fstab, fs_spec),
56         offsetof (struct Mono_Posix_Syscall__Fstab, fs_file),
57         offsetof (struct Mono_Posix_Syscall__Fstab, fs_type)
58 };
59
60 #elif defined (HAVE_FSTAB_H)
61
62 typedef struct fstab mph_fstab;
63
64 static const size_t
65 fstab_offsets[] = {
66         offsetof (struct fstab, fs_spec),
67         offsetof (struct fstab, fs_file),
68         offsetof (struct fstab, fs_vfstype),
69         offsetof (struct fstab, fs_mntops),
70         offsetof (struct fstab, fs_type)
71 };
72
73 static const size_t
74 mph_fstab_offsets[] = {
75         offsetof (struct Mono_Posix_Syscall__Fstab, fs_spec),
76         offsetof (struct Mono_Posix_Syscall__Fstab, fs_file),
77         offsetof (struct Mono_Posix_Syscall__Fstab, fs_vfstype),
78         offsetof (struct Mono_Posix_Syscall__Fstab, fs_mntops),
79         offsetof (struct Mono_Posix_Syscall__Fstab, fs_type)
80 };
81
82 #endif /* def HAVE_FSTAB_H */
83
84 #if defined (HAVE_CHECKLIST_H) || defined (HAVE_FSTAB_H)
85
86 /*
87  * Copy the native `fstab' structure to it's managed representation.
88  *
89  * To minimize separate mallocs, all the strings are allocated within the same
90  * memory block (stored in _fs_buf_).
91  */
92 static int
93 copy_fstab (struct Mono_Posix_Syscall__Fstab *to, mph_fstab *from)
94 {
95         char *buf;
96
97         memset (to, 0, sizeof(*to));
98
99         buf = _mph_copy_structure_strings (to, mph_fstab_offsets,
100                         from, fstab_offsets, sizeof(fstab_offsets)/sizeof(fstab_offsets[0]));
101
102         to->fs_freq   = from->fs_freq;
103         to->fs_passno = from->fs_passno;
104
105         to->_fs_buf_ = buf;
106         if (buf == NULL) {
107                 return -1;
108         }
109
110         return 0;
111 }
112
113 #endif /* def HAVE_CHECKLIST_H || def HAVE_FSTAB_H */
114
115 #ifdef HAVE_SYS_VFSTAB_H
116
117 /* 
118  * Solaris doesn't provide <fstab.h> but has equivalent functionality in
119  * <sys/fstab.h> via getvfsent(3C) and company.
120  */
121
122 typedef struct vfstab mph_fstab;
123
124 static const size_t
125 vfstab_offsets[] = {
126         offsetof (struct vfstab, vfs_special),
127         offsetof (struct vfstab, vfs_mountp),
128         offsetof (struct vfstab, vfs_fstype),
129         offsetof (struct vfstab, vfs_mntopts)
130 };
131
132 static const size_t
133 mph_fstab_offsets[] = {
134         offsetof (struct Mono_Posix_Syscall__Fstab, fs_spec),
135         offsetof (struct Mono_Posix_Syscall__Fstab, fs_file),
136         offsetof (struct Mono_Posix_Syscall__Fstab, fs_vfstype),
137         offsetof (struct Mono_Posix_Syscall__Fstab, fs_mntops)
138 };
139
140 /*
141  * Copy the native `vfstab' structure to it's managed representation.
142  *
143  * To minimize separate mallocs, all the strings are allocated within the same
144  * memory block (stored in _fs_buf_).
145  */
146 static int
147 copy_fstab (struct Mono_Posix_Syscall__Fstab *to, struct vfstab *from)
148 {
149         char *buf;
150
151         memset (to, 0, sizeof(*to));
152
153         buf = _mph_copy_structure_strings (to, mph_fstab_offsets,
154                         from, vfstab_offsets, sizeof(vfstab_offsets)/sizeof(vfstab_offsets[0]));
155
156         to->fs_type   = NULL;
157         to->fs_freq   = -1;
158         to->fs_passno = -1;
159
160         to->_fs_buf_ = buf;
161         if (buf == NULL) {
162                 return -1;
163         }
164
165         return 0;
166 }
167
168 /*
169  * Implement Linux/BSD getfsent(3) in terms of Solaris getvfsent(3C)...
170  */
171 static FILE*
172 etc_fstab;
173
174 static int
175 setfsent (void)
176 {
177         /* protect from bad users calling setfsent(), setfsent(), ... endfsent() */
178         if (etc_fstab != NULL)
179                 fclose (etc_fstab);
180         etc_fstab = fopen ("/etc/vfstab", "r");
181         if (etc_fstab != NULL)
182                 return 1;
183         return 0;
184 }
185
186 static void
187 endfsent (void)
188 {
189         fclose (etc_fstab);
190         etc_fstab = NULL;
191 }
192
193 static struct vfstab
194 cur_vfstab_entry;
195
196 static struct vfstab*
197 getfsent (void)
198 {
199         int r;
200         r = getvfsent (etc_fstab, &cur_vfstab_entry);
201         if (r == 0)
202                 return &cur_vfstab_entry;
203         return NULL;
204 }
205
206 static struct vfstab*
207 getfsfile (const char *mount_point)
208 {
209         int r;
210         int close = 0;
211         if (etc_fstab == 0) {
212                 close = 1;
213                 if (setfsent () != 1)
214                         return NULL;
215         }
216         rewind (etc_fstab);
217         r = getvfsfile (etc_fstab, &cur_vfstab_entry, (char*) mount_point);
218         if (close)
219                 endfsent ();
220         if (r == 0)
221                 return &cur_vfstab_entry;
222         return NULL;
223 }
224
225 static struct vfstab*
226 getfsspec (const char *special_file)
227 {
228         int r;
229         int close = 0;
230         if (etc_fstab == 0) {
231                 close = 1;
232                 if (setfsent () != 1)
233                         return NULL;
234         }
235         rewind (etc_fstab);
236         r = getvfsspec (etc_fstab, &cur_vfstab_entry, (char*) special_file);
237         if (close)
238                 endfsent ();
239         if (r == 0)
240                 return &cur_vfstab_entry;
241         return NULL;
242 }
243
244 #endif /* def HAVE_SYS_VFSTAB_H */
245
246 #if defined (HAVE_FSTAB_H) || defined (HAVE_CHECKPOINT_H) || defined (HAVE_SYS_VFSTAB_H)
247
248 void
249 Mono_Posix_Syscall_endfsent (void)
250 {
251         endfsent ();
252 }
253
254 gint32
255 Mono_Posix_Syscall_getfsent (struct Mono_Posix_Syscall__Fstab *fsbuf)
256 {
257         mph_fstab *fs;
258
259         if (fsbuf == NULL) {
260                 errno = EFAULT;
261                 return -1;
262         }
263
264         fs = getfsent ();
265         if (fs == NULL)
266                 return -1;
267
268         if (copy_fstab (fsbuf, fs) == -1) {
269                 errno = ENOMEM;
270                 return -1;
271         }
272         return 0;
273 }
274
275 gint32
276 Mono_Posix_Syscall_getfsfile (const char *mount_point, 
277                 struct Mono_Posix_Syscall__Fstab *fsbuf)
278 {
279         mph_fstab *fs;
280
281         if (fsbuf == NULL) {
282                 errno = EFAULT;
283                 return -1;
284         }
285
286         fs = getfsfile (mount_point);
287         if (fs == NULL)
288                 return -1;
289
290         if (copy_fstab (fsbuf, fs) == -1) {
291                 errno = ENOMEM;
292                 return -1;
293         }
294         return 0;
295 }
296
297 gint32
298 Mono_Posix_Syscall_getfsspec (const char *special_file, 
299                 struct Mono_Posix_Syscall__Fstab *fsbuf)
300 {
301         mph_fstab *fs;
302
303         if (fsbuf == NULL) {
304                 errno = EFAULT;
305                 return -1;
306         }
307
308         fs = getfsspec (special_file);
309         if (fs == NULL)
310                 return -1;
311
312         if (copy_fstab (fsbuf, fs) == -1) {
313                 errno = ENOMEM;
314                 return -1;
315         }
316         return 0;
317 }
318
319 gint32
320 Mono_Posix_Syscall_setfsent (void)
321 {
322         return setfsent ();
323 }
324
325 #endif /* def HAVE_FSTAB_H || def HAVE_CHECKPOINT_H || def HAVE_SYS_VFSTAB_H */
326
327 G_END_DECLS
328
329 /*
330  * vim: noexpandtab
331  */