author | eschrock |
Fri, 19 Aug 2005 11:56:37 -0700 | |
changeset 380 | 4ae8f505c115 |
parent 0 | 68f95e015346 |
child 4830 | 956da15b6610 |
permissions | -rw-r--r-- |
0 | 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, Version 1.0 only |
|
6 |
* (the "License"). You may not use this file except in compliance |
|
7 |
* with the License. |
|
8 |
* |
|
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. |
|
13 |
* |
|
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] |
|
19 |
* |
|
20 |
* CDDL HEADER END |
|
21 |
*/ |
|
22 |
/* |
|
380
4ae8f505c115
6307489 getmntany() should not stat meaningless special devices
eschrock
parents:
0
diff
changeset
|
23 |
* Copyright 2005 Sun Microsystems, Inc. All rights reserved. |
0 | 24 |
* Use is subject to license terms. |
25 |
*/ |
|
26 |
||
27 |
#pragma ident "%Z%%M% %I% %E% SMI" |
|
28 |
||
29 |
/* Copyright (c) 1988 AT&T */ |
|
30 |
/* All Rights Reserved */ |
|
31 |
||
32 |
||
33 |
#pragma weak getmntany = _getmntany |
|
34 |
#pragma weak getmntent = _getmntent |
|
35 |
#pragma weak getextmntent = _getextmntent |
|
36 |
#pragma weak resetmnttab = _resetmnttab |
|
37 |
#pragma weak hasmntopt = _hasmntopt |
|
38 |
||
39 |
#include "synonyms.h" |
|
40 |
#include <mtlib.h> |
|
41 |
#include <stdio.h> |
|
42 |
#include <sys/types.h> |
|
43 |
#include <sys/stat.h> |
|
44 |
#include <sys/mnttab.h> |
|
45 |
#include <sys/mntio.h> |
|
46 |
#include <string.h> |
|
47 |
#include <ctype.h> |
|
48 |
#include <errno.h> |
|
49 |
#include <stdlib.h> |
|
50 |
#include <thread.h> |
|
51 |
#include <synch.h> |
|
52 |
#include <libc.h> |
|
53 |
#include <unistd.h> |
|
54 |
#include "tsd.h" |
|
55 |
||
56 |
static int getmntent_compat(FILE *fp, struct mnttab *mp); |
|
57 |
static int convert_mntent(struct extmnttab *, struct extmnttab *, int); |
|
58 |
||
59 |
#define GETTOK_R(xx, ll, tmp)\ |
|
60 |
if ((mp->xx = (char *)strtok_r(ll, sepstr, tmp)) == NULL)\ |
|
61 |
return (MNT_TOOFEW);\ |
|
62 |
if (strcmp(mp->xx, dash) == 0)\ |
|
63 |
mp->xx = NULL |
|
64 |
||
65 |
#define DIFF(xx)\ |
|
66 |
(mrefp->xx != NULL && (mgetp->xx == NULL ||\ |
|
67 |
strcmp(mrefp->xx, mgetp->xx) != 0)) |
|
68 |
||
69 |
#define SDIFF(xx, typem, typer)\ |
|
70 |
((mgetp->xx == NULL) || (stat64(mgetp->xx, &statb) == -1) ||\ |
|
71 |
((statb.st_mode & S_IFMT) != typem) ||\ |
|
72 |
(statb.st_rdev != typer)) |
|
73 |
||
74 |
static const char sepstr[] = " \t\n"; |
|
75 |
static const char dash[] = "-"; |
|
76 |
||
77 |
typedef struct { |
|
78 |
size_t buflen; |
|
79 |
char *buf; |
|
80 |
} thread_data_t; |
|
81 |
||
82 |
static void |
|
83 |
destroy_thread_data(void *arg) |
|
84 |
{ |
|
85 |
thread_data_t *thread_data = arg; |
|
86 |
||
87 |
if (thread_data->buf != NULL) { |
|
88 |
free(thread_data->buf); |
|
89 |
thread_data->buf = NULL; |
|
90 |
} |
|
91 |
thread_data->buflen = 0; |
|
92 |
} |
|
93 |
||
94 |
static char * |
|
95 |
getmntbuf(size_t size) |
|
96 |
{ |
|
97 |
thread_data_t *thread_data; |
|
98 |
||
99 |
if (size < MNT_LINE_MAX) |
|
100 |
size = MNT_LINE_MAX; |
|
101 |
||
102 |
thread_data = tsdalloc(_T_GETMNTENT, |
|
103 |
sizeof (thread_data_t), destroy_thread_data); |
|
104 |
if (thread_data == NULL) |
|
105 |
return (NULL); |
|
106 |
if (thread_data->buf == NULL || |
|
107 |
thread_data->buflen < size) { |
|
108 |
if (thread_data->buf != NULL) |
|
109 |
free(thread_data->buf); |
|
110 |
thread_data->buflen = 0; |
|
111 |
if ((thread_data->buf = malloc(size)) == NULL) |
|
112 |
return (NULL); |
|
113 |
thread_data->buflen = size; |
|
114 |
} |
|
115 |
return (thread_data->buf); |
|
116 |
} |
|
117 |
||
118 |
int |
|
119 |
getmntany(FILE *fp, struct mnttab *mgetp, struct mnttab *mrefp) |
|
120 |
{ |
|
121 |
int ret, bstat; |
|
122 |
mode_t bmode; |
|
123 |
dev_t brdev; |
|
124 |
struct stat64 statb; |
|
125 |
||
380
4ae8f505c115
6307489 getmntany() should not stat meaningless special devices
eschrock
parents:
0
diff
changeset
|
126 |
/* |
4ae8f505c115
6307489 getmntany() should not stat meaningless special devices
eschrock
parents:
0
diff
changeset
|
127 |
* Ignore specials that don't correspond to real devices to avoid doing |
4ae8f505c115
6307489 getmntany() should not stat meaningless special devices
eschrock
parents:
0
diff
changeset
|
128 |
* unnecessary lookups in stat64(). |
4ae8f505c115
6307489 getmntany() should not stat meaningless special devices
eschrock
parents:
0
diff
changeset
|
129 |
*/ |
4ae8f505c115
6307489 getmntany() should not stat meaningless special devices
eschrock
parents:
0
diff
changeset
|
130 |
if (mrefp->mnt_special && mrefp->mnt_special[0] == '/' && |
4ae8f505c115
6307489 getmntany() should not stat meaningless special devices
eschrock
parents:
0
diff
changeset
|
131 |
stat64(mrefp->mnt_special, &statb) == 0 && |
0 | 132 |
((bmode = (statb.st_mode & S_IFMT)) == S_IFBLK || |
133 |
bmode == S_IFCHR)) { |
|
134 |
bstat = 1; |
|
135 |
brdev = statb.st_rdev; |
|
136 |
} else { |
|
137 |
bstat = 0; |
|
138 |
} |
|
139 |
||
140 |
while ((ret = getmntent(fp, mgetp)) == 0 && |
|
141 |
((bstat == 0 && DIFF(mnt_special)) || |
|
142 |
(bstat == 1 && SDIFF(mnt_special, bmode, brdev)) || |
|
143 |
DIFF(mnt_mountp) || |
|
144 |
DIFF(mnt_fstype) || |
|
145 |
DIFF(mnt_mntopts) || |
|
146 |
DIFF(mnt_time))) |
|
147 |
; |
|
148 |
||
149 |
return (ret); |
|
150 |
} |
|
151 |
||
152 |
int |
|
153 |
getmntent(FILE *fp, struct mnttab *mp) |
|
154 |
{ |
|
155 |
int ret; |
|
156 |
struct extmnttab *emp; |
|
157 |
||
158 |
ret = ioctl(fileno(fp), MNTIOC_GETMNTENT, &emp); |
|
159 |
||
160 |
switch (ret) { |
|
161 |
case 0: |
|
162 |
return (convert_mntent(emp, (struct extmnttab *)mp, 0)); |
|
163 |
case 1: |
|
164 |
return (-1); |
|
165 |
default: |
|
166 |
return (getmntent_compat(fp, mp)); |
|
167 |
} |
|
168 |
} |
|
169 |
||
170 |
char * |
|
171 |
mntopt(char **p) |
|
172 |
{ |
|
173 |
char *cp = *p; |
|
174 |
char *retstr; |
|
175 |
||
176 |
while (*cp && isspace(*cp)) |
|
177 |
cp++; |
|
178 |
||
179 |
retstr = cp; |
|
180 |
while (*cp && *cp != ',') |
|
181 |
cp++; |
|
182 |
||
183 |
if (*cp) { |
|
184 |
*cp = '\0'; |
|
185 |
cp++; |
|
186 |
} |
|
187 |
||
188 |
*p = cp; |
|
189 |
return (retstr); |
|
190 |
} |
|
191 |
||
192 |
char * |
|
193 |
hasmntopt(struct mnttab *mnt, char *opt) |
|
194 |
{ |
|
195 |
char tmpopts[MNT_LINE_MAX]; |
|
196 |
char *f, *opts = tmpopts; |
|
197 |
||
198 |
if (mnt->mnt_mntopts == NULL) |
|
199 |
return (NULL); |
|
200 |
(void) strcpy(opts, mnt->mnt_mntopts); |
|
201 |
f = mntopt(&opts); |
|
202 |
for (; *f; f = mntopt(&opts)) { |
|
203 |
if (strncmp(opt, f, strlen(opt)) == 0) |
|
204 |
return (f - tmpopts + mnt->mnt_mntopts); |
|
205 |
} |
|
206 |
return (NULL); |
|
207 |
} |
|
208 |
||
209 |
/*ARGSUSED*/ |
|
210 |
int |
|
211 |
getextmntent(FILE *fp, struct extmnttab *mp, size_t len) |
|
212 |
{ |
|
213 |
int ret; |
|
214 |
struct extmnttab *emp; |
|
215 |
||
216 |
ret = ioctl(fileno(fp), MNTIOC_GETMNTENT, &emp); |
|
217 |
||
218 |
switch (ret) { |
|
219 |
case 0: |
|
220 |
return (convert_mntent(emp, mp, 1)); |
|
221 |
case 1: |
|
222 |
return (-1); |
|
223 |
default: |
|
224 |
return (ret); |
|
225 |
} |
|
226 |
} |
|
227 |
||
228 |
void |
|
229 |
resetmnttab(FILE *fp) |
|
230 |
{ |
|
231 |
rewind(fp); |
|
232 |
} |
|
233 |
||
234 |
/* |
|
235 |
* This is a horrible function, necessary to support this broken interface. |
|
236 |
* Some callers of get(ext)mntent assume that the memory is valid even after the |
|
237 |
* file is closed. Since we switched to a direct ioctl() interface, this is no |
|
238 |
* longer true. In order to support these apps, we have to put the data into a |
|
239 |
* thread specific buffer. |
|
240 |
*/ |
|
241 |
static int |
|
242 |
convert_mntent(struct extmnttab *src, struct extmnttab *dst, int isext) |
|
243 |
{ |
|
244 |
size_t len; |
|
245 |
char *buf; |
|
246 |
||
247 |
len = src->mnt_time - src->mnt_special + strlen(src->mnt_time) + 1; |
|
248 |
||
249 |
buf = getmntbuf(len); |
|
250 |
if (buf == NULL) { |
|
251 |
errno = ENOMEM; |
|
252 |
return (-1); |
|
253 |
} |
|
254 |
||
255 |
memcpy(buf, src->mnt_special, len); |
|
256 |
dst->mnt_special = buf; |
|
257 |
dst->mnt_mountp = buf + (src->mnt_mountp - src->mnt_special); |
|
258 |
dst->mnt_fstype = buf + (src->mnt_fstype - src->mnt_special); |
|
259 |
dst->mnt_mntopts = buf + (src->mnt_mntopts - src->mnt_special); |
|
260 |
dst->mnt_time = buf + (src->mnt_time - src->mnt_special); |
|
261 |
if (isext) { |
|
262 |
dst->mnt_major = src->mnt_major; |
|
263 |
dst->mnt_minor = src->mnt_minor; |
|
264 |
} |
|
265 |
||
266 |
return (0); |
|
267 |
} |
|
268 |
||
269 |
/* |
|
270 |
* Compatibility for non-mntfs files. For backwards compatibility, we continue |
|
271 |
* to have to support this broken interface. Note that getextmntent() has |
|
272 |
* always failed when using a file other than /etc/mnttab, because it relies on |
|
273 |
* an ioctl() call. |
|
274 |
*/ |
|
275 |
static int |
|
276 |
getline(char *lp, FILE *fp) |
|
277 |
{ |
|
278 |
char *cp; |
|
279 |
||
280 |
while ((lp = fgets(lp, MNT_LINE_MAX, fp)) != NULL) { |
|
281 |
if (strlen(lp) == MNT_LINE_MAX-1 && lp[MNT_LINE_MAX-2] != '\n') |
|
282 |
return (MNT_TOOLONG); |
|
283 |
||
284 |
for (cp = lp; *cp == ' ' || *cp == '\t'; cp++) |
|
285 |
; |
|
286 |
||
287 |
if (*cp != '#' && *cp != '\n') |
|
288 |
return (0); |
|
289 |
} |
|
290 |
return (-1); |
|
291 |
} |
|
292 |
||
293 |
static int |
|
294 |
getmntent_compat(FILE *fp, struct mnttab *mp) |
|
295 |
{ |
|
296 |
int ret; |
|
297 |
char *tmp; |
|
298 |
char *line = getmntbuf(MNT_LINE_MAX); |
|
299 |
||
300 |
if (line == NULL) { |
|
301 |
errno = ENOMEM; |
|
302 |
return (-1); |
|
303 |
} |
|
304 |
||
305 |
/* skip leading spaces and comments */ |
|
306 |
if ((ret = getline(line, fp)) != 0) |
|
307 |
return (ret); |
|
308 |
||
309 |
/* split up each field */ |
|
310 |
GETTOK_R(mnt_special, line, &tmp); |
|
311 |
GETTOK_R(mnt_mountp, NULL, &tmp); |
|
312 |
GETTOK_R(mnt_fstype, NULL, &tmp); |
|
313 |
GETTOK_R(mnt_mntopts, NULL, &tmp); |
|
314 |
GETTOK_R(mnt_time, NULL, &tmp); |
|
315 |
||
316 |
/* check for too many fields */ |
|
317 |
if (strtok_r(NULL, sepstr, &tmp) != NULL) |
|
318 |
return (MNT_TOOMANY); |
|
319 |
||
320 |
return (0); |
|
321 |
} |