4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1996,1998 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
32 * File system mount table input routines. We handle a
33 * a combination of BSD and SVR4 formats by coding functions
34 * to explicitly read the SVR4 vfstab file and using
35 * #define's to build a routine to read both BSD files
36 * (fstab and mtab) and SVR4's mnttab file. Internally
37 * we keep everything in the common (mtab/mnttab) format.
39 static struct pmntent
{
40 struct mntent
*pm_mnt
;
41 struct pmntent
*pm_next
;
44 /* Note that nothing is ever free()'d, so this is safe */
45 #define mntstrdup(s) ((s) ? strdup((s)) : "")
48 static struct mntent
*mygetmntent(FILE *, char *);
49 static struct pmntent
*addmtab(char *, struct pmntent
*);
50 static struct mntent
*allocmntent(struct mntent
*);
52 static struct pmntent
*addmtab();
53 static struct mntent
*mygetmntent();
54 static struct mntent
*allocmntent();
55 static int idatesort();
58 static struct mntent
*
63 static struct mntent mt
;
66 if ((status
= getmntent(f
, &mt
)) == 0)
70 case EOF
: break; /* normal exit condition */
72 msg(gettext("%s has a line that is too long\n"), name
);
75 msg(gettext("%s has a line with too many entries\n"), name
);
78 msg(gettext("%s has a line with too few entries\n"), name
);
82 "Unknown return code, %d, from getmntent() on %s\n"),
91 * Read in SVR4 vfstab-format table.
93 static struct pmntent
*
94 addvfstab(tablename
, pm
)
103 assert(((mnttable
== NULL
) && (pm
== NULL
)) || (pm
!= NULL
));
106 * No need to secure this, as tablename is hard-coded to VFSTAB,
107 * and that file is in /etc. If random people have write-permission
108 * there, then there are more problems than any degree of paranoia
109 * on our part can fix.
111 tp
= fopen(tablename
, "r");
112 if (tp
== (FILE *)0) {
113 msg(gettext("Cannot open %s for dump table information.\n"),
115 return ((struct pmntent
*)0);
117 while ((status
= getvfsent(tp
, &vfs
)) == 0) {
118 if (vfs
.vfs_fstype
== (char *)0 ||
119 strcmp(vfs
.vfs_fstype
, MNTTYPE_42
) != 0)
122 mnt
= (struct mnttab
*)xmalloc(sizeof (*mnt
));
123 mnt
->mnt_fsname
= mntstrdup(vfs
.vfs_special
);
124 mnt
->mnt_dir
= mntstrdup(vfs
.vfs_mountp
);
125 mnt
->mnt_type
= mntstrdup(vfs
.vfs_fstype
);
126 mnt
->mnt_opts
= mntstrdup(vfs
.vfs_mntopts
);
128 if (mnttable
== (struct pmntent
*)0)
130 * Guaranteed by caller that pm will also be NULL,
131 * so no memory leak to worry about.
133 mnttable
= pm
= (struct pmntent
*)xmalloc(sizeof (*pm
));
135 /* Guaranteed pm not NULL by caller and local logic */
136 pm
->pm_next
= (struct pmntent
*)xmalloc(sizeof (*pm
));
140 pm
->pm_next
= (struct pmntent
*)0;
144 case EOF
: break; /* normal exit condition */
146 msg(gettext("%s has a line that is too long\n"), tablename
);
149 msg(gettext("%s has a line with too many entries\n"),
153 msg(gettext("%s has a line with too few entries\n"), tablename
);
157 "Unknown return code, %d, from getvfsent() on %s\n"),
165 static struct mntent
*
171 new = (struct mntent
*)xmalloc(sizeof (*mnt
));
172 new->mnt_fsname
= mntstrdup(mnt
->mnt_fsname
); /* mnt_special */
173 new->mnt_dir
= mntstrdup(mnt
->mnt_dir
); /* mnt_mountp */
174 new->mnt_type
= mntstrdup(mnt
->mnt_type
); /* mnt_fstype */
175 new->mnt_opts
= mntstrdup(mnt
->mnt_opts
); /* mnt_mntopts */
182 struct pmntent
*pm
= (struct pmntent
*)0;
184 if (mnttable
!= (struct pmntent
*)0)
187 * Read in the file system mount tables. Order
188 * is important as the first matched entry is used
189 * if the target device/filesystem is not mounted.
190 * We try fstab or vfstab first, then mtab or mnttab.
192 pm
= addvfstab(VFSTAB
, pm
);
193 (void) addmtab(MOUNTED
, pm
);
196 static struct pmntent
*
197 addmtab(tablename
, pm
)
204 tp
= setmntent(tablename
, "r");
205 if (tp
== (FILE *)0) {
206 msg(gettext("Cannot open %s for dump table information.\n"),
208 return ((struct pmntent
*)0);
210 while (mnt
= mygetmntent(tp
, tablename
)) {
211 if (mnt
->mnt_type
== (char *)0 ||
212 strcmp(mnt
->mnt_type
, MNTTYPE_42
) != 0)
215 mnt
= allocmntent(mnt
);
216 if (mnttable
== (struct pmntent
*)0)
218 * Guaranteed by caller that pm will also be NULL,
219 * so no memory leak to worry about.
221 mnttable
= pm
= (struct pmntent
*)xmalloc(sizeof (*pm
));
223 /* Guaranteed pm not NULL by caller and local logic */
224 pm
->pm_next
= (struct pmntent
*)xmalloc(sizeof (*pm
));
228 pm
->pm_next
= (struct pmntent
*)0;
230 (void) endmntent(tp
);
235 * Search in fstab and potentially mtab for a file name.
236 * If "mounted" is non-zero, the target file system must
237 * be mounted in order for the search to succeed.
238 * This file name can be either the special or the path file name.
240 * The entries in either fstab or mtab are the BLOCK special names,
241 * not the character special names.
242 * The caller of mnttabsearch assures that the character device
243 * is dumped (that is much faster)
245 * The file name can omit the leading '/'.
248 mnttabsearch(key
, mounted
)
254 struct mntent
*first
= (struct mntent
*)0;
257 char path
[MAXPATHLEN
];
259 for (pm
= mnttable
; pm
; pm
= pm
->pm_next
) {
262 if (strcmp(mnt
->mnt_dir
, key
) == 0)
264 if (strcmp(mnt
->mnt_fsname
, key
) == 0)
266 if ((s
= rawname(mnt
->mnt_fsname
)) != NULL
&&
270 gotreal
= realpath(mnt
->mnt_dir
, path
);
271 if (gotreal
&& strcmp(path
, key
) == 0)
274 if (*mnt
->mnt_fsname
== '/' &&
275 strcmp(mnt
->mnt_fsname
+ 1, key
) == 0)
277 if (*mnt
->mnt_dir
== '/' &&
278 strcmp(mnt
->mnt_dir
+ 1, key
) == 0)
280 if (gotreal
&& *path
== '/' &&
281 strcmp(path
+ 1, key
) == 0)
284 if (s
!= NULL
&& s
!= mnt
->mnt_fsname
)
288 /* Pointer comparison, not string comparison */
289 if (s
!= NULL
&& s
!= mnt
->mnt_fsname
)
292 * Found a match; return immediately if
293 * it is mounted (valid), otherwise just
294 * record if it's the first matched entry.
296 if (lf_ismounted(mnt
->mnt_fsname
, mnt
->mnt_dir
) > 0)
298 else if (first
== (struct mntent
*)0)
302 * If we get here, there were either
303 * no matches, or no matched entries
304 * were mounted. Return failure if
305 * we were supposed to find a mounted
306 * entry, otherwise return the first
307 * matched entry (or null).
310 return ((struct mntent
*)0);
314 static struct pmntent
*current
;
341 current
= current
->pm_next
;
344 return ((struct mntent
*)0);