xref: /illumos-gate/usr/src/cmd/backup/dump/dumpfstab.c (revision 2a8bcb4e)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1996,1998 by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate  * All rights reserved.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #include "dump.h"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * File system mount table input routines.  We handle a
31*7c478bd9Sstevel@tonic-gate  * a combination of BSD and SVR4 formats by coding functions
32*7c478bd9Sstevel@tonic-gate  * to explicitly read the SVR4 vfstab file and using
33*7c478bd9Sstevel@tonic-gate  * #define's to build a routine to read both BSD files
34*7c478bd9Sstevel@tonic-gate  * (fstab and mtab) and SVR4's mnttab file.  Internally
35*7c478bd9Sstevel@tonic-gate  * we keep everything in the common (mtab/mnttab) format.
36*7c478bd9Sstevel@tonic-gate  */
37*7c478bd9Sstevel@tonic-gate static struct pmntent {
38*7c478bd9Sstevel@tonic-gate 	struct mntent	*pm_mnt;
39*7c478bd9Sstevel@tonic-gate 	struct pmntent	*pm_next;
40*7c478bd9Sstevel@tonic-gate } *mnttable;
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate /* Note that nothing is ever free()'d, so this is safe */
43*7c478bd9Sstevel@tonic-gate #define	mntstrdup(s)	((s) ? strdup((s)) : "")
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate #ifdef __STDC__
46*7c478bd9Sstevel@tonic-gate static struct mntent *mygetmntent(FILE *, char *);
47*7c478bd9Sstevel@tonic-gate static struct pmntent *addmtab(char *, struct pmntent *);
48*7c478bd9Sstevel@tonic-gate static struct mntent *allocmntent(struct mntent *);
49*7c478bd9Sstevel@tonic-gate #else /* !__STDC__ */
50*7c478bd9Sstevel@tonic-gate static struct pmntent *addmtab();
51*7c478bd9Sstevel@tonic-gate static struct mntent *mygetmntent();
52*7c478bd9Sstevel@tonic-gate static struct mntent *allocmntent();
53*7c478bd9Sstevel@tonic-gate static int idatesort();
54*7c478bd9Sstevel@tonic-gate #endif
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate static struct mntent *
mygetmntent(f,name)57*7c478bd9Sstevel@tonic-gate mygetmntent(f, name)
58*7c478bd9Sstevel@tonic-gate 	FILE *f;
59*7c478bd9Sstevel@tonic-gate 	char *name;
60*7c478bd9Sstevel@tonic-gate {
61*7c478bd9Sstevel@tonic-gate 	static struct mntent mt;
62*7c478bd9Sstevel@tonic-gate 	int status;
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate 	if ((status = getmntent(f, &mt)) == 0)
65*7c478bd9Sstevel@tonic-gate 		return (&mt);
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate 	switch (status) {
68*7c478bd9Sstevel@tonic-gate 	case EOF:	break;		/* normal exit condition */
69*7c478bd9Sstevel@tonic-gate 	case MNT_TOOLONG:
70*7c478bd9Sstevel@tonic-gate 		msg(gettext("%s has a line that is too long\n"), name);
71*7c478bd9Sstevel@tonic-gate 		break;
72*7c478bd9Sstevel@tonic-gate 	case MNT_TOOMANY:
73*7c478bd9Sstevel@tonic-gate 		msg(gettext("%s has a line with too many entries\n"), name);
74*7c478bd9Sstevel@tonic-gate 		break;
75*7c478bd9Sstevel@tonic-gate 	case MNT_TOOFEW:
76*7c478bd9Sstevel@tonic-gate 		msg(gettext("%s has a line with too few entries\n"), name);
77*7c478bd9Sstevel@tonic-gate 		break;
78*7c478bd9Sstevel@tonic-gate 	default:
79*7c478bd9Sstevel@tonic-gate 		msg(gettext(
80*7c478bd9Sstevel@tonic-gate 			"Unknown return code, %d, from getmntent() on %s\n"),
81*7c478bd9Sstevel@tonic-gate 			status, name);
82*7c478bd9Sstevel@tonic-gate 		break;
83*7c478bd9Sstevel@tonic-gate 	}
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate 	return (NULL);
86*7c478bd9Sstevel@tonic-gate }
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate /*
89*7c478bd9Sstevel@tonic-gate  * Read in SVR4 vfstab-format table.
90*7c478bd9Sstevel@tonic-gate  */
91*7c478bd9Sstevel@tonic-gate static struct pmntent *
addvfstab(tablename,pm)92*7c478bd9Sstevel@tonic-gate addvfstab(tablename, pm)
93*7c478bd9Sstevel@tonic-gate 	char	*tablename;
94*7c478bd9Sstevel@tonic-gate 	struct pmntent *pm;
95*7c478bd9Sstevel@tonic-gate {
96*7c478bd9Sstevel@tonic-gate 	struct mnttab *mnt;
97*7c478bd9Sstevel@tonic-gate 	struct vfstab vfs;
98*7c478bd9Sstevel@tonic-gate 	FILE	*tp;
99*7c478bd9Sstevel@tonic-gate 	int status;
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate 	assert(((mnttable == NULL) && (pm == NULL)) || (pm != NULL));
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate 	/*
104*7c478bd9Sstevel@tonic-gate 	 * No need to secure this, as tablename is hard-coded to VFSTAB,
105*7c478bd9Sstevel@tonic-gate 	 * and that file is in /etc.  If random people have write-permission
106*7c478bd9Sstevel@tonic-gate 	 * there, then there are more problems than any degree of paranoia
107*7c478bd9Sstevel@tonic-gate 	 * on our part can fix.
108*7c478bd9Sstevel@tonic-gate 	 */
109*7c478bd9Sstevel@tonic-gate 	tp = fopen(tablename, "r");
110*7c478bd9Sstevel@tonic-gate 	if (tp == (FILE *)0) {
111*7c478bd9Sstevel@tonic-gate 		msg(gettext("Cannot open %s for dump table information.\n"),
112*7c478bd9Sstevel@tonic-gate 			tablename);
113*7c478bd9Sstevel@tonic-gate 		return ((struct pmntent *)0);
114*7c478bd9Sstevel@tonic-gate 	}
115*7c478bd9Sstevel@tonic-gate 	while ((status = getvfsent(tp, &vfs)) == 0) {
116*7c478bd9Sstevel@tonic-gate 		if (vfs.vfs_fstype == (char *)0 ||
117*7c478bd9Sstevel@tonic-gate 		    strcmp(vfs.vfs_fstype, MNTTYPE_42) != 0)
118*7c478bd9Sstevel@tonic-gate 			continue;
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate 		mnt = (struct mnttab *)xmalloc(sizeof (*mnt));
121*7c478bd9Sstevel@tonic-gate 		mnt->mnt_fsname = mntstrdup(vfs.vfs_special);
122*7c478bd9Sstevel@tonic-gate 		mnt->mnt_dir = mntstrdup(vfs.vfs_mountp);
123*7c478bd9Sstevel@tonic-gate 		mnt->mnt_type = mntstrdup(vfs.vfs_fstype);
124*7c478bd9Sstevel@tonic-gate 		mnt->mnt_opts = mntstrdup(vfs.vfs_mntopts);
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate 		if (mnttable == (struct pmntent *)0)
127*7c478bd9Sstevel@tonic-gate 			/*
128*7c478bd9Sstevel@tonic-gate 			 * Guaranteed by caller that pm will also be NULL,
129*7c478bd9Sstevel@tonic-gate 			 * so no memory leak to worry about.
130*7c478bd9Sstevel@tonic-gate 			 */
131*7c478bd9Sstevel@tonic-gate 			mnttable = pm = (struct pmntent *)xmalloc(sizeof (*pm));
132*7c478bd9Sstevel@tonic-gate 		else {
133*7c478bd9Sstevel@tonic-gate 			/* Guaranteed pm not NULL by caller and local logic */
134*7c478bd9Sstevel@tonic-gate 			pm->pm_next = (struct pmntent *)xmalloc(sizeof (*pm));
135*7c478bd9Sstevel@tonic-gate 			pm = pm->pm_next;
136*7c478bd9Sstevel@tonic-gate 		}
137*7c478bd9Sstevel@tonic-gate 		pm->pm_mnt = mnt;
138*7c478bd9Sstevel@tonic-gate 		pm->pm_next = (struct pmntent *)0;
139*7c478bd9Sstevel@tonic-gate 	}
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 	switch (status) {
142*7c478bd9Sstevel@tonic-gate 	case EOF:	break;		/* normal exit condition */
143*7c478bd9Sstevel@tonic-gate 	case VFS_TOOLONG:
144*7c478bd9Sstevel@tonic-gate 		msg(gettext("%s has a line that is too long\n"), tablename);
145*7c478bd9Sstevel@tonic-gate 		break;
146*7c478bd9Sstevel@tonic-gate 	case VFS_TOOMANY:
147*7c478bd9Sstevel@tonic-gate 		msg(gettext("%s has a line with too many entries\n"),
148*7c478bd9Sstevel@tonic-gate 			tablename);
149*7c478bd9Sstevel@tonic-gate 		break;
150*7c478bd9Sstevel@tonic-gate 	case VFS_TOOFEW:
151*7c478bd9Sstevel@tonic-gate 		msg(gettext("%s has a line with too few entries\n"), tablename);
152*7c478bd9Sstevel@tonic-gate 		break;
153*7c478bd9Sstevel@tonic-gate 	default:
154*7c478bd9Sstevel@tonic-gate 		msg(gettext(
155*7c478bd9Sstevel@tonic-gate 			"Unknown return code, %d, from getvfsent() on %s\n"),
156*7c478bd9Sstevel@tonic-gate 			status, tablename);
157*7c478bd9Sstevel@tonic-gate 		break;
158*7c478bd9Sstevel@tonic-gate 	}
159*7c478bd9Sstevel@tonic-gate 	(void) fclose(tp);
160*7c478bd9Sstevel@tonic-gate 	return (pm);
161*7c478bd9Sstevel@tonic-gate }
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate static struct mntent *
allocmntent(mnt)164*7c478bd9Sstevel@tonic-gate allocmntent(mnt)
165*7c478bd9Sstevel@tonic-gate 	struct mntent *mnt;
166*7c478bd9Sstevel@tonic-gate {
167*7c478bd9Sstevel@tonic-gate 	struct mntent *new;
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate 	new = (struct mntent *)xmalloc(sizeof (*mnt));
170*7c478bd9Sstevel@tonic-gate 	new->mnt_fsname = mntstrdup(mnt->mnt_fsname);	/* mnt_special */
171*7c478bd9Sstevel@tonic-gate 	new->mnt_dir = mntstrdup(mnt->mnt_dir);		/* mnt_mountp  */
172*7c478bd9Sstevel@tonic-gate 	new->mnt_type = mntstrdup(mnt->mnt_type);	/* mnt_fstype  */
173*7c478bd9Sstevel@tonic-gate 	new->mnt_opts = mntstrdup(mnt->mnt_opts);	/* mnt_mntopts */
174*7c478bd9Sstevel@tonic-gate 	return (new);
175*7c478bd9Sstevel@tonic-gate }
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate void
mnttabread()178*7c478bd9Sstevel@tonic-gate mnttabread()
179*7c478bd9Sstevel@tonic-gate {
180*7c478bd9Sstevel@tonic-gate 	struct pmntent *pm = (struct pmntent *)0;
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate 	if (mnttable != (struct pmntent *)0)
183*7c478bd9Sstevel@tonic-gate 		return;
184*7c478bd9Sstevel@tonic-gate 	/*
185*7c478bd9Sstevel@tonic-gate 	 * Read in the file system mount tables.  Order
186*7c478bd9Sstevel@tonic-gate 	 * is important as the first matched entry is used
187*7c478bd9Sstevel@tonic-gate 	 * if the target device/filesystem is not mounted.
188*7c478bd9Sstevel@tonic-gate 	 * We try fstab or vfstab first, then mtab or mnttab.
189*7c478bd9Sstevel@tonic-gate 	 */
190*7c478bd9Sstevel@tonic-gate 	pm = addvfstab(VFSTAB, pm);
191*7c478bd9Sstevel@tonic-gate 	(void) addmtab(MOUNTED, pm);
192*7c478bd9Sstevel@tonic-gate }
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate static struct pmntent *
addmtab(tablename,pm)195*7c478bd9Sstevel@tonic-gate addmtab(tablename, pm)
196*7c478bd9Sstevel@tonic-gate 	char	*tablename;
197*7c478bd9Sstevel@tonic-gate 	struct pmntent *pm;
198*7c478bd9Sstevel@tonic-gate {
199*7c478bd9Sstevel@tonic-gate 	struct mntent *mnt;
200*7c478bd9Sstevel@tonic-gate 	FILE	*tp;
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	tp = setmntent(tablename, "r");
203*7c478bd9Sstevel@tonic-gate 	if (tp == (FILE *)0) {
204*7c478bd9Sstevel@tonic-gate 		msg(gettext("Cannot open %s for dump table information.\n"),
205*7c478bd9Sstevel@tonic-gate 			tablename);
206*7c478bd9Sstevel@tonic-gate 		return ((struct pmntent *)0);
207*7c478bd9Sstevel@tonic-gate 	}
208*7c478bd9Sstevel@tonic-gate 	while (mnt = mygetmntent(tp, tablename)) {
209*7c478bd9Sstevel@tonic-gate 		if (mnt->mnt_type == (char *)0 ||
210*7c478bd9Sstevel@tonic-gate 		    strcmp(mnt->mnt_type, MNTTYPE_42) != 0)
211*7c478bd9Sstevel@tonic-gate 			continue;
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 		mnt = allocmntent(mnt);
214*7c478bd9Sstevel@tonic-gate 		if (mnttable == (struct pmntent *)0)
215*7c478bd9Sstevel@tonic-gate 			/*
216*7c478bd9Sstevel@tonic-gate 			 * Guaranteed by caller that pm will also be NULL,
217*7c478bd9Sstevel@tonic-gate 			 * so no memory leak to worry about.
218*7c478bd9Sstevel@tonic-gate 			 */
219*7c478bd9Sstevel@tonic-gate 			mnttable = pm = (struct pmntent *)xmalloc(sizeof (*pm));
220*7c478bd9Sstevel@tonic-gate 		else {
221*7c478bd9Sstevel@tonic-gate 			/* Guaranteed pm not NULL by caller and local logic */
222*7c478bd9Sstevel@tonic-gate 			pm->pm_next = (struct pmntent *)xmalloc(sizeof (*pm));
223*7c478bd9Sstevel@tonic-gate 			pm = pm->pm_next;
224*7c478bd9Sstevel@tonic-gate 		}
225*7c478bd9Sstevel@tonic-gate 		pm->pm_mnt = mnt;
226*7c478bd9Sstevel@tonic-gate 		pm->pm_next = (struct pmntent *)0;
227*7c478bd9Sstevel@tonic-gate 	}
228*7c478bd9Sstevel@tonic-gate 	(void) endmntent(tp);
229*7c478bd9Sstevel@tonic-gate 	return (pm);
230*7c478bd9Sstevel@tonic-gate }
231*7c478bd9Sstevel@tonic-gate 
232*7c478bd9Sstevel@tonic-gate /*
233*7c478bd9Sstevel@tonic-gate  * Search in fstab and potentially mtab for a file name.
234*7c478bd9Sstevel@tonic-gate  * If "mounted" is non-zero, the target file system must
235*7c478bd9Sstevel@tonic-gate  * be mounted in order for the search to succeed.
236*7c478bd9Sstevel@tonic-gate  * This file name can be either the special or the path file name.
237*7c478bd9Sstevel@tonic-gate  *
238*7c478bd9Sstevel@tonic-gate  * The entries in either fstab or mtab are the BLOCK special names,
239*7c478bd9Sstevel@tonic-gate  * not the character special names.
240*7c478bd9Sstevel@tonic-gate  * The caller of mnttabsearch assures that the character device
241*7c478bd9Sstevel@tonic-gate  * is dumped (that is much faster)
242*7c478bd9Sstevel@tonic-gate  *
243*7c478bd9Sstevel@tonic-gate  * The file name can omit the leading '/'.
244*7c478bd9Sstevel@tonic-gate  */
245*7c478bd9Sstevel@tonic-gate struct mntent *
mnttabsearch(key,mounted)246*7c478bd9Sstevel@tonic-gate mnttabsearch(key, mounted)
247*7c478bd9Sstevel@tonic-gate 	char	*key;
248*7c478bd9Sstevel@tonic-gate 	int	mounted;
249*7c478bd9Sstevel@tonic-gate {
250*7c478bd9Sstevel@tonic-gate 	struct pmntent *pm;
251*7c478bd9Sstevel@tonic-gate 	struct mntent *mnt;
252*7c478bd9Sstevel@tonic-gate 	struct mntent *first = (struct mntent *)0;
253*7c478bd9Sstevel@tonic-gate 	char *s;
254*7c478bd9Sstevel@tonic-gate 	char *gotreal;
255*7c478bd9Sstevel@tonic-gate 	char path[MAXPATHLEN];
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 	for (pm = mnttable; pm; pm = pm->pm_next) {
258*7c478bd9Sstevel@tonic-gate 		s = NULL;
259*7c478bd9Sstevel@tonic-gate 		mnt = pm->pm_mnt;
260*7c478bd9Sstevel@tonic-gate 		if (strcmp(mnt->mnt_dir, key) == 0)
261*7c478bd9Sstevel@tonic-gate 			goto found;
262*7c478bd9Sstevel@tonic-gate 		if (strcmp(mnt->mnt_fsname, key) == 0)
263*7c478bd9Sstevel@tonic-gate 			goto found;
264*7c478bd9Sstevel@tonic-gate 		if ((s = rawname(mnt->mnt_fsname)) != NULL &&
265*7c478bd9Sstevel@tonic-gate 		    strcmp(s, key) == 0)
266*7c478bd9Sstevel@tonic-gate 			goto found;
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate 		gotreal = realpath(mnt->mnt_dir, path);
269*7c478bd9Sstevel@tonic-gate 		if (gotreal && strcmp(path, key) == 0)
270*7c478bd9Sstevel@tonic-gate 			goto found;
271*7c478bd9Sstevel@tonic-gate 		if (key[0] != '/') {
272*7c478bd9Sstevel@tonic-gate 			if (*mnt->mnt_fsname == '/' &&
273*7c478bd9Sstevel@tonic-gate 			    strcmp(mnt->mnt_fsname + 1, key) == 0)
274*7c478bd9Sstevel@tonic-gate 				goto found;
275*7c478bd9Sstevel@tonic-gate 			if (*mnt->mnt_dir == '/' &&
276*7c478bd9Sstevel@tonic-gate 			    strcmp(mnt->mnt_dir + 1, key) == 0)
277*7c478bd9Sstevel@tonic-gate 				goto found;
278*7c478bd9Sstevel@tonic-gate 			if (gotreal && *path == '/' &&
279*7c478bd9Sstevel@tonic-gate 			    strcmp(path + 1, key) == 0)
280*7c478bd9Sstevel@tonic-gate 				goto found;
281*7c478bd9Sstevel@tonic-gate 		}
282*7c478bd9Sstevel@tonic-gate 		if (s != NULL && s != mnt->mnt_fsname)
283*7c478bd9Sstevel@tonic-gate 			free(s);
284*7c478bd9Sstevel@tonic-gate 		continue;
285*7c478bd9Sstevel@tonic-gate found:
286*7c478bd9Sstevel@tonic-gate 		/* Pointer comparison, not string comparison */
287*7c478bd9Sstevel@tonic-gate 		if (s != NULL && s != mnt->mnt_fsname)
288*7c478bd9Sstevel@tonic-gate 			free(s);
289*7c478bd9Sstevel@tonic-gate 		/*
290*7c478bd9Sstevel@tonic-gate 		 * Found a match; return immediately if
291*7c478bd9Sstevel@tonic-gate 		 * it is mounted (valid), otherwise just
292*7c478bd9Sstevel@tonic-gate 		 * record if it's the first matched entry.
293*7c478bd9Sstevel@tonic-gate 		 */
294*7c478bd9Sstevel@tonic-gate 		if (lf_ismounted(mnt->mnt_fsname, mnt->mnt_dir) > 0)
295*7c478bd9Sstevel@tonic-gate 			return (mnt);
296*7c478bd9Sstevel@tonic-gate 		else if (first == (struct mntent *)0)
297*7c478bd9Sstevel@tonic-gate 			first = mnt;
298*7c478bd9Sstevel@tonic-gate 	}
299*7c478bd9Sstevel@tonic-gate 	/*
300*7c478bd9Sstevel@tonic-gate 	 * If we get here, there were either
301*7c478bd9Sstevel@tonic-gate 	 * no matches, or no matched entries
302*7c478bd9Sstevel@tonic-gate 	 * were mounted.  Return failure if
303*7c478bd9Sstevel@tonic-gate 	 * we were supposed to find a mounted
304*7c478bd9Sstevel@tonic-gate 	 * entry, otherwise return the first
305*7c478bd9Sstevel@tonic-gate 	 * matched entry (or null).
306*7c478bd9Sstevel@tonic-gate 	 */
307*7c478bd9Sstevel@tonic-gate 	if (mounted)
308*7c478bd9Sstevel@tonic-gate 		return ((struct mntent *)0);
309*7c478bd9Sstevel@tonic-gate 	return (first);
310*7c478bd9Sstevel@tonic-gate }
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate static struct pmntent *current;
313*7c478bd9Sstevel@tonic-gate static int set;
314*7c478bd9Sstevel@tonic-gate 
315*7c478bd9Sstevel@tonic-gate void
316*7c478bd9Sstevel@tonic-gate #ifdef __STDC__
setmnttab(void)317*7c478bd9Sstevel@tonic-gate setmnttab(void)
318*7c478bd9Sstevel@tonic-gate #else
319*7c478bd9Sstevel@tonic-gate setmnttab()
320*7c478bd9Sstevel@tonic-gate #endif
321*7c478bd9Sstevel@tonic-gate {
322*7c478bd9Sstevel@tonic-gate 	current = mnttable;
323*7c478bd9Sstevel@tonic-gate 	set = 1;
324*7c478bd9Sstevel@tonic-gate }
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate struct mntent *
327*7c478bd9Sstevel@tonic-gate #ifdef __STDC__
getmnttab(void)328*7c478bd9Sstevel@tonic-gate getmnttab(void)
329*7c478bd9Sstevel@tonic-gate #else
330*7c478bd9Sstevel@tonic-gate getmnttab()
331*7c478bd9Sstevel@tonic-gate #endif
332*7c478bd9Sstevel@tonic-gate {
333*7c478bd9Sstevel@tonic-gate 	struct pmntent *pm;
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate 	if (!set)
336*7c478bd9Sstevel@tonic-gate 		setmnttab();
337*7c478bd9Sstevel@tonic-gate 	pm = current;
338*7c478bd9Sstevel@tonic-gate 	if (current) {
339*7c478bd9Sstevel@tonic-gate 		current = current->pm_next;
340*7c478bd9Sstevel@tonic-gate 		return (pm->pm_mnt);
341*7c478bd9Sstevel@tonic-gate 	}
342*7c478bd9Sstevel@tonic-gate 	return ((struct mntent *)0);
343*7c478bd9Sstevel@tonic-gate }
344