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