22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ |
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ |
23 /* All Rights Reserved */ |
23 /* All Rights Reserved */ |
24 |
24 |
25 |
25 |
26 /* |
26 /* |
27 * Copyright 1996-2003 Sun Microsystems, Inc. All rights reserved. |
27 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. |
28 * Use is subject to license terms. |
28 * Use is subject to license terms. |
29 */ |
29 */ |
30 |
30 |
31 #pragma ident "%Z%%M% %I% %E% SMI" |
31 #pragma ident "%Z%%M% %I% %E% SMI" |
32 |
32 |
39 #include <sys/vfstab.h> |
39 #include <sys/vfstab.h> |
40 #include <sys/types.h> |
40 #include <sys/types.h> |
41 #include <sys/stat.h> |
41 #include <sys/stat.h> |
42 #include <fcntl.h> |
42 #include <fcntl.h> |
43 #include <string.h> |
43 #include <string.h> |
|
44 #include <libdiskmgt.h> |
|
45 #include "fslib.h" |
|
46 |
|
47 |
|
48 static int match(char **opts, char *s); |
44 |
49 |
45 #define FSTYPE_MAX 8 |
50 #define FSTYPE_MAX 8 |
46 #define ARGV_MAX 1024 |
51 #define ARGV_MAX 1024 |
47 #define VFS_PATH "/usr/lib/fs" |
52 #define VFS_PATH "/usr/lib/fs" |
48 #define ALT_PATH "/etc/fs" |
53 #define ALT_PATH "/etc/fs" |
115 register char *ptr; |
120 register char *ptr; |
116 char full_path[PATH_MAX]; |
121 char full_path[PATH_MAX]; |
117 char *vfs_path = VFS_PATH; |
122 char *vfs_path = VFS_PATH; |
118 char *alt_path = ALT_PATH; |
123 char *alt_path = ALT_PATH; |
119 int i; |
124 int i; |
|
125 int j; |
120 int verbose = 0; /* set if -V is specified */ |
126 int verbose = 0; /* set if -V is specified */ |
121 int F_flg = 0; |
127 int F_flg = 0; |
122 int mflag = 0; |
128 int mflag = 0; |
|
129 int Nflag = 0; |
123 char *oopts = NULL; |
130 char *oopts = NULL; |
|
131 char *tmpopts = NULL; /* used for in use checking */ |
124 int iflag = 0; |
132 int iflag = 0; |
125 int usgflag = 0; |
133 int usgflag = 0; |
126 int arg; /* argument from getopt() */ |
134 int arg; /* argument from getopt() */ |
|
135 char *msg; |
|
136 int error; |
127 extern char *optarg; /* getopt specific */ |
137 extern char *optarg; /* getopt specific */ |
128 extern int optind; |
138 extern int optind; |
129 extern int opterr; |
139 extern int opterr; |
130 |
140 |
131 (void) setlocale(LC_ALL, ""); |
141 (void) setlocale(LC_ALL, ""); |
165 break; |
175 break; |
166 case 'o': /* FSType specific arguments */ |
176 case 'o': /* FSType specific arguments */ |
167 newargv[newargc++] = "-o"; |
177 newargv[newargc++] = "-o"; |
168 newargv[newargc++] = optarg; |
178 newargv[newargc++] = optarg; |
169 oopts = optarg; |
179 oopts = optarg; |
|
180 if (!Nflag) { |
|
181 tmpopts = optarg; |
|
182 Nflag = has_Nflag(tmpopts); |
|
183 } |
170 break; |
184 break; |
171 case '?': /* print usage message */ |
185 case '?': /* print usage message */ |
172 newargv[newargc++] = "-?"; |
186 newargv[newargc++] = "-?"; |
173 usgflag = 1; |
187 usgflag = 1; |
174 break; |
188 break; |
190 break; |
204 break; |
191 } |
205 } |
192 optarg = NULL; |
206 optarg = NULL; |
193 } |
207 } |
194 if (F_flg > 1) { |
208 if (F_flg > 1) { |
195 fprintf(stderr, gettext("%s: more than one FSType specified\n"), |
209 (void) fprintf(stderr, |
196 cbasename); |
210 gettext("%s: more than one FSType specified\n"), |
|
211 cbasename); |
197 usage(cbasename, c_ptr->c_usgstr); |
212 usage(cbasename, c_ptr->c_usgstr); |
198 exit(2); |
213 exit(2); |
199 } |
214 } |
200 if (fstype != NULL) { |
215 if (fstype != NULL) { |
201 if (strlen(fstype) > FSTYPE_MAX) { |
216 if (strlen(fstype) > FSTYPE_MAX) { |
202 fprintf(stderr, |
217 (void) fprintf(stderr, |
203 gettext("%s: FSType %s exceeds %d characters\n"), |
218 gettext("%s: FSType %s exceeds %d characters\n"), |
204 cbasename, fstype, FSTYPE_MAX); |
219 cbasename, fstype, FSTYPE_MAX); |
205 exit(2); |
220 exit(2); |
206 } |
221 } |
207 } |
222 } |
222 stat_snap(cbasename, diff == 0 ? argv[argc-1] : NULL, oopts); |
237 stat_snap(cbasename, diff == 0 ? argv[argc-1] : NULL, oopts); |
223 exit(0); |
238 exit(0); |
224 } |
239 } |
225 |
240 |
226 if ((special == NULL) && (!usgflag)) { |
241 if ((special == NULL) && (!usgflag)) { |
227 fprintf(stderr, gettext("%s: special not specified\n"), |
242 (void) fprintf(stderr, gettext("%s: special not specified\n"), |
228 cbasename); |
243 cbasename); |
229 usage(cbasename, c_ptr->c_usgstr); |
244 usage(cbasename, c_ptr->c_usgstr); |
230 exit(2); |
245 exit(2); |
231 } |
246 } |
|
247 |
232 if ((fstype == NULL) && (usgflag)) |
248 if ((fstype == NULL) && (usgflag)) |
233 usage(cbasename, c_ptr->c_usgstr); |
249 usage(cbasename, c_ptr->c_usgstr); |
234 if (fstype == NULL) |
250 if (fstype == NULL) |
235 lookup(); |
251 lookup(); |
236 if (fstype == NULL) { |
252 if (fstype == NULL) { |
237 fprintf(stderr, gettext("%s: FSType cannot be identified\n"), |
253 (void) fprintf(stderr, |
238 cbasename); |
254 gettext("%s: FSType cannot be identified\n"), cbasename); |
239 usage(cbasename, c_ptr->c_usgstr); |
255 usage(cbasename, c_ptr->c_usgstr); |
240 exit(2); |
256 exit(2); |
241 } |
257 } |
242 newargv[newargc++] = special; |
258 newargv[newargc++] = special; |
243 for (; optind < argc; optind++) |
259 for (; optind < argc; optind++) |
252 printf("%s -F %s ", cbasename, fstype); |
268 printf("%s -F %s ", cbasename, fstype); |
253 for (i = 2; newargv[i]; i++) |
269 for (i = 2; newargv[i]; i++) |
254 printf("%s ", newargv[i]); |
270 printf("%s ", newargv[i]); |
255 printf("\n"); |
271 printf("\n"); |
256 exit(0); |
272 exit(0); |
|
273 } |
|
274 |
|
275 /* |
|
276 * Prior to executing the command for mkfs check for device in use. |
|
277 * If the mflag is set, user wants to see command that created |
|
278 * an already existing filesystem. Do not check for in use in this |
|
279 * case. If Nflag is set user wants to see what the parameters |
|
280 * would be to create the filesystem. Do not check for in use in |
|
281 * this case. |
|
282 */ |
|
283 if (strcmp(cbasename, "mkfs") == 0 && !mflag && !Nflag) { |
|
284 if (dm_inuse(special, &msg, DM_WHO_MKFS, &error) || |
|
285 error) { |
|
286 if (error != 0) { |
|
287 (void) fprintf(stderr, gettext("Error occurred" |
|
288 " with device in use checking: %s\n"), |
|
289 strerror(error)); |
|
290 } else { |
|
291 (void) fprintf(stderr, "%s", msg); |
|
292 free(msg); |
|
293 exit(2); |
|
294 } |
|
295 } |
257 } |
296 } |
258 |
297 |
259 /* |
298 /* |
260 * Execute the FSType specific command. |
299 * Execute the FSType specific command. |
261 */ |
300 */ |
277 newargv[1] = full_path; |
316 newargv[1] = full_path; |
278 execv("/sbin/sh", &newargv[0]); |
317 execv("/sbin/sh", &newargv[0]); |
279 } |
318 } |
280 if (errno != ENOENT) { |
319 if (errno != ENOENT) { |
281 perror(cbasename); |
320 perror(cbasename); |
282 fprintf(stderr, gettext("%s: cannot execute %s\n"), cbasename, |
321 (void) fprintf(stderr, gettext("%s: cannot execute %s\n"), |
283 full_path); |
322 cbasename, full_path); |
284 exit(2); |
323 exit(2); |
285 } |
324 } |
286 |
325 |
287 if (sysfs(GETFSIND, fstype) == (-1)) { |
326 if (sysfs(GETFSIND, fstype) == (-1)) { |
288 fprintf(stderr, |
327 (void) fprintf(stderr, |
289 gettext("%s: FSType %s not installed in the kernel\n"), |
328 gettext("%s: FSType %s not installed in the kernel\n"), |
290 cbasename, fstype); |
329 cbasename, fstype); |
291 exit(2); |
330 exit(2); |
292 } |
331 } |
293 fprintf(stderr, |
332 (void) fprintf(stderr, |
294 gettext("%s: Operation not applicable for FSType %s \n"), |
333 gettext("%s: Operation not applicable for FSType %s \n"), |
295 cbasename, fstype); |
334 cbasename, fstype); |
296 exit(2); |
335 exit(2); |
297 } |
336 } |
298 |
337 |
299 usage(cmd, usg) |
338 usage(cmd, usg) |
300 char *cmd; |
339 char *cmd; |
301 char **usg; |
340 char **usg; |
302 { |
341 { |
303 int i; |
342 int i; |
304 fprintf(stderr, gettext("Usage:\n")); |
343 (void) fprintf(stderr, gettext("Usage:\n")); |
305 for (i = 0; usg[i] != NULL; i++) |
344 for (i = 0; usg[i] != NULL; i++) |
306 fprintf(stderr, "%s %s\n", gettext(cmd), gettext(usg[i])); |
345 (void) fprintf(stderr, "%s %s\n", gettext(cmd), |
|
346 gettext(usg[i])); |
307 exit(2); |
347 exit(2); |
308 } |
348 } |
309 |
349 |
310 |
350 |
311 /* |
351 /* |
321 FILE *fd; |
361 FILE *fd; |
322 int ret; |
362 int ret; |
323 struct vfstab vget, vref; |
363 struct vfstab vget, vref; |
324 |
364 |
325 if ((fd = fopen(vfstab, "r")) == NULL) { |
365 if ((fd = fopen(vfstab, "r")) == NULL) { |
326 fprintf(stderr, gettext("%s: cannot open vfstab\n"), cbasename); |
366 (void) fprintf(stderr, gettext("%s: cannot open vfstab\n"), |
|
367 cbasename); |
327 exit(1); |
368 exit(1); |
328 } |
369 } |
329 vfsnull(&vref); |
370 vfsnull(&vref); |
330 vref.vfs_special = special; |
371 vref.vfs_special = special; |
331 ret = getvfsany(fd, &vget, &vref); |
372 ret = getvfsany(fd, &vget, &vref); |
343 break; |
384 break; |
344 case 0: |
385 case 0: |
345 fstype = vget.vfs_fstype; |
386 fstype = vget.vfs_fstype; |
346 break; |
387 break; |
347 case VFS_TOOLONG: |
388 case VFS_TOOLONG: |
348 fprintf(stderr, |
389 (void) fprintf(stderr, |
349 gettext("%s: line in vfstab exceeds %d characters\n"), |
390 gettext("%s: line in vfstab exceeds %d characters\n"), |
350 cbasename, VFS_LINE_MAX-2); |
391 cbasename, VFS_LINE_MAX-2); |
351 exit(1); |
392 exit(1); |
352 break; |
393 break; |
353 case VFS_TOOFEW: |
394 case VFS_TOOFEW: |
354 fprintf(stderr, |
395 (void) fprintf(stderr, |
355 gettext("%s: line in vfstab has too few entries\n"), |
396 gettext("%s: line in vfstab has too few entries\n"), |
356 cbasename); |
397 cbasename); |
357 exit(1); |
398 exit(1); |
358 break; |
399 break; |
359 } |
400 } |
374 en = errno; |
415 en = errno; |
375 errstr = strerror(errno); |
416 errstr = strerror(errno); |
376 if (errstr == NULL) |
417 if (errstr == NULL) |
377 errstr = gettext("Unknown error"); |
418 errstr = gettext("Unknown error"); |
378 |
419 |
379 fprintf(stderr, gettext("%s: %s: error %d: %s\n"), |
420 (void) fprintf(stderr, |
380 cmd, mountpoint, en, errstr); |
421 gettext("%s: %s: error %d: %s\n"), |
|
422 cmd, mountpoint, en, errstr); |
381 |
423 |
382 exit(2); |
424 exit(2); |
383 } |
425 } |
384 close(fd); |
426 close(fd); |
385 } |
427 } |
386 fssnap_show_status(mountpoint, opts, 1, (opts ? 0 : 1)); |
428 fssnap_show_status(mountpoint, opts, 1, (opts ? 0 : 1)); |
387 } |
429 } |
|
430 static int |
|
431 has_Nflag(char *opts) |
|
432 { |
|
433 while (opts != NULL && *opts != '\0') { |
|
434 if (match(&opts, "N")) { |
|
435 return (1); |
|
436 } |
|
437 if (!opts) |
|
438 break; |
|
439 if (*opts == ',') |
|
440 opts ++; |
|
441 if (*opts == ' ') |
|
442 opts ++; |
|
443 } |
|
444 return (0); |
|
445 } |
|
446 /* |
|
447 * Parses the -o [fs specific options string] to search for the UFS -N flag. |
|
448 * Return the opts string pointing to the next position in the string if |
|
449 * match is not found. A delimiter of , or ' ' can be used depending on the |
|
450 * caller, newfs or mkfs. |
|
451 */ |
|
452 static int |
|
453 match(char **opts, char *s) |
|
454 { |
|
455 char *cs; |
|
456 char *tmp_str; |
|
457 |
|
458 cs = *opts; |
|
459 |
|
460 while (*cs++ == *s) { |
|
461 if (*s++ == '\0') { |
|
462 goto true; |
|
463 } |
|
464 } |
|
465 if (*s != '\0') { |
|
466 /* |
|
467 * If we cannot find the delimiter it means we |
|
468 * have hit the end of the string. |
|
469 */ |
|
470 tmp_str = strchr(*opts, ','); |
|
471 if (!tmp_str) |
|
472 tmp_str = strchr(*opts, ' '); |
|
473 |
|
474 *opts = tmp_str; |
|
475 return (0); |
|
476 } |
|
477 true: |
|
478 cs--; |
|
479 *opts = cs; |
|
480 return (1); |
|
481 } |