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