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