xref: /illumos-gate/usr/src/lib/libc/port/gen/getvfsent.c (revision 6a634c9d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /*	Copyright (c) 1988 AT&T	*/
27 /*	  All Rights Reserved  	*/
28 
29 #include	"lint.h"
30 #include	<mtlib.h>
31 #include	<stdio.h>
32 #include	<stdlib.h>
33 #include	<errno.h>
34 #include	<sys/types.h>
35 #include	<sys/stat.h>
36 #include	<sys/vfstab.h>
37 #include	<string.h>
38 #include	<thread.h>
39 #include	<synch.h>
40 #include	<strings.h>
41 #include	<libc.h>
42 #include	"tsd.h"
43 
44 
45 #define	GETTOK_R(xx, ll, tmp)\
46 	if ((vp->xx = (char *)strtok_r(ll, sepstr, tmp)) == NULL)\
47 		return (VFS_TOOFEW);\
48 	if (strcmp(vp->xx, dash) == 0)\
49 		vp->xx = NULL
50 #define	GETTOK(xx, ll)\
51 	if ((vp->xx = strtok(ll, sepstr)) == NULL)\
52 		return (VFS_TOOFEW);\
53 	if (strcmp(vp->xx, dash) == 0)\
54 		vp->xx = NULL
55 #define	DIFF(xx)\
56 	(vrefp->xx != NULL && (vgetp->xx == NULL ||\
57 	    strcmp(vrefp->xx, vgetp->xx) != 0))
58 #define	SDIFF(xx, typem, typer)\
59 	(vgetp->xx == NULL || stat64(vgetp->xx, &statb) == -1 ||\
60 	(statb.st_mode & S_IFMT) != typem ||\
61 	    statb.st_rdev != typer)
62 
63 static const char	sepstr[] = " \t\n";
64 static const char	dash[] = "-";
65 
66 static int	getaline(char *, FILE *);
67 
68 int
getvfsspec(FILE * fd,struct vfstab * vgetp,char * special)69 getvfsspec(FILE *fd, struct vfstab *vgetp, char *special)
70 {
71 	int	ret, bstat;
72 	mode_t	bmode;
73 	dev_t	brdev;
74 	struct stat64	statb;
75 
76 
77 	if (special && stat64(special, &statb) == 0 &&
78 	    ((bmode = (statb.st_mode & S_IFMT)) == S_IFBLK ||
79 	    bmode == S_IFCHR)) {
80 		bstat = 1;
81 		brdev = statb.st_rdev;
82 	} else
83 		bstat = 0;
84 
85 	while ((ret = getvfsent(fd, vgetp)) == 0 &&
86 	    ((bstat == 0 &&
87 	    (special != NULL && (vgetp->vfs_special == NULL ||
88 	    strcmp(special, vgetp->vfs_special) != 0))) ||
89 	    (bstat == 1 &&
90 	    (vgetp->vfs_special == NULL ||
91 	    stat64(vgetp->vfs_special, &statb) == -1 ||
92 	    (statb.st_mode & S_IFMT) != bmode ||
93 	    statb.st_rdev != brdev))))
94 		;
95 	return (ret);
96 }
97 
98 int
getvfsfile(FILE * fd,struct vfstab * vp,char * mountp)99 getvfsfile(FILE *fd, struct vfstab *vp, char *mountp)
100 {
101 	struct vfstab	vv;
102 
103 	bzero(&vv, (size_t)sizeof (vv));
104 	vv.vfs_mountp = mountp;
105 	return (getvfsany(fd, vp, &vv));
106 }
107 
108 int
getvfsany(FILE * fd,struct vfstab * vgetp,struct vfstab * vrefp)109 getvfsany(FILE *fd, struct vfstab *vgetp, struct vfstab *vrefp)
110 {
111 	int	ret, bstat, cstat;
112 	mode_t	bmode, cmode;
113 	dev_t	brdev, crdev;
114 	struct stat64	statb;
115 	off64_t start = ftello64(fd);
116 
117 	/* Match by straight strcmp */
118 	while ((ret = getvfsent(fd, vgetp)) == 0 &&
119 	    (DIFF(vfs_special) || DIFF(vfs_fsckdev) ||
120 	    DIFF(vfs_mountp) ||
121 	    DIFF(vfs_fstype) ||
122 	    DIFF(vfs_fsckpass) ||
123 	    DIFF(vfs_automnt) ||
124 	    DIFF(vfs_mntopts)))
125 		;
126 
127 	/* If something other than EOF, return it */
128 	if (ret != -1)
129 		return (ret);
130 
131 	/*
132 	 * Go back to the original location in the file and try to
133 	 * match the devices by doing stat's (retains compatibility
134 	 * with original getvfsany).
135 	 */
136 	(void) fseeko64(fd, start, SEEK_SET);
137 
138 	if (vrefp->vfs_special && stat64(vrefp->vfs_special, &statb) == 0 &&
139 	    ((bmode = (statb.st_mode & S_IFMT)) == S_IFBLK ||
140 	    bmode == S_IFCHR)) {
141 		bstat = 1;
142 		brdev = statb.st_rdev;
143 	} else
144 		bstat = 0;
145 
146 	if (vrefp->vfs_fsckdev && stat64(vrefp->vfs_fsckdev, &statb) == 0 &&
147 	    ((cmode = (statb.st_mode & S_IFMT)) == S_IFBLK ||
148 	    cmode == S_IFCHR)) {
149 		cstat = 1;
150 		crdev = statb.st_rdev;
151 	} else
152 		cstat = 0;
153 
154 	while ((ret = getvfsent(fd, vgetp)) == 0 &&
155 	    ((bstat == 0 && DIFF(vfs_special)) ||
156 	    (bstat == 1 && SDIFF(vfs_special, bmode, brdev)) ||
157 	    (cstat == 0 && DIFF(vfs_fsckdev)) ||
158 	    (cstat == 1 && SDIFF(vfs_fsckdev, cmode, crdev)) ||
159 	    DIFF(vfs_mountp) ||
160 	    DIFF(vfs_fstype) ||
161 	    DIFF(vfs_fsckpass) ||
162 	    DIFF(vfs_automnt) ||
163 	    DIFF(vfs_mntopts)))
164 		;
165 	return (ret);
166 }
167 
168 int
getvfsent(FILE * fd,struct vfstab * vp)169 getvfsent(FILE *fd, struct vfstab *vp)
170 {
171 	int	ret;
172 	char	*tmp, *line;
173 
174 	line = tsdalloc(_T_GETVFSENT, VFS_LINE_MAX, NULL);
175 	if (line == NULL)
176 		return (0);
177 
178 	/* skip leading spaces and comments */
179 	if ((ret = getaline(line, fd)) != 0)
180 		return (ret);
181 
182 	/* split up each field */
183 	GETTOK_R(vfs_special, line, &tmp);
184 	GETTOK_R(vfs_fsckdev, NULL, &tmp);
185 	GETTOK_R(vfs_mountp, NULL, &tmp);
186 	GETTOK_R(vfs_fstype, NULL, &tmp);
187 	GETTOK_R(vfs_fsckpass, NULL, &tmp);
188 	GETTOK_R(vfs_automnt, NULL, &tmp);
189 	GETTOK_R(vfs_mntopts, NULL, &tmp);
190 
191 	/* check for too many fields */
192 	if (strtok_r(NULL, sepstr, &tmp) != NULL)
193 		return (VFS_TOOMANY);
194 
195 	return (0);
196 }
197 
198 static int
getaline(char * lp,FILE * fd)199 getaline(char *lp, FILE *fd)
200 {
201 	char	*cp;
202 
203 	while ((lp = fgets(lp, VFS_LINE_MAX, fd)) != NULL) {
204 		if (strlen(lp) == VFS_LINE_MAX-1 && lp[VFS_LINE_MAX-2] != '\n')
205 			return (VFS_TOOLONG);
206 
207 		for (cp = lp; *cp == ' ' || *cp == '\t'; cp++)
208 			;
209 
210 		if (*cp != '#' && *cp != '\n')
211 			return (0);
212 	}
213 	return (-1);
214 }
215