xref: /freebsd/usr.sbin/extattrctl/extattrctl.c (revision 23f282aa31e9b6fceacd449020e936e98d6f2298)
1 /*-
2  * Copyright (c) 1999, 2000 Robert N. M. Watson
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  *	$FreeBSD$
27  */
28 /*
29  * TrustedBSD Project - extended attribute support for UFS-like file systems
30  */
31 
32 #include <sys/types.h>
33 #include <sys/uio.h>
34 #include <sys/extattr.h>
35 #include <sys/param.h>
36 #include <sys/mount.h>
37 
38 #include <ufs/ufs/extattr.h>
39 
40 #include <fcntl.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45 
46 extern char	*optarg;
47 extern int	optind;
48 
49 void
50 usage(void)
51 {
52 
53 	fprintf(stderr,
54 	    "usage:\n"
55 	    "  extattrctl start [path]\n"
56 	    "  extattrctl stop [path]\n"
57 	    "  extattrctl initattr [-p path] [-r [kroa]] [-w [kroa]] "
58 	    "[attrsize] [attrfile]\n"
59 	    "  extattrctl enable [path] [attrname] [attrfile]\n"
60 	    "  extattrctl disable [path] [attrname]\n");
61 	exit(-1);
62 }
63 
64 /*
65  * Return a level, or -1
66  */
67 int
68 extattr_level_from_string(char *string)
69 {
70 
71 	if (strlen(string) != 1)
72 		return (-1);
73 
74 	switch(string[0]) {
75 	case 'k':
76 	case 'K':
77 		return (UFS_EXTATTR_PERM_KERNEL);
78 	case 'r':
79 	case 'R':
80 		return (UFS_EXTATTR_PERM_ROOT);
81 	case 'o':
82 	case 'O':
83 		return (UFS_EXTATTR_PERM_OWNER);
84 	case 'a':
85 	case 'A':
86 		return (UFS_EXTATTR_PERM_ANYONE);
87 	default:
88 		return (-1);
89 	}
90 }
91 
92 long
93 num_inodes_by_path(char *path)
94 {
95 	struct statfs	buf;
96 	int	error;
97 
98 	error = statfs(path, &buf);
99 	if (error) {
100 		perror("statfs");
101 		return (-1);
102 	}
103 
104 	return (buf.f_files);
105 }
106 
107 int
108 initattr(int argc, char *argv[])
109 {
110 	struct ufs_extattr_fileheader	uef;
111 	char	*fs_path = NULL;
112 	char	*zero_buf = NULL;
113 	long	loop, num_inodes;
114 	int	initattr_rlevel = UFS_EXTATTR_PERM_ROOT;
115 	int	initattr_wlevel = UFS_EXTATTR_PERM_ROOT;
116 	int	ch, i, error;
117 
118 	optind = 0;
119 	while ((ch = getopt(argc, argv, "p:rw")) != -1)
120 		switch (ch) {
121 		case 'p':
122 			fs_path = strdup(optarg);
123 			break;
124 		case 'r':
125 			initattr_rlevel = extattr_level_from_string(optarg);
126 			if (initattr_rlevel == -1)
127 				usage();
128 			break;
129 		case 'w':
130 			initattr_wlevel = extattr_level_from_string(optarg);
131 			if (initattr_wlevel == -1)
132 				usage();
133 			break;
134 		case '?':
135 		default:
136 			usage();
137 		}
138 
139 	argc -= optind;
140 	argv += optind;
141 
142 	if (argc != 2)
143 		usage();
144 
145 	error = 0;
146 	if ((i = open(argv[1], O_CREAT | O_EXCL | O_WRONLY, 0600)) != -1) {
147 		uef.uef_magic = UFS_EXTATTR_MAGIC;
148 		uef.uef_version = UFS_EXTATTR_VERSION;
149 		uef.uef_write_perm = initattr_wlevel;
150 		uef.uef_read_perm = initattr_rlevel;
151 		uef.uef_size = atoi(argv[0]);
152 		if (write(i, &uef, sizeof(uef)) == -1)
153 			error = -1;
154 		else if (fs_path) {
155 			zero_buf = (char *) (malloc(uef.uef_size));
156 			if (zero_buf == NULL) {
157 				perror("malloc");
158 				unlink(argv[1]);
159 				return (-1);
160 			}
161 			memset(zero_buf, 0, uef.uef_size);
162 			num_inodes = num_inodes_by_path(fs_path);
163 			for (loop = 0; loop < num_inodes; loop++) {
164 				error = write(i, zero_buf, uef.uef_size);
165 				if (error != uef.uef_size) {
166 					perror("write");
167 					unlink(argv[1]);
168 					return (-1);
169 				}
170 			}
171 		}
172 	}
173 	if (i == -1 || error == -1) {
174 		perror(argv[1]);
175 		unlink(argv[1]);
176 		return (-1);
177 	}
178 
179 	return (0);
180 }
181 
182 int
183 main(int argc, char *argv[])
184 {
185 	int	error = 0;
186 
187 	if (argc < 2)
188 		usage();
189 
190 	if (!strcmp(argv[1], "start")) {
191 		if (argc != 3)
192 			usage();
193 		error = extattrctl(argv[2], UFS_EXTATTR_CMD_START, 0, 0);
194 	} else if (!strcmp(argv[1], "stop")) {
195 		if (argc != 3)
196 			usage();
197 		error = extattrctl(argv[2], UFS_EXTATTR_CMD_STOP, 0, 0);
198 	} else if (!strcmp(argv[1], "enable")) {
199 		if (argc != 5)
200 			usage();
201 		error = extattrctl(argv[2], UFS_EXTATTR_CMD_ENABLE, argv[3],
202 		    argv[4]);
203 	} else if (!strcmp(argv[1], "disable")) {
204 		if (argc != 4)
205 			usage();
206 		error = extattrctl(argv[2], UFS_EXTATTR_CMD_DISABLE, argv[3],
207 		    NULL);
208 	} else if (!strcmp(argv[1], "initattr")) {
209 		argc -= 2;
210 		argv += 2;
211 		error = initattr(argc, argv);
212 	} else
213 		usage();
214 
215 	if (error)
216 		perror(argv[1]);
217 
218 	return(error);
219 }
220