| @@ -1,778 +1,776 @@ | | | @@ -1,778 +1,776 @@ |
1 | /* $NetBSD: mount.c,v 1.97 2012/06/14 00:39:33 christos Exp $ */ | | 1 | /* $NetBSD: mount.c,v 1.98 2013/01/24 17:53:49 christos Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1980, 1989, 1993, 1994 | | 4 | * Copyright (c) 1980, 1989, 1993, 1994 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * 3. Neither the name of the University nor the names of its contributors | | 15 | * 3. Neither the name of the University nor the names of its contributors |
16 | * may be used to endorse or promote products derived from this software | | 16 | * may be used to endorse or promote products derived from this software |
17 | * without specific prior written permission. | | 17 | * without specific prior written permission. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 | * SUCH DAMAGE. | | 29 | * SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | #ifndef lint | | 33 | #ifndef lint |
34 | __COPYRIGHT("@(#) Copyright (c) 1980, 1989, 1993, 1994\ | | 34 | __COPYRIGHT("@(#) Copyright (c) 1980, 1989, 1993, 1994\ |
35 | The Regents of the University of California. All rights reserved."); | | 35 | The Regents of the University of California. All rights reserved."); |
36 | #endif /* not lint */ | | 36 | #endif /* not lint */ |
37 | | | 37 | |
38 | #ifndef lint | | 38 | #ifndef lint |
39 | #if 0 | | 39 | #if 0 |
40 | static char sccsid[] = "@(#)mount.c 8.25 (Berkeley) 5/8/95"; | | 40 | static char sccsid[] = "@(#)mount.c 8.25 (Berkeley) 5/8/95"; |
41 | #else | | 41 | #else |
42 | __RCSID("$NetBSD: mount.c,v 1.97 2012/06/14 00:39:33 christos Exp $"); | | 42 | __RCSID("$NetBSD: mount.c,v 1.98 2013/01/24 17:53:49 christos Exp $"); |
43 | #endif | | 43 | #endif |
44 | #endif /* not lint */ | | 44 | #endif /* not lint */ |
45 | | | 45 | |
46 | #include <sys/param.h> | | 46 | #include <sys/param.h> |
47 | #include <sys/mount.h> | | 47 | #include <sys/mount.h> |
48 | #include <sys/wait.h> | | 48 | #include <sys/wait.h> |
49 | | | 49 | |
50 | #include <fs/puffs/puffs_msgif.h> | | 50 | #include <fs/puffs/puffs_msgif.h> |
51 | | | 51 | |
52 | #include <err.h> | | 52 | #include <err.h> |
53 | #include <errno.h> | | 53 | #include <errno.h> |
54 | #include <fstab.h> | | 54 | #include <fstab.h> |
55 | #include <pwd.h> | | 55 | #include <pwd.h> |
56 | #include <signal.h> | | 56 | #include <signal.h> |
57 | #include <stdio.h> | | 57 | #include <stdio.h> |
58 | #include <stdlib.h> | | 58 | #include <stdlib.h> |
59 | #include <string.h> | | 59 | #include <string.h> |
60 | #include <unistd.h> | | 60 | #include <unistd.h> |
61 | #include <util.h> | | 61 | #include <util.h> |
62 | | | 62 | |
63 | #define MOUNTNAMES | | 63 | #define MOUNTNAMES |
64 | #include <fcntl.h> | | 64 | #include <fcntl.h> |
65 | #include <sys/disk.h> | | 65 | #include <sys/disk.h> |
66 | #include <sys/disklabel.h> | | 66 | #include <sys/disklabel.h> |
67 | #include <sys/ioctl.h> | | 67 | #include <sys/ioctl.h> |
68 | | | 68 | |
69 | #include "pathnames.h" | | 69 | #include "pathnames.h" |
70 | #include "mountprog.h" | | 70 | #include "mountprog.h" |
71 | | | 71 | |
72 | static int debug, verbose; | | 72 | static int debug, verbose; |
73 | | | 73 | |
74 | static void catopt(char **, const char *); | | 74 | static void catopt(char **, const char *); |
75 | static const char * | | 75 | static const char * |
76 | getfslab(const char *str); | | 76 | getfslab(const char *str); |
77 | static struct statvfs * | | 77 | static struct statvfs * |
78 | getmntpt(const char *); | | 78 | getmntpt(const char *); |
79 | static int getmntargs(struct statvfs *, char *, size_t); | | 79 | static int getmntargs(struct statvfs *, char *, size_t); |
80 | static int hasopt(const char *, const char *); | | 80 | static int hasopt(const char *, const char *); |
81 | static void mangle(char *, int *, const char ** volatile *, int *); | | 81 | static void mangle(char *, int *, const char ** volatile *, int *); |
82 | static int mountfs(const char *, const char *, const char *, | | 82 | static int mountfs(const char *, const char *, const char *, |
83 | int, const char *, const char *, int, char *, size_t); | | 83 | int, const char *, const char *, int, char *, size_t); |
84 | static void prmount(struct statvfs *); | | 84 | static void prmount(struct statvfs *); |
85 | __dead static void usage(void); | | 85 | __dead static void usage(void); |
86 | | | 86 | |
87 | | | 87 | |
88 | /* Map from mount otions to printable formats. */ | | 88 | /* Map from mount otions to printable formats. */ |
89 | static const struct opt { | | 89 | static const struct opt { |
90 | int o_opt; | | 90 | int o_opt; |
91 | int o_silent; | | 91 | int o_silent; |
92 | const char *o_name; | | 92 | const char *o_name; |
93 | } optnames[] = { | | 93 | } optnames[] = { |
94 | __MNT_FLAGS | | 94 | __MNT_FLAGS |
95 | }; | | 95 | }; |
96 | | | 96 | |
97 | static const char ffs_fstype[] = "ffs"; | | 97 | static const char ffs_fstype[] = "ffs"; |
98 | | | 98 | |
99 | int | | 99 | int |
100 | main(int argc, char *argv[]) | | 100 | main(int argc, char *argv[]) |
101 | { | | 101 | { |
102 | const char *mntfromname, *mntonname, **vfslist, *vfstype; | | 102 | const char *mntfromname, *mntonname, **vfslist, *vfstype; |
103 | struct fstab *fs; | | 103 | struct fstab *fs; |
104 | struct statvfs *mntbuf; | | 104 | struct statvfs *mntbuf; |
105 | #if 0 | | 105 | #if 0 |
106 | FILE *mountdfp; | | 106 | FILE *mountdfp; |
107 | #endif | | 107 | #endif |
108 | int all, ch, forceall, i, init_flags, mntsize, rval; | | 108 | int all, ch, forceall, i, init_flags, mntsize, rval; |
109 | char *options; | | 109 | char *options; |
110 | const char *mountopts, *fstypename; | | 110 | const char *mountopts, *fstypename; |
111 | char canonical_path_buf[MAXPATHLEN], buf[MAXPATHLEN]; | | 111 | char canonical_path_buf[MAXPATHLEN], buf[MAXPATHLEN]; |
112 | char *canonical_path; | | 112 | char *canonical_path; |
113 | | | 113 | |
114 | /* started as "mount" */ | | 114 | /* started as "mount" */ |
115 | all = forceall = init_flags = 0; | | 115 | all = forceall = init_flags = 0; |
116 | options = NULL; | | 116 | options = NULL; |
117 | vfslist = NULL; | | 117 | vfslist = NULL; |
118 | vfstype = ffs_fstype; | | 118 | vfstype = ffs_fstype; |
119 | while ((ch = getopt(argc, argv, "Aadfo:rwt:uv")) != -1) | | 119 | while ((ch = getopt(argc, argv, "Aadfo:rwt:uv")) != -1) |
120 | switch (ch) { | | 120 | switch (ch) { |
121 | case 'A': | | 121 | case 'A': |
122 | all = forceall = 1; | | 122 | all = forceall = 1; |
123 | break; | | 123 | break; |
124 | case 'a': | | 124 | case 'a': |
125 | all = 1; | | 125 | all = 1; |
126 | break; | | 126 | break; |
127 | case 'd': | | 127 | case 'd': |
128 | debug = 1; | | 128 | debug = 1; |
129 | break; | | 129 | break; |
130 | case 'f': | | 130 | case 'f': |
131 | init_flags |= MNT_FORCE; | | 131 | init_flags |= MNT_FORCE; |
132 | break; | | 132 | break; |
133 | case 'o': | | 133 | case 'o': |
134 | if (*optarg) | | 134 | if (*optarg) |
135 | catopt(&options, optarg); | | 135 | catopt(&options, optarg); |
136 | break; | | 136 | break; |
137 | case 'r': | | 137 | case 'r': |
138 | init_flags |= MNT_RDONLY; | | 138 | init_flags |= MNT_RDONLY; |
139 | break; | | 139 | break; |
140 | case 't': | | 140 | case 't': |
141 | if (vfslist != NULL) | | 141 | if (vfslist != NULL) |
142 | errx(EXIT_FAILURE, | | 142 | errx(EXIT_FAILURE, |
143 | "Only one -t option may be specified."); | | 143 | "Only one -t option may be specified."); |
144 | vfslist = makevfslist(optarg); | | 144 | vfslist = makevfslist(optarg); |
145 | vfstype = optarg; | | 145 | vfstype = optarg; |
146 | break; | | 146 | break; |
147 | case 'u': | | 147 | case 'u': |
148 | init_flags |= MNT_UPDATE; | | 148 | init_flags |= MNT_UPDATE; |
149 | break; | | 149 | break; |
150 | case 'v': | | 150 | case 'v': |
151 | verbose++; | | 151 | verbose++; |
152 | break; | | 152 | break; |
153 | case 'w': | | 153 | case 'w': |
154 | init_flags &= ~MNT_RDONLY; | | 154 | init_flags &= ~MNT_RDONLY; |
155 | break; | | 155 | break; |
156 | case '?': | | 156 | case '?': |
157 | default: | | 157 | default: |
158 | usage(); | | 158 | usage(); |
159 | /* NOTREACHED */ | | 159 | /* NOTREACHED */ |
160 | } | | 160 | } |
161 | argc -= optind; | | 161 | argc -= optind; |
162 | argv += optind; | | 162 | argv += optind; |
163 | | | 163 | |
164 | #define BADTYPE(type) \ | | 164 | #define BADTYPE(type) \ |
165 | (strcmp(type, FSTAB_RO) && \ | | 165 | (strcmp(type, FSTAB_RO) && \ |
166 | strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ)) | | 166 | strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ)) |
167 | | | 167 | |
168 | rval = 0; | | 168 | rval = 0; |
169 | switch (argc) { | | 169 | switch (argc) { |
170 | case 0: | | 170 | case 0: |
171 | if (all) | | 171 | if (all) |
172 | while ((fs = getfsent()) != NULL) { | | 172 | while ((fs = getfsent()) != NULL) { |
173 | if (BADTYPE(fs->fs_type)) | | 173 | if (BADTYPE(fs->fs_type)) |
174 | continue; | | 174 | continue; |
175 | if (checkvfsname(fs->fs_vfstype, vfslist)) | | 175 | if (checkvfsname(fs->fs_vfstype, vfslist)) |
176 | continue; | | 176 | continue; |
177 | if (hasopt(fs->fs_mntops, "noauto")) | | 177 | if (hasopt(fs->fs_mntops, "noauto")) |
178 | continue; | | 178 | continue; |
179 | if (strcmp(fs->fs_spec, "from_mount") == 0) { | | 179 | if (strcmp(fs->fs_spec, "from_mount") == 0) { |
180 | if ((mntbuf = getmntpt(fs->fs_file)) | | 180 | if ((mntbuf = getmntpt(fs->fs_file)) |
181 | == NULL) | | 181 | == NULL) |
182 | errx(EXIT_FAILURE, | | 182 | errx(EXIT_FAILURE, |
183 | "Unknown file system %s", | | 183 | "Unknown file system %s", |
184 | fs->fs_file); | | 184 | fs->fs_file); |
185 | mntfromname = mntbuf->f_mntfromname; | | 185 | mntfromname = mntbuf->f_mntfromname; |
186 | } else | | 186 | } else |
187 | mntfromname = fs->fs_spec; | | 187 | mntfromname = fs->fs_spec; |
188 | mntfromname = getfsspecname(buf, sizeof(buf), | | 188 | mntfromname = getfsspecname(buf, sizeof(buf), |
189 | mntfromname); | | 189 | mntfromname); |
190 | if (mntfromname == NULL) | | 190 | if (mntfromname == NULL) |
191 | err(EXIT_FAILURE, "%s", buf); | | 191 | err(EXIT_FAILURE, "%s", buf); |
192 | if (mountfs(fs->fs_vfstype, mntfromname, | | 192 | if (mountfs(fs->fs_vfstype, mntfromname, |
193 | fs->fs_file, init_flags, options, | | 193 | fs->fs_file, init_flags, options, |
194 | fs->fs_mntops, !forceall, NULL, 0)) | | 194 | fs->fs_mntops, !forceall, NULL, 0)) |
195 | rval = 1; | | 195 | rval = 1; |
196 | } | | 196 | } |
197 | else { | | 197 | else { |
198 | if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) | | 198 | if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) |
199 | err(EXIT_FAILURE, "getmntinfo"); | | 199 | err(EXIT_FAILURE, "getmntinfo"); |
200 | for (i = 0; i < mntsize; i++) { | | 200 | for (i = 0; i < mntsize; i++) { |
201 | if (checkvfsname(mntbuf[i].f_fstypename, | | 201 | if (checkvfsname(mntbuf[i].f_fstypename, |
202 | vfslist)) | | 202 | vfslist)) |
203 | continue; | | 203 | continue; |
204 | prmount(&mntbuf[i]); | | 204 | prmount(&mntbuf[i]); |
205 | } | | 205 | } |
206 | } | | 206 | } |
207 | exit(rval); | | 207 | return rval; |
208 | /* NOTREACHED */ | | | |
209 | case 1: | | 208 | case 1: |
210 | if (vfslist != NULL) { | | 209 | if (vfslist != NULL) { |
211 | usage(); | | 210 | usage(); |
212 | /* NOTREACHED */ | | 211 | /* NOTREACHED */ |
213 | } | | 212 | } |
214 | | | 213 | |
215 | /* | | 214 | /* |
216 | * Create a canonical version of the device or mount path | | 215 | * Create a canonical version of the device or mount path |
217 | * passed to us. It's ok for this to fail. It's also ok | | 216 | * passed to us. It's ok for this to fail. It's also ok |
218 | * for the result to be exactly the same as the original. | | 217 | * for the result to be exactly the same as the original. |
219 | */ | | 218 | */ |
220 | canonical_path = realpath(*argv, canonical_path_buf); | | 219 | canonical_path = realpath(*argv, canonical_path_buf); |
221 | | | 220 | |
222 | if (init_flags & MNT_UPDATE) { | | 221 | if (init_flags & MNT_UPDATE) { |
223 | /* | | 222 | /* |
224 | * Try looking up the canonical path first, | | 223 | * Try looking up the canonical path first, |
225 | * then try exactly what the user entered. | | 224 | * then try exactly what the user entered. |
226 | */ | | 225 | */ |
227 | if ((canonical_path == NULL || | | 226 | if ((canonical_path == NULL || |
228 | (mntbuf = getmntpt(canonical_path)) == NULL) && | | 227 | (mntbuf = getmntpt(canonical_path)) == NULL) && |
229 | (mntbuf = getmntpt(*argv)) == NULL) { | | 228 | (mntbuf = getmntpt(*argv)) == NULL) { |
230 | out: | | 229 | out: |
231 | errx(EXIT_FAILURE, | | 230 | errx(EXIT_FAILURE, |
232 | "Unknown special file or file system `%s'", | | 231 | "Unknown special file or file system `%s'", |
233 | *argv); | | 232 | *argv); |
234 | } | | 233 | } |
235 | mntfromname = mntbuf->f_mntfromname; | | 234 | mntfromname = mntbuf->f_mntfromname; |
236 | if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL) { | | 235 | if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL) { |
237 | if (strcmp(fs->fs_spec, "from_mount") != 0) | | 236 | if (strcmp(fs->fs_spec, "from_mount") != 0) |
238 | mntfromname = fs->fs_spec; | | 237 | mntfromname = fs->fs_spec; |
239 | /* ignore the fstab file options. */ | | 238 | /* ignore the fstab file options. */ |
240 | fs->fs_mntops = NULL; | | 239 | fs->fs_mntops = NULL; |
241 | } | | 240 | } |
242 | mntonname = mntbuf->f_mntonname; | | 241 | mntonname = mntbuf->f_mntonname; |
243 | fstypename = mntbuf->f_fstypename; | | 242 | fstypename = mntbuf->f_fstypename; |
244 | mountopts = NULL; | | 243 | mountopts = NULL; |
245 | } else { | | 244 | } else { |
246 | /* | | 245 | /* |
247 | * Try looking up the canonical path first, | | 246 | * Try looking up the canonical path first, |
248 | * then try exactly what the user entered. | | 247 | * then try exactly what the user entered. |
249 | */ | | 248 | */ |
250 | if (canonical_path == NULL || | | 249 | if (canonical_path == NULL || |
251 | ((fs = getfsfile(canonical_path)) == NULL && | | 250 | ((fs = getfsfile(canonical_path)) == NULL && |
252 | (fs = getfsspec(canonical_path)) == NULL)) | | 251 | (fs = getfsspec(canonical_path)) == NULL)) |
253 | { | | 252 | { |
254 | if ((fs = getfsfile(*argv)) == NULL && | | 253 | if ((fs = getfsfile(*argv)) == NULL && |
255 | (fs = getfsspec(*argv)) == NULL) { | | 254 | (fs = getfsspec(*argv)) == NULL) { |
256 | goto out; | | 255 | goto out; |
257 | } | | 256 | } |
258 | } | | 257 | } |
259 | if (BADTYPE(fs->fs_type)) | | 258 | if (BADTYPE(fs->fs_type)) |
260 | errx(EXIT_FAILURE, | | 259 | errx(EXIT_FAILURE, |
261 | "Unknown file system type for `%s'", | | 260 | "Unknown file system type for `%s'", |
262 | *argv); | | 261 | *argv); |
263 | if (strcmp(fs->fs_spec, "from_mount") == 0) { | | 262 | if (strcmp(fs->fs_spec, "from_mount") == 0) { |
264 | if ((canonical_path == NULL || | | 263 | if ((canonical_path == NULL || |
265 | (mntbuf = getmntpt(canonical_path)) | | 264 | (mntbuf = getmntpt(canonical_path)) |
266 | == NULL) && | | 265 | == NULL) && |
267 | (mntbuf = getmntpt(*argv)) == NULL) | | 266 | (mntbuf = getmntpt(*argv)) == NULL) |
268 | goto out; | | 267 | goto out; |
269 | mntfromname = mntbuf->f_mntfromname; | | 268 | mntfromname = mntbuf->f_mntfromname; |
270 | } else | | 269 | } else |
271 | mntfromname = fs->fs_spec; | | 270 | mntfromname = fs->fs_spec; |
272 | mntonname = fs->fs_file; | | 271 | mntonname = fs->fs_file; |
273 | fstypename = fs->fs_vfstype; | | 272 | fstypename = fs->fs_vfstype; |
274 | mountopts = fs->fs_mntops; | | 273 | mountopts = fs->fs_mntops; |
275 | } | | 274 | } |
276 | mntfromname = getfsspecname(buf, sizeof(buf), mntfromname); | | 275 | mntfromname = getfsspecname(buf, sizeof(buf), mntfromname); |
277 | if (mntfromname == NULL) | | 276 | if (mntfromname == NULL) |
278 | err(EXIT_FAILURE, "%s", buf); | | 277 | err(EXIT_FAILURE, "%s", buf); |
279 | rval = mountfs(fstypename, mntfromname, | | 278 | rval = mountfs(fstypename, mntfromname, |
280 | mntonname, init_flags, options, mountopts, 0, NULL, 0); | | 279 | mntonname, init_flags, options, mountopts, 0, NULL, 0); |
281 | break; | | 280 | break; |
282 | case 2: | | 281 | case 2: |
283 | /* | | 282 | /* |
284 | * If -t flag has not been specified, and spec contains either | | 283 | * If -t flag has not been specified, and spec contains either |
285 | * a ':' or a '@' then assume that an NFS filesystem is being | | 284 | * a ':' or a '@' then assume that an NFS filesystem is being |
286 | * specified ala Sun. | | 285 | * specified ala Sun. |
287 | */ | | 286 | */ |
288 | mntfromname = getfsspecname(buf, sizeof(buf), argv[0]); | | 287 | mntfromname = getfsspecname(buf, sizeof(buf), argv[0]); |
289 | if (mntfromname == NULL) | | 288 | if (mntfromname == NULL) |
290 | err(EXIT_FAILURE, "%s", buf); | | 289 | err(EXIT_FAILURE, "%s", buf); |
291 | if (vfslist == NULL) { | | 290 | if (vfslist == NULL) { |
292 | if (strpbrk(argv[0], ":@") != NULL) { | | 291 | if (strpbrk(argv[0], ":@") != NULL) { |
293 | fprintf(stderr, "WARNING: autoselecting nfs " | | 292 | fprintf(stderr, "WARNING: autoselecting nfs " |
294 | "based on : or @ in the device name is " | | 293 | "based on : or @ in the device name is " |
295 | "deprecated!\n" | | 294 | "deprecated!\n" |
296 | "WARNING: This behaviour will be removed " | | 295 | "WARNING: This behaviour will be removed " |
297 | "in a future release\n"); | | 296 | "in a future release\n"); |
298 | vfstype = "nfs"; | | 297 | vfstype = "nfs"; |
299 | } else { | | 298 | } else { |
300 | vfstype = getfslab(mntfromname); | | 299 | vfstype = getfslab(mntfromname); |
301 | if (vfstype == NULL) | | 300 | if (vfstype == NULL) |
302 | vfstype = ffs_fstype; | | 301 | vfstype = ffs_fstype; |
303 | } | | 302 | } |
304 | } | | 303 | } |
305 | rval = mountfs(vfstype, mntfromname, argv[1], init_flags, | | 304 | rval = mountfs(vfstype, mntfromname, argv[1], init_flags, |
306 | options, NULL, 0, NULL, 0); | | 305 | options, NULL, 0, NULL, 0); |
307 | break; | | 306 | break; |
308 | default: | | 307 | default: |
309 | usage(); | | 308 | usage(); |
310 | } | | 309 | } |
311 | | | 310 | |
312 | #if 0 /* disabled because it interferes the service. */ | | 311 | #if 0 /* disabled because it interferes the service. */ |
313 | /* | | 312 | /* |
314 | * If the mount was successfully, and done by root, tell mountd the | | 313 | * If the mount was successfully, and done by root, tell mountd the |
315 | * good news. Pid checks are probably unnecessary, but don't hurt. | | 314 | * good news. Pid checks are probably unnecessary, but don't hurt. |
316 | */ | | 315 | */ |
317 | if (rval == 0 && getuid() == 0 && | | 316 | if (rval == 0 && getuid() == 0 && |
318 | (mountdfp = fopen(_PATH_MOUNTDPID, "r")) != NULL) { | | 317 | (mountdfp = fopen(_PATH_MOUNTDPID, "r")) != NULL) { |
319 | int pid; | | 318 | int pid; |
320 | | | 319 | |
321 | if (fscanf(mountdfp, "%d", &pid) == 1 && | | 320 | if (fscanf(mountdfp, "%d", &pid) == 1 && |
322 | pid > 0 && kill(pid, SIGHUP) == -1 && errno != ESRCH) | | 321 | pid > 0 && kill(pid, SIGHUP) == -1 && errno != ESRCH) |
323 | err(EXIT_FAILURE, "signal mountd"); | | 322 | err(EXIT_FAILURE, "signal mountd"); |
324 | (void)fclose(mountdfp); | | 323 | (void)fclose(mountdfp); |
325 | } | | 324 | } |
326 | #endif | | 325 | #endif |
327 | | | 326 | |
328 | exit(rval); | | 327 | return rval; |
329 | /* NOTREACHED */ | | | |
330 | } | | 328 | } |
331 | | | 329 | |
332 | int | | 330 | int |
333 | hasopt(const char *mntopts, const char *option) | | 331 | hasopt(const char *mntopts, const char *option) |
334 | { | | 332 | { |
335 | int negative, found; | | 333 | int negative, found; |
336 | char *opt, *optbuf; | | 334 | char *opt, *optbuf; |
337 | | | 335 | |
338 | if (option[0] == 'n' && option[1] == 'o') { | | 336 | if (option[0] == 'n' && option[1] == 'o') { |
339 | negative = 1; | | 337 | negative = 1; |
340 | option += 2; | | 338 | option += 2; |
341 | } else | | 339 | } else |
342 | negative = 0; | | 340 | negative = 0; |
343 | optbuf = estrdup(mntopts); | | 341 | optbuf = estrdup(mntopts); |
344 | found = 0; | | 342 | found = 0; |
345 | for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) { | | 343 | for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) { |
346 | if (opt[0] == 'n' && opt[1] == 'o') { | | 344 | if (opt[0] == 'n' && opt[1] == 'o') { |
347 | if (!strcasecmp(opt + 2, option)) | | 345 | if (!strcasecmp(opt + 2, option)) |
348 | found = negative; | | 346 | found = negative; |
349 | } else if (!strcasecmp(opt, option)) | | 347 | } else if (!strcasecmp(opt, option)) |
350 | found = !negative; | | 348 | found = !negative; |
351 | } | | 349 | } |
352 | free(optbuf); | | 350 | free(optbuf); |
353 | return (found); | | 351 | return (found); |
354 | } | | 352 | } |
355 | | | 353 | |
356 | static int | | 354 | static int |
357 | mountfs(const char *vfstype, const char *spec, const char *name, | | 355 | mountfs(const char *vfstype, const char *spec, const char *name, |
358 | int flags, const char *options, const char *mntopts, | | 356 | int flags, const char *options, const char *mntopts, |
359 | int skipmounted, char *buf, size_t buflen) | | 357 | int skipmounted, char *buf, size_t buflen) |
360 | { | | 358 | { |
361 | /* List of directories containing mount_xxx subcommands. */ | | 359 | /* List of directories containing mount_xxx subcommands. */ |
362 | static const char *edirs[] = { | | 360 | static const char *edirs[] = { |
363 | #ifdef RESCUEDIR | | 361 | #ifdef RESCUEDIR |
364 | RESCUEDIR, | | 362 | RESCUEDIR, |
365 | #endif | | 363 | #endif |
366 | _PATH_SBIN, | | 364 | _PATH_SBIN, |
367 | _PATH_USRSBIN, | | 365 | _PATH_USRSBIN, |
368 | NULL | | 366 | NULL |
369 | }; | | 367 | }; |
370 | const char ** volatile argv, **edir; | | 368 | const char ** volatile argv, **edir; |
371 | struct statvfs *sfp, sf; | | 369 | struct statvfs *sfp, sf; |
372 | pid_t pid; | | 370 | pid_t pid; |
373 | int pfd[2]; | | 371 | int pfd[2]; |
374 | int argc, numfs, i, status, maxargc; | | 372 | int argc, numfs, i, status, maxargc; |
375 | char *optbuf, execname[MAXPATHLEN + 1], execbase[MAXPATHLEN], | | 373 | char *optbuf, execname[MAXPATHLEN + 1], execbase[MAXPATHLEN], |
376 | mntpath[MAXPATHLEN]; | | 374 | mntpath[MAXPATHLEN]; |
377 | volatile int getargs; | | 375 | volatile int getargs; |
378 | | | 376 | |
379 | if (realpath(name, mntpath) == NULL) { | | 377 | if (realpath(name, mntpath) == NULL) { |
380 | warn("realpath `%s'", name); | | 378 | warn("realpath `%s'", name); |
381 | return (1); | | 379 | return (1); |
382 | } | | 380 | } |
383 | | | 381 | |
384 | name = mntpath; | | 382 | name = mntpath; |
385 | | | 383 | |
386 | optbuf = NULL; | | 384 | optbuf = NULL; |
387 | if (mntopts) | | 385 | if (mntopts) |
388 | catopt(&optbuf, mntopts); | | 386 | catopt(&optbuf, mntopts); |
389 | | | 387 | |
390 | if (options) { | | 388 | if (options) { |
391 | catopt(&optbuf, options); | | 389 | catopt(&optbuf, options); |
392 | getargs = strstr(options, "getargs") != NULL; | | 390 | getargs = strstr(options, "getargs") != NULL; |
393 | } else | | 391 | } else |
394 | getargs = 0; | | 392 | getargs = 0; |
395 | | | 393 | |
396 | if (!mntopts && !options) | | 394 | if (!mntopts && !options) |
397 | catopt(&optbuf, "rw"); | | 395 | catopt(&optbuf, "rw"); |
398 | | | 396 | |
399 | if (getargs == 0 && strcmp(name, "/") == 0 && !hasopt(optbuf, "union")) | | 397 | if (getargs == 0 && strcmp(name, "/") == 0 && !hasopt(optbuf, "union")) |
400 | flags |= MNT_UPDATE; | | 398 | flags |= MNT_UPDATE; |
401 | else if (skipmounted) { | | 399 | else if (skipmounted) { |
402 | if ((numfs = getmntinfo(&sfp, MNT_WAIT)) == 0) { | | 400 | if ((numfs = getmntinfo(&sfp, MNT_WAIT)) == 0) { |
403 | warn("getmntinfo"); | | 401 | warn("getmntinfo"); |
404 | return (1); | | 402 | return (1); |
405 | } | | 403 | } |
406 | for(i = 0; i < numfs; i++) { | | 404 | for(i = 0; i < numfs; i++) { |
407 | const char *mountedtype = sfp[i].f_fstypename; | | 405 | const char *mountedtype = sfp[i].f_fstypename; |
408 | size_t cmplen = sizeof(sfp[i].f_fstypename); | | 406 | size_t cmplen = sizeof(sfp[i].f_fstypename); |
409 | | | 407 | |
410 | /* remove "puffs|" from comparisons, if present */ | | 408 | /* remove "puffs|" from comparisons, if present */ |
411 | #define TYPESIZE (sizeof(PUFFS_TYPEPREFIX)-1) | | 409 | #define TYPESIZE (sizeof(PUFFS_TYPEPREFIX)-1) |
412 | if (strncmp(mountedtype, | | 410 | if (strncmp(mountedtype, |
413 | PUFFS_TYPEPREFIX, TYPESIZE) == 0) { | | 411 | PUFFS_TYPEPREFIX, TYPESIZE) == 0) { |
414 | mountedtype += TYPESIZE; | | 412 | mountedtype += TYPESIZE; |
415 | cmplen -= TYPESIZE; | | 413 | cmplen -= TYPESIZE; |
416 | } | | 414 | } |
417 | | | 415 | |
418 | /* | | 416 | /* |
419 | * XXX can't check f_mntfromname, | | 417 | * XXX can't check f_mntfromname, |
420 | * thanks to mfs, union, etc. | | 418 | * thanks to mfs, union, etc. |
421 | */ | | 419 | */ |
422 | if (strncmp(name, sfp[i].f_mntonname, MNAMELEN) == 0 && | | 420 | if (strncmp(name, sfp[i].f_mntonname, MNAMELEN) == 0 && |
423 | strncmp(vfstype, mountedtype, cmplen) == 0) { | | 421 | strncmp(vfstype, mountedtype, cmplen) == 0) { |
424 | if (verbose) | | 422 | if (verbose) |
425 | (void)printf("%s on %s type %.*s: " | | 423 | (void)printf("%s on %s type %.*s: " |
426 | "%s\n", | | 424 | "%s\n", |
427 | sfp[i].f_mntfromname, | | 425 | sfp[i].f_mntfromname, |
428 | sfp[i].f_mntonname, | | 426 | sfp[i].f_mntonname, |
429 | (int)sizeof(sfp[i].f_fstypename), | | 427 | (int)sizeof(sfp[i].f_fstypename), |
430 | sfp[i].f_fstypename, | | 428 | sfp[i].f_fstypename, |
431 | "already mounted"); | | 429 | "already mounted"); |
432 | return (0); | | 430 | return (0); |
433 | } | | 431 | } |
434 | } | | 432 | } |
435 | } | | 433 | } |
436 | if (flags & MNT_FORCE) | | 434 | if (flags & MNT_FORCE) |
437 | catopt(&optbuf, "force"); | | 435 | catopt(&optbuf, "force"); |
438 | if (flags & MNT_RDONLY) | | 436 | if (flags & MNT_RDONLY) |
439 | catopt(&optbuf, "ro"); | | 437 | catopt(&optbuf, "ro"); |
440 | | | 438 | |
441 | if (flags & MNT_UPDATE) { | | 439 | if (flags & MNT_UPDATE) { |
442 | catopt(&optbuf, "update"); | | 440 | catopt(&optbuf, "update"); |
443 | /* Figure out the fstype only if we defaulted to ffs */ | | 441 | /* Figure out the fstype only if we defaulted to ffs */ |
444 | if (vfstype == ffs_fstype && statvfs(name, &sf) != -1) | | 442 | if (vfstype == ffs_fstype && statvfs(name, &sf) != -1) |
445 | vfstype = sf.f_fstypename; | | 443 | vfstype = sf.f_fstypename; |
446 | } | | 444 | } |
447 | | | 445 | |
448 | maxargc = 64; | | 446 | maxargc = 64; |
449 | argv = ecalloc(maxargc, sizeof(*argv)); | | 447 | argv = ecalloc(maxargc, sizeof(*argv)); |
450 | | | 448 | |
451 | if (getargs && | | 449 | if (getargs && |
452 | strncmp(vfstype, PUFFS_TYPEPREFIX, sizeof(PUFFS_TYPEPREFIX)-1) == 0) | | 450 | strncmp(vfstype, PUFFS_TYPEPREFIX, sizeof(PUFFS_TYPEPREFIX)-1) == 0) |
453 | (void)snprintf(execbase, sizeof(execbase), "mount_puffs"); | | 451 | (void)snprintf(execbase, sizeof(execbase), "mount_puffs"); |
454 | else if (hasopt(optbuf, "rump")) | | 452 | else if (hasopt(optbuf, "rump")) |
455 | (void)snprintf(execbase, sizeof(execbase), "rump_%s", vfstype); | | 453 | (void)snprintf(execbase, sizeof(execbase), "rump_%s", vfstype); |
456 | else | | 454 | else |
457 | (void)snprintf(execbase, sizeof(execbase), "mount_%s", vfstype); | | 455 | (void)snprintf(execbase, sizeof(execbase), "mount_%s", vfstype); |
458 | argc = 0; | | 456 | argc = 0; |
459 | argv[argc++] = execbase; | | 457 | argv[argc++] = execbase; |
460 | if (optbuf) | | 458 | if (optbuf) |
461 | mangle(optbuf, &argc, &argv, &maxargc); | | 459 | mangle(optbuf, &argc, &argv, &maxargc); |
462 | argv[argc++] = spec; | | 460 | argv[argc++] = spec; |
463 | argv[argc++] = name; | | 461 | argv[argc++] = name; |
464 | argv[argc] = NULL; | | 462 | argv[argc] = NULL; |
465 | | | 463 | |
466 | if ((verbose && buf == NULL) || debug) { | | 464 | if ((verbose && buf == NULL) || debug) { |
467 | (void)printf("exec:"); | | 465 | (void)printf("exec:"); |
468 | for (i = 0; i < argc; i++) | | 466 | for (i = 0; i < argc; i++) |
469 | (void)printf(" %s", argv[i]); | | 467 | (void)printf(" %s", argv[i]); |
470 | (void)printf("\n"); | | 468 | (void)printf("\n"); |
471 | } | | 469 | } |
472 | | | 470 | |
473 | if (buf) { | | 471 | if (buf) { |
474 | if (pipe(pfd) == -1) | | 472 | if (pipe(pfd) == -1) |
475 | warn("Cannot create pipe"); | | 473 | warn("Cannot create pipe"); |
476 | } | | 474 | } |
477 | | | 475 | |
478 | switch (pid = vfork()) { | | 476 | switch (pid = vfork()) { |
479 | case -1: /* Error. */ | | 477 | case -1: /* Error. */ |
480 | warn("vfork"); | | 478 | warn("vfork"); |
481 | if (optbuf) | | 479 | if (optbuf) |
482 | free(optbuf); | | 480 | free(optbuf); |
483 | free(argv); | | 481 | free(argv); |
484 | return (1); | | 482 | return (1); |
485 | | | 483 | |
486 | case 0: /* Child. */ | | 484 | case 0: /* Child. */ |
487 | if (debug) | | 485 | if (debug) |
488 | _exit(0); | | 486 | _exit(0); |
489 | | | 487 | |
490 | if (buf) { | | 488 | if (buf) { |
491 | (void)close(pfd[0]); | | 489 | (void)close(pfd[0]); |
492 | (void)close(STDOUT_FILENO); | | 490 | (void)close(STDOUT_FILENO); |
493 | if (dup2(pfd[1], STDOUT_FILENO) == -1) | | 491 | if (dup2(pfd[1], STDOUT_FILENO) == -1) |
494 | warn("Cannot open fd to mount program"); | | 492 | warn("Cannot open fd to mount program"); |
495 | } | | 493 | } |
496 | | | 494 | |
497 | /* Go find an executable. */ | | 495 | /* Go find an executable. */ |
498 | edir = edirs; | | 496 | edir = edirs; |
499 | do { | | 497 | do { |
500 | (void)snprintf(execname, | | 498 | (void)snprintf(execname, |
501 | sizeof(execname), "%s/%s", *edir, execbase); | | 499 | sizeof(execname), "%s/%s", *edir, execbase); |
502 | (void)execv(execname, __UNCONST(argv)); | | 500 | (void)execv(execname, __UNCONST(argv)); |
503 | if (errno != ENOENT) | | 501 | if (errno != ENOENT) |
504 | warn("exec %s for %s", execname, name); | | 502 | warn("exec %s for %s", execname, name); |
505 | } while (*++edir != NULL); | | 503 | } while (*++edir != NULL); |
506 | | | 504 | |
507 | if (errno == ENOENT) | | 505 | if (errno == ENOENT) |
508 | warnx("%s not found for %s", execbase, name); | | 506 | warnx("%s not found for %s", execbase, name); |
509 | _exit(1); | | 507 | _exit(1); |
510 | /* NOTREACHED */ | | 508 | /* NOTREACHED */ |
511 | | | 509 | |
512 | default: /* Parent. */ | | 510 | default: /* Parent. */ |
513 | if (optbuf) | | 511 | if (optbuf) |
514 | free(optbuf); | | 512 | free(optbuf); |
515 | free(argv); | | 513 | free(argv); |
516 | | | 514 | |
517 | if (buf || getargs) { | | 515 | if (buf || getargs) { |
518 | char tbuf[1024], *ptr; | | 516 | char tbuf[1024], *ptr; |
519 | int nread; | | 517 | int nread; |
520 | | | 518 | |
521 | if (buf == NULL) { | | 519 | if (buf == NULL) { |
522 | ptr = tbuf; | | 520 | ptr = tbuf; |
523 | buflen = sizeof(tbuf) - 1; | | 521 | buflen = sizeof(tbuf) - 1; |
524 | } else { | | 522 | } else { |
525 | ptr = buf; | | 523 | ptr = buf; |
526 | buflen--; | | 524 | buflen--; |
527 | } | | 525 | } |
528 | (void)close(pfd[1]); | | 526 | (void)close(pfd[1]); |
529 | (void)signal(SIGPIPE, SIG_IGN); | | 527 | (void)signal(SIGPIPE, SIG_IGN); |
530 | while ((nread = read(pfd[0], ptr, buflen)) > 0) { | | 528 | while ((nread = read(pfd[0], ptr, buflen)) > 0) { |
531 | buflen -= nread; | | 529 | buflen -= nread; |
532 | ptr += nread; | | 530 | ptr += nread; |
533 | } | | 531 | } |
534 | *ptr = '\0'; | | 532 | *ptr = '\0'; |
535 | if (buflen == 0) { | | 533 | if (buflen == 0) { |
536 | while (read(pfd[0], &nread, sizeof(nread)) > 0) | | 534 | while (read(pfd[0], &nread, sizeof(nread)) > 0) |
537 | continue; | | 535 | continue; |
538 | } | | 536 | } |
539 | if (buf == NULL) | | 537 | if (buf == NULL) |
540 | (void)fprintf(stdout, "%s", tbuf); | | 538 | (void)fprintf(stdout, "%s", tbuf); |
541 | } | | 539 | } |
542 | | | 540 | |
543 | if (waitpid(pid, &status, 0) == -1) { | | 541 | if (waitpid(pid, &status, 0) == -1) { |
544 | warn("waitpid"); | | 542 | warn("waitpid"); |
545 | return (1); | | 543 | return (1); |
546 | } | | 544 | } |
547 | | | 545 | |
548 | if (WIFEXITED(status)) { | | 546 | if (WIFEXITED(status)) { |
549 | if (WEXITSTATUS(status) != 0) | | 547 | if (WEXITSTATUS(status) != 0) |
550 | return (WEXITSTATUS(status)); | | 548 | return (WEXITSTATUS(status)); |
551 | } else if (WIFSIGNALED(status)) { | | 549 | } else if (WIFSIGNALED(status)) { |
552 | warnx("%s: %s", name, strsignal(WTERMSIG(status))); | | 550 | warnx("%s: %s", name, strsignal(WTERMSIG(status))); |
553 | return (1); | | 551 | return (1); |
554 | } | | 552 | } |
555 | | | 553 | |
556 | if (buf == NULL) { | | 554 | if (buf == NULL) { |
557 | if (verbose) { | | 555 | if (verbose) { |
558 | if (statvfs(name, &sf) == -1) { | | 556 | if (statvfs(name, &sf) == -1) { |
559 | warn("statvfs %s", name); | | 557 | warn("statvfs %s", name); |
560 | return (1); | | 558 | return (1); |
561 | } | | 559 | } |
562 | prmount(&sf); | | 560 | prmount(&sf); |
563 | } | | 561 | } |
564 | } | | 562 | } |
565 | break; | | 563 | break; |
566 | } | | 564 | } |
567 | | | 565 | |
568 | return (0); | | 566 | return (0); |
569 | } | | 567 | } |
570 | | | 568 | |
571 | static void | | 569 | static void |
572 | prmount(struct statvfs *sfp) | | 570 | prmount(struct statvfs *sfp) |
573 | { | | 571 | { |
574 | int flags; | | 572 | int flags; |
575 | const struct opt *o; | | 573 | const struct opt *o; |
576 | struct passwd *pw; | | 574 | struct passwd *pw; |
577 | int f; | | 575 | int f; |
578 | | | 576 | |
579 | (void)printf("%s on %s type %.*s", sfp->f_mntfromname, | | 577 | (void)printf("%s on %s type %.*s", sfp->f_mntfromname, |
580 | sfp->f_mntonname, (int)sizeof(sfp->f_fstypename), | | 578 | sfp->f_mntonname, (int)sizeof(sfp->f_fstypename), |
581 | sfp->f_fstypename); | | 579 | sfp->f_fstypename); |
582 | | | 580 | |
583 | flags = sfp->f_flag & MNT_VISFLAGMASK; | | 581 | flags = sfp->f_flag & MNT_VISFLAGMASK; |
584 | for (f = 0, o = optnames; flags && o < | | 582 | for (f = 0, o = optnames; flags && o < |
585 | &optnames[sizeof(optnames)/sizeof(optnames[0])]; o++) | | 583 | &optnames[sizeof(optnames)/sizeof(optnames[0])]; o++) |
586 | if (flags & o->o_opt) { | | 584 | if (flags & o->o_opt) { |
587 | if (!o->o_silent || verbose) | | 585 | if (!o->o_silent || verbose) |
588 | (void)printf("%s%s", !f++ ? " (" : ", ", | | 586 | (void)printf("%s%s", !f++ ? " (" : ", ", |
589 | o->o_name); | | 587 | o->o_name); |
590 | flags &= ~o->o_opt; | | 588 | flags &= ~o->o_opt; |
591 | } | | 589 | } |
592 | if (flags) | | 590 | if (flags) |
593 | (void)printf("%sunknown flag%s %#x", !f++ ? " (" : ", ", | | 591 | (void)printf("%sunknown flag%s %#x", !f++ ? " (" : ", ", |
594 | flags & (flags - 1) ? "s" : "", flags); | | 592 | flags & (flags - 1) ? "s" : "", flags); |
595 | if (sfp->f_owner) { | | 593 | if (sfp->f_owner) { |
596 | (void)printf("%smounted by ", !f++ ? " (" : ", "); | | 594 | (void)printf("%smounted by ", !f++ ? " (" : ", "); |
597 | if ((pw = getpwuid(sfp->f_owner)) != NULL) | | 595 | if ((pw = getpwuid(sfp->f_owner)) != NULL) |
598 | (void)printf("%s", pw->pw_name); | | 596 | (void)printf("%s", pw->pw_name); |
599 | else | | 597 | else |
600 | (void)printf("%d", sfp->f_owner); | | 598 | (void)printf("%d", sfp->f_owner); |
601 | } | | 599 | } |
602 | if (verbose) | | 600 | if (verbose) |
603 | (void)printf("%sfsid: 0x%x/0x%x", | | 601 | (void)printf("%sfsid: 0x%x/0x%x", |
604 | !f++ ? " (" /* ) */: ", ", | | 602 | !f++ ? " (" /* ) */: ", ", |
605 | sfp->f_fsidx.__fsid_val[0], sfp->f_fsidx.__fsid_val[1]); | | 603 | sfp->f_fsidx.__fsid_val[0], sfp->f_fsidx.__fsid_val[1]); |
606 | | | 604 | |
607 | if (verbose) { | | 605 | if (verbose) { |
608 | (void)printf("%s", !f++ ? " (" : ", "); | | 606 | (void)printf("%s", !f++ ? " (" : ", "); |
609 | (void)printf("reads: sync %" PRIu64 " async %" PRIu64 "", | | 607 | (void)printf("reads: sync %" PRIu64 " async %" PRIu64 "", |
610 | sfp->f_syncreads, sfp->f_asyncreads); | | 608 | sfp->f_syncreads, sfp->f_asyncreads); |
611 | (void)printf(", writes: sync %" PRIu64 " async %" PRIu64 "", | | 609 | (void)printf(", writes: sync %" PRIu64 " async %" PRIu64 "", |
612 | sfp->f_syncwrites, sfp->f_asyncwrites); | | 610 | sfp->f_syncwrites, sfp->f_asyncwrites); |
613 | if (verbose > 1) { | | 611 | if (verbose > 1) { |
614 | char buf[2048]; | | 612 | char buf[2048]; |
615 | | | 613 | |
616 | if (getmntargs(sfp, buf, sizeof(buf))) | | 614 | if (getmntargs(sfp, buf, sizeof(buf))) |
617 | printf(", [%s: %s]", sfp->f_fstypename, buf); | | 615 | printf(", [%s: %s]", sfp->f_fstypename, buf); |
618 | } | | 616 | } |
619 | printf(")\n"); | | 617 | printf(")\n"); |
620 | } else | | 618 | } else |
621 | (void)printf("%s", f ? ")\n" : "\n"); | | 619 | (void)printf("%s", f ? ")\n" : "\n"); |
622 | } | | 620 | } |
623 | | | 621 | |
624 | static int | | 622 | static int |
625 | getmntargs(struct statvfs *sfs, char *buf, size_t buflen) | | 623 | getmntargs(struct statvfs *sfs, char *buf, size_t buflen) |
626 | { | | 624 | { |
627 | | | 625 | |
628 | if (mountfs(sfs->f_fstypename, sfs->f_mntfromname, sfs->f_mntonname, 0, | | 626 | if (mountfs(sfs->f_fstypename, sfs->f_mntfromname, sfs->f_mntonname, 0, |
629 | "getargs", NULL, 0, buf, buflen)) | | 627 | "getargs", NULL, 0, buf, buflen)) |
630 | return (0); | | 628 | return (0); |
631 | else { | | 629 | else { |
632 | if (*buf == '\0') | | 630 | if (*buf == '\0') |
633 | return (0); | | 631 | return (0); |
634 | if ((buf = strchr(buf, '\n')) != NULL) | | 632 | if ((buf = strchr(buf, '\n')) != NULL) |
635 | *buf = '\0'; | | 633 | *buf = '\0'; |
636 | return (1); | | 634 | return (1); |
637 | } | | 635 | } |
638 | } | | 636 | } |
639 | | | 637 | |
640 | static struct statvfs * | | 638 | static struct statvfs * |
641 | getmntpt(const char *name) | | 639 | getmntpt(const char *name) |
642 | { | | 640 | { |
643 | struct statvfs *mntbuf; | | 641 | struct statvfs *mntbuf; |
644 | int i, mntsize; | | 642 | int i, mntsize; |
645 | | | 643 | |
646 | mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); | | 644 | mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); |
647 | for (i = 0; i < mntsize; i++) | | 645 | for (i = 0; i < mntsize; i++) |
648 | if (strcmp(mntbuf[i].f_mntfromname, name) == 0 || | | 646 | if (strcmp(mntbuf[i].f_mntfromname, name) == 0 || |
649 | strcmp(mntbuf[i].f_mntonname, name) == 0) | | 647 | strcmp(mntbuf[i].f_mntonname, name) == 0) |
650 | return (&mntbuf[i]); | | 648 | return (&mntbuf[i]); |
651 | return (NULL); | | 649 | return (NULL); |
652 | } | | 650 | } |
653 | | | 651 | |
654 | static void | | 652 | static void |
655 | catopt(char **sp, const char *o) | | 653 | catopt(char **sp, const char *o) |
656 | { | | 654 | { |
657 | char *s, *n; | | 655 | char *s, *n; |
658 | | | 656 | |
659 | s = *sp; | | 657 | s = *sp; |
660 | if (s) { | | 658 | if (s) { |
661 | easprintf(&n, "%s,%s", s, o); | | 659 | easprintf(&n, "%s,%s", s, o); |
662 | free(s); | | 660 | free(s); |
663 | s = n; | | 661 | s = n; |
664 | } else | | 662 | } else |
665 | s = estrdup(o); | | 663 | s = estrdup(o); |
666 | *sp = s; | | 664 | *sp = s; |
667 | } | | 665 | } |
668 | | | 666 | |
669 | static void | | 667 | static void |
670 | mangle(char *options, int *argcp, const char ** volatile *argvp, int *maxargcp) | | 668 | mangle(char *options, int *argcp, const char ** volatile *argvp, int *maxargcp) |
671 | { | | 669 | { |
672 | char *p, *s; | | 670 | char *p, *s; |
673 | int argc, maxargc; | | 671 | int argc, maxargc; |
674 | const char **argv, **nargv; | | 672 | const char **argv, **nargv; |
675 | | | 673 | |
676 | argc = *argcp; | | 674 | argc = *argcp; |
677 | argv = *argvp; | | 675 | argv = *argvp; |
678 | maxargc = *maxargcp; | | 676 | maxargc = *maxargcp; |
679 | | | 677 | |
680 | for (s = options; (p = strsep(&s, ",")) != NULL;) { | | 678 | for (s = options; (p = strsep(&s, ",")) != NULL;) { |
681 | /* Always leave space for one more argument and the NULL. */ | | 679 | /* Always leave space for one more argument and the NULL. */ |
682 | if (argc >= maxargc - 4) { | | 680 | if (argc >= maxargc - 4) { |
683 | nargv = erealloc(argv, (maxargc << 1) * sizeof(nargv)); | | 681 | nargv = erealloc(argv, (maxargc << 1) * sizeof(nargv)); |
684 | argv = nargv; | | 682 | argv = nargv; |
685 | maxargc <<= 1; | | 683 | maxargc <<= 1; |
686 | } | | 684 | } |
687 | if (*p != '\0') { | | 685 | if (*p != '\0') { |
688 | if (*p == '-') { | | 686 | if (*p == '-') { |
689 | argv[argc++] = p; | | 687 | argv[argc++] = p; |
690 | p = strchr(p, '='); | | 688 | p = strchr(p, '='); |
691 | if (p) { | | 689 | if (p) { |
692 | *p = '\0'; | | 690 | *p = '\0'; |
693 | argv[argc++] = p+1; | | 691 | argv[argc++] = p+1; |
694 | } | | 692 | } |
695 | } else if (strcmp(p, "rw") != 0) { | | 693 | } else if (strcmp(p, "rw") != 0) { |
696 | argv[argc++] = "-o"; | | 694 | argv[argc++] = "-o"; |
697 | argv[argc++] = p; | | 695 | argv[argc++] = p; |
698 | } | | 696 | } |
699 | } | | 697 | } |
700 | } | | 698 | } |
701 | | | 699 | |
702 | *argcp = argc; | | 700 | *argcp = argc; |
703 | *argvp = argv; | | 701 | *argvp = argv; |
704 | *maxargcp = maxargc; | | 702 | *maxargcp = maxargc; |
705 | } | | 703 | } |
706 | | | 704 | |
707 | /* Deduce the filesystem type from the disk label. */ | | 705 | /* Deduce the filesystem type from the disk label. */ |
708 | static const char * | | 706 | static const char * |
709 | getfslab(const char *str) | | 707 | getfslab(const char *str) |
710 | { | | 708 | { |
711 | static struct dkwedge_info dkw; | | 709 | static struct dkwedge_info dkw; |
712 | struct disklabel dl; | | 710 | struct disklabel dl; |
713 | int fd; | | 711 | int fd; |
714 | int part; | | 712 | int part; |
715 | const char *vfstype; | | 713 | const char *vfstype; |
716 | u_char fstype; | | 714 | u_char fstype; |
717 | char buf[MAXPATHLEN + 1]; | | 715 | char buf[MAXPATHLEN + 1]; |
718 | char *sp, *ep; | | 716 | char *sp, *ep; |
719 | | | 717 | |
720 | if ((fd = open(str, O_RDONLY)) == -1) { | | 718 | if ((fd = open(str, O_RDONLY)) == -1) { |
721 | /* | | 719 | /* |
722 | * Iff we get EBUSY try the raw device. Since mount always uses | | 720 | * Iff we get EBUSY try the raw device. Since mount always uses |
723 | * the block device we know we are never passed a raw device. | | 721 | * the block device we know we are never passed a raw device. |
724 | */ | | 722 | */ |
725 | if (errno != EBUSY) | | 723 | if (errno != EBUSY) |
726 | err(EXIT_FAILURE, "cannot open `%s'", str); | | 724 | err(EXIT_FAILURE, "cannot open `%s'", str); |
727 | strlcpy(buf, str, MAXPATHLEN); | | 725 | strlcpy(buf, str, MAXPATHLEN); |
728 | if ((sp = strrchr(buf, '/')) != NULL) | | 726 | if ((sp = strrchr(buf, '/')) != NULL) |
729 | ++sp; | | 727 | ++sp; |
730 | else | | 728 | else |
731 | sp = buf; | | 729 | sp = buf; |
732 | for (ep = sp + strlen(sp) + 1; ep > sp; ep--) | | 730 | for (ep = sp + strlen(sp) + 1; ep > sp; ep--) |
733 | *ep = *(ep - 1); | | 731 | *ep = *(ep - 1); |
734 | *sp = 'r'; | | 732 | *sp = 'r'; |
735 | | | 733 | |
736 | /* Silently fail here - mount call can display error */ | | 734 | /* Silently fail here - mount call can display error */ |
737 | if ((fd = open(buf, O_RDONLY)) == -1) | | 735 | if ((fd = open(buf, O_RDONLY)) == -1) |
738 | return (NULL); | | 736 | return (NULL); |
739 | } | | 737 | } |
740 | | | 738 | |
741 | /* Check to see if this is a wedge. */ | | 739 | /* Check to see if this is a wedge. */ |
742 | if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == 0) { | | 740 | if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == 0) { |
743 | /* Yup, this is easy. */ | | 741 | /* Yup, this is easy. */ |
744 | (void) close(fd); | | 742 | (void) close(fd); |
745 | return (dkw.dkw_ptype); | | 743 | return (dkw.dkw_ptype); |
746 | } | | 744 | } |
747 | | | 745 | |
748 | if (ioctl(fd, DIOCGDINFO, &dl) == -1) { | | 746 | if (ioctl(fd, DIOCGDINFO, &dl) == -1) { |
749 | (void) close(fd); | | 747 | (void) close(fd); |
750 | return (NULL); | | 748 | return (NULL); |
751 | } | | 749 | } |
752 | | | 750 | |
753 | (void) close(fd); | | 751 | (void) close(fd); |
754 | | | 752 | |
755 | part = str[strlen(str) - 1] - 'a'; | | 753 | part = str[strlen(str) - 1] - 'a'; |
756 | | | 754 | |
757 | if (part < 0 || part >= dl.d_npartitions) | | 755 | if (part < 0 || part >= dl.d_npartitions) |
758 | return (NULL); | | 756 | return (NULL); |
759 | | | 757 | |
760 | /* Return NULL for unknown types - caller can fall back to ffs */ | | 758 | /* Return NULL for unknown types - caller can fall back to ffs */ |
761 | if ((fstype = dl.d_partitions[part].p_fstype) >= FSMAXMOUNTNAMES) | | 759 | if ((fstype = dl.d_partitions[part].p_fstype) >= FSMAXMOUNTNAMES) |
762 | vfstype = NULL; | | 760 | vfstype = NULL; |
763 | else | | 761 | else |
764 | vfstype = mountnames[fstype]; | | 762 | vfstype = mountnames[fstype]; |
765 | | | 763 | |
766 | return (vfstype); | | 764 | return (vfstype); |
767 | } | | 765 | } |
768 | | | 766 | |
769 | static void | | 767 | static void |
770 | usage(void) | | 768 | usage(void) |
771 | { | | 769 | { |
772 | | | 770 | |
773 | (void)fprintf(stderr, "Usage: %s [-Aadfruvw] [-t type]\n" | | 771 | (void)fprintf(stderr, "Usage: %s [-Aadfruvw] [-t type]\n" |
774 | "\t%s [-dfruvw] special | node\n" | | 772 | "\t%s [-dfruvw] special | node\n" |
775 | "\t%s [-dfruvw] [-o options] [-t type] special node\n", | | 773 | "\t%s [-dfruvw] [-o options] [-t type] special node\n", |
776 | getprogname(), getprogname(), getprogname()); | | 774 | getprogname(), getprogname(), getprogname()); |
777 | exit(1); | | 775 | exit(1); |
778 | } | | 776 | } |