1 /*
2  * Copyright (c) 1992-1998 Michael A. Cooper.
3  * This software may be freely used and distributed provided it is not
4  * sold for profit or used in part or in whole for commercial gain
5  * without prior written agreement, and the author is credited
6  * appropriately.
7  */
8 /*
9  * Copyright (c) 1983 Regents of the University of California.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *	This product includes software developed by the University of
23  *	California, Berkeley and its contributors.
24  * 4. Neither the name of the University nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  */
40 
41 #ifndef lint
42 static char RCSid[] =
43 "$Id: filesys-os.c,v 6.18 1998/11/10 04:09:58 mcooper Exp $";
44 
45 static char sccsid[] = "@(#)filesys-os.c";
46 
47 static char copyright[] =
48 "Copyright (c) 1992-1998 Michael A. Cooper.\n\
49 @(#) Copyright (c) 1983 Regents of the University of California.\n\
50  All rights reserved.\n";
51 #endif /* not lint */
52 
53 /*
54  * OS specific file system routines
55  */
56 
57 #include "defs.h"
58 #include "filesys.h"
59 
60 #if 	FSI_TYPE == FSI_GETFSSTAT
61 static struct statfs   *mnt = NULL;
62 typedef u_long 		ulong;
63 #endif	/* FSI_GETFSSTAT */
64 
65 #if	FSI_TYPE == FSI_MNTCTL
66 static struct vmount   *mnt = NULL;
67 #endif	/* FSI_MNTCTL */
68 
69 #if	(FSI_TYPE == FSI_MNTCTL) || (FSI_TYPE == FSI_GETFSSTAT)
70 static char 	       *mntbuf = NULL;
71 static int 		entries_left;
72 #endif	/* FSI_MNTCTL || FSI_GETFSSTAT */
73 
74 #if	FSI_TYPE == FSI_MNTCTL
75 /*
76  * AIX version of setmountent()
77  */
setmountent(file,mode)78 FILE *setmountent(file, mode)
79 	/*ARGSUSED*/
80 	char *file;
81 	char *mode;
82 {
83 	ulong size;
84 
85 	if (mntbuf)
86 		(void) free(mntbuf);
87 
88 	mntctl(MCTL_QUERY, sizeof(size), &size);
89 	mntbuf = (char *) xmalloc(size);
90 
91 	entries_left = mntctl(MCTL_QUERY, size, mntbuf);
92 	if (!entries_left)
93 		return((FILE *)NULL);
94 
95 	mnt = (struct vmount *)mntbuf;
96 	return((FILE *) 1);
97 }
98 #endif	/* FSI_MNTCTL */
99 
100 #if	FSI_TYPE == FSI_GETFSSTAT
101 /*
102  * getfsstat() version of get mount info routines.
103  */
setmountent(file,mode)104 FILE *setmountent(file, mode)
105 	/*ARGSUSED*/
106 	char *file;
107 	char *mode;
108 {
109 	ulong size;
110 
111 	if (mntbuf)
112 		(void) free(mntbuf);
113 
114 	size = getfsstat((struct statfs *) NULL, 0, MNT_WAIT);
115 	size *= sizeof(struct statfs);
116 	mntbuf = (char *) xmalloc(size);
117 
118 	entries_left = getfsstat((struct statfs *)mntbuf, size, MNT_WAIT);
119 	if (entries_left == -1)
120 		return((FILE *) NULL);
121 
122 	mnt = (struct statfs *) mntbuf;
123 
124 	return((FILE *) 1);
125 }
126 #endif	/* FSI_GETFSSTAT */
127 
128 #if	FSI_TYPE == FSI_MNTCTL
129 /*
130  * AIX version of getmountent()
131  */
132 /*
133  * Iterate over mount entries
134  */
getmountent(fptr)135 mntent_t *getmountent(fptr)
136 	/*ARGSUSED*/
137 	FILE *fptr;
138 {
139 	static mntent_t mntstruct;
140 
141 	if (!entries_left)
142 		return((mntent_t*)0);
143 
144 	bzero((char *) &mntstruct, sizeof(mntstruct));
145 
146 	if (mnt->vmt_flags & MNT_READONLY)
147 		mntstruct.me_flags |= MEFLAG_READONLY;
148 
149 	mntstruct.me_path = vmt2dataptr(mnt, VMT_STUB);
150 	switch ((ulong)(struct vmount*)mnt->vmt_gfstype) {
151 	      case MNT_NFS:
152 		mntstruct.me_type = METYPE_NFS;
153 		break;
154 	      default:
155 		mntstruct.me_type = METYPE_OTHER;
156 		break;
157 	}
158 
159 	mnt = (struct vmount*)((mnt->vmt_length)+(char *)mnt);
160 	entries_left--;
161 
162 	return(&mntstruct);
163 }
164 #endif	/* FSI_MNTCTL */
165 
166 #if	FSI_TYPE == FSI_GETFSSTAT
167 /*
168  * getfsstat() version of getmountent()
169  */
getmountent(fptr)170 mntent_t *getmountent(fptr)
171 	/*ARGSUSED*/
172 	FILE *fptr;
173 {
174 	static mntent_t mntstruct;
175 	static char remote_dev[MAXHOSTNAMELEN+MAXPATHLEN+1];
176 
177 	if (!entries_left)
178 		return((mntent_t*)0);
179 
180 	bzero((char *) &mntstruct, sizeof(mntstruct));
181 
182 #if	defined(MNT_RDONLY)
183 	if (mnt->f_flags & MNT_RDONLY)
184 		mntstruct.me_flags |= MEFLAG_READONLY;
185 #endif
186 #if	defined(M_RDONLY)
187 	if (mnt->f_flags & M_RDONLY)
188 		mntstruct.me_flags |= MEFLAG_READONLY;
189 #endif
190 #ifdef MOUNT_NFS
191 	switch ((ulong)((struct statfs*)mnt)->f_type) {
192 	      case MOUNT_NFS:
193 		(void) sprintf(remote_dev, "%s", mnt->f_mntfromname);
194 		mntstruct.me_path = remote_dev;
195 		mntstruct.me_type = METYPE_NFS;
196 		break;
197 	      default:
198 		mntstruct.me_path = mnt->f_mntonname;
199 		mntstruct.me_type = METYPE_OTHER;
200 		break;
201 	}
202 #else
203 	if ((((struct statfs*)mnt)->f_flags & MNT_LOCAL) == 0) {
204 		(void) sprintf(remote_dev, "%s", mnt->f_mntfromname);
205 		mntstruct.me_path = remote_dev;
206 		mntstruct.me_type = METYPE_NFS;
207 	} else {
208 		mntstruct.me_path = mnt->f_mntonname;
209 		mntstruct.me_type = METYPE_OTHER;
210 	}
211 #endif
212 
213 	mnt++;
214 	entries_left--;
215 
216 	return(&mntstruct);
217 }
218 #endif
219 
220 #if	(FSI_TYPE == FSI_MNTCTL) || (FSI_TYPE == FSI_GETFSSTAT)
221 /*
222  * Done with iterations
223  */
endmountent(fptr)224 void endmountent(fptr)
225 	/*ARGSUSED*/
226 	FILE *fptr;
227 {
228 	mnt = NULL;
229 
230 	if (mntbuf) {
231 		(void) free(mntbuf);
232 		mntbuf = (char *) NULL;
233 	}
234 }
235 #endif	/* FSI_MNTCTL || FSI_GETFSSTAT */
236 
237 #if	FSI_TYPE == FSI_GETMNTENT2
238 /*
239  * Prepare to iterate over mounted filesystem list
240  */
setmountent(file,mode)241 FILE *setmountent(file, mode)
242 	/*ARGSUSED*/
243 	char *file;
244 	char *mode;
245 {
246 	return(fopen(file, mode));
247 }
248 
249 /*
250  * Done with iteration
251  */
endmountent(fptr)252 void endmountent(fptr)
253 	/*ARGSUSED*/
254 	FILE *fptr;
255 {
256 	fclose(fptr);
257 }
258 
259 /*
260  * Iterate over mount entries
261  */
getmountent(fptr)262 mntent_t *getmountent(fptr)
263 	FILE *fptr;
264 {
265 	static mntent_t me;
266 	static struct mnttab mntent;
267 
268 	bzero((char *)&me, sizeof(mntent_t));
269 
270 #if     defined(UNICOS)
271         if (getmntent(fptr, &mntent) != NULL) {
272 #else
273         if (getmntent(fptr, &mntent) != -1) {
274 #endif
275 		me.me_path = mntent.mnt_mountp;
276 		me.me_type = mntent.mnt_fstype;
277 		if (mntent.mnt_mntopts && hasmntopt(&mntent, MNTOPT_RO))
278 			me.me_flags |= MEFLAG_READONLY;
279 
280 #if	defined(MNTTYPE_IGNORE)
281 		if (strcmp(mntent.mnt_fstype, MNTTYPE_IGNORE) == 0)
282 			me.me_flags |= MEFLAG_IGNORE;
283 #endif	/* MNTTYPE_IGNORE */
284 #if	defined(MNTTYPE_SWAP)
285 		if (strcmp(mntent.mnt_fstype, MNTTYPE_SWAP) == 0)
286 			me.me_flags |= MEFLAG_IGNORE;
287 #endif	/* MNTTYPE_SWAP */
288 
289 		return(&me);
290 	} else
291 		return((mntent_t *) NULL);
292 }
293 #endif	/* FSI_GETMNTNET2 */
294 
295 #if	FSI_TYPE == FSI_GETMNTENT
296 /*
297  * Prepare to iterate over mounted filesystem list
298  */
setmountent(file,mode)299 FILE *setmountent(file, mode)
300 	/*ARGSUSED*/
301 	char *file;
302 	char *mode;
303 {
304 	return(setmntent(file, mode));
305 }
306 
307 /*
308  * Done with iteration
309  */
endmountent(fptr)310 void endmountent(fptr)
311 	/*ARGSUSED*/
312 	FILE *fptr;
313 {
314 	endmntent(fptr);
315 }
316 
317 /*
318  * Iterate over mount entries
319  */
getmountent(fptr)320 mntent_t *getmountent(fptr)
321 	FILE *fptr;
322 {
323 	static mntent_t me;
324 	struct mntent *mntent;
325 
326 	bzero((char *)&me, sizeof(mntent_t));
327 
328 	if (mntent = getmntent(fptr)) {
329 		me.me_path = mntent->mnt_dir;
330 		me.me_type = mntent->mnt_type;
331 		if (mntent->mnt_opts && hasmntopt(mntent, MNTOPT_RO))
332 			me.me_flags |= MEFLAG_READONLY;
333 
334 #if	defined(MNTTYPE_IGNORE)
335 		if (strcmp(mntent->mnt_type, MNTTYPE_IGNORE) == 0)
336 			me.me_flags |= MEFLAG_IGNORE;
337 #endif	/* MNTTYPE_IGNORE */
338 #if	defined(MNTTYPE_SWAP)
339 		if (strcmp(mntent->mnt_type, MNTTYPE_SWAP) == 0)
340 			me.me_flags |= MEFLAG_IGNORE;
341 #endif	/* MNTTYPE_SWAP */
342 
343 		return(&me);
344 	} else
345 		return((mntent_t *) NULL);
346 }
347 #endif	/* FSI_GETMNTNET */
348 
349 #if	FSI_TYPE == FSI_GETMNT
350 /*
351  * getmnt() interface (Ultrix)
352  */
353 
354 #include <sys/fs_types.h>
355 
356 static int startmounts = 0;
357 
setmountent(file,mode)358 FILE *setmountent(file, mode)
359 	/*ARGSUSED*/
360 	char *file;
361 	char *mode;
362 {
363 	startmounts = 0;
364 }
365 
endmountent(fptr)366 void endmountent(fptr)
367 	/*ARGSUSED*/
368 	FILE *fptr;
369 {
370 	/* NOOP */
371 }
372 
373 /*
374  * Iterate over mounted filesystems using getmnt()
375  */
getmountent(fptr)376 mntent_t *getmountent(fptr)
377 	/*ARGSUSED*/
378 	FILE *fptr;
379 {
380 	struct fs_data fs_data;
381 	static mntent_t me;
382 
383 	if (getmnt(&startmounts, &fs_data, sizeof(fs_data), NOSTAT_MANY,
384 		   (char *) NULL) <= 0)
385 		return((mntent_t *) NULL);
386 
387 	bzero((char *)&me, sizeof(mntent_t));
388 	me.me_path = fs_data.fd_path;
389 	if (fs_data.fd_fstype == GT_NFS)
390 		me.me_type = METYPE_NFS;
391 	else
392 		me.me_type = METYPE_OTHER;
393 
394 	if (fs_data.fd_flags & M_RONLY)
395 		me.me_flags |= MEFLAG_READONLY;
396 
397 	return(&me);
398 }
399 #endif	/* FSI_GETMNT */
400 
401 /*
402  * Make a new (copy) of a mntent structure.
403  */
newmountent(old)404 mntent_t *newmountent(old)
405 	mntent_t *old;
406 {
407 	mntent_t *new;
408 
409 	if (!old)
410 		return((mntent_t *) NULL);
411 
412 	new = (mntent_t *) xcalloc(1, sizeof(mntent_t));
413 	new->me_path = strdup(old->me_path);
414 	new->me_type = strdup(old->me_type);
415 	new->me_flags = old->me_flags;
416 
417 	return(new);
418 }
419