1 /* 2 * Copyright (c) 1992, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software donated to Berkeley by 6 * Jan-Simon Pendry. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)mount_union.c 8.3 (Berkeley) 02/22/94 11 */ 12 13 #include <sys/param.h> 14 #include <sys/mount.h> 15 #include <miscfs/union/union.h> 16 17 #include <errno.h> 18 #include <stdio.h> 19 #include <unistd.h> 20 #include <stdlib.h> 21 #include <string.h> 22 23 static int subdir __P((const char *, const char *)); 24 void usage __P((void)); 25 26 int 27 main(argc, argv) 28 int argc; 29 char *argv[]; 30 { 31 struct union_args args; 32 int ch, mntflags; 33 char target[MAXPATHLEN]; 34 int error = 0; 35 36 mntflags = 0; 37 args.mntflags = UNMNT_ABOVE; 38 39 while ((ch = getopt(argc, argv, "F:a:b:r:")) != EOF) { 40 switch(ch) { 41 case 'F': 42 mntflags = atoi(optarg); 43 break; 44 case 'a': 45 if (strcmp(optarg, "bove") == 0) { 46 args.mntflags &= ~UNMNT_OPMASK; 47 args.mntflags |= UNMNT_ABOVE; 48 } else { 49 error = 1; 50 } 51 break; 52 53 case 'b': 54 if (strcmp(optarg, "elow") == 0) { 55 args.mntflags &= ~UNMNT_OPMASK; 56 args.mntflags |= UNMNT_BELOW; 57 } else { 58 error = 1; 59 } 60 break; 61 62 case 'r': 63 if (strcmp(optarg, "eplace") == 0) { 64 args.mntflags &= ~UNMNT_OPMASK; 65 args.mntflags |= UNMNT_REPLACE; 66 } else { 67 error = 1; 68 } 69 break; 70 71 case '?': 72 default: 73 error = 1; 74 break; 75 } 76 } 77 argc -= optind; 78 argv += optind; 79 80 if (argc != 2) 81 error = 1; 82 83 if (error) 84 usage(); 85 86 if (realpath(argv[0], target) == 0) { 87 (void)fprintf(stderr, "mount_union: %s: %s\n", 88 target, strerror(errno)); 89 exit(1); 90 } 91 92 if (subdir(target, argv[1]) || subdir(argv[1], target)) { 93 (void)fprintf(stderr, 94 "mount_union: %s (%s) and %s are not distinct paths\n", 95 argv[0], target, argv[1]); 96 exit(1); 97 } 98 99 args.target = target; 100 101 if (mount(MOUNT_UNION, argv[1], mntflags, &args)) { 102 (void)fprintf(stderr, "mount_union: %s\n", strerror(errno)); 103 exit(1); 104 } 105 exit(0); 106 } 107 108 static int 109 subdir(p, dir) 110 const char *p; 111 const char *dir; 112 { 113 int l; 114 115 l = strlen(dir); 116 if (l <= 1) 117 return (1); 118 119 if ((strncmp(p, dir, l) == 0) && (p[l] == '/' || p[l] == '\0')) 120 return (1); 121 122 return (0); 123 } 124 125 void 126 usage() 127 { 128 (void)fprintf(stderr, 129 "usage: mount_union [ -F fsoptions ] target_fs mount_point\n"); 130 exit(1); 131 } 132