xref: /freebsd/usr.sbin/extattrctl/extattrctl.c (revision 1b6c76a2fe091c74f08427e6c870851025a9cf67)
1 /*-
2  * Copyright (c) 1999, 2000, 2001 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 <errno.h>
41 #include <fcntl.h>
42 #include <libutil.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 
48 extern char	*optarg;
49 extern int	optind;
50 
51 void
52 usage(void)
53 {
54 
55 	fprintf(stderr,
56 	    "usage:\n"
57 	    "  extattrctl start [path]\n"
58 	    "  extattrctl stop [path]\n"
59 	    "  extattrctl initattr [-f] [-p path] [attrsize] [attrfile]\n"
60 	    "  extattrctl enable [path] [attrnamespace] [attrname] [attrfile]\n"
61 	    "  extattrctl disable [path] [attrnamespace] [attrname]\n");
62 	exit(-1);
63 }
64 
65 long
66 num_inodes_by_path(char *path)
67 {
68 	struct statfs	buf;
69 	int	error;
70 
71 	error = statfs(path, &buf);
72 	if (error) {
73 		perror("statfs");
74 		return (-1);
75 	}
76 
77 	return (buf.f_files);
78 }
79 
80 int
81 initattr(int argc, char *argv[])
82 {
83 	struct ufs_extattr_fileheader	uef;
84 	char	*fs_path = NULL;
85 	char	*zero_buf = NULL;
86 	long	loop, num_inodes;
87 	int	ch, i, error, chunksize, overwrite = 0, flags;
88 
89 	optind = 0;
90 	while ((ch = getopt(argc, argv, "fp:r:w:")) != -1)
91 		switch (ch) {
92 		case 'f':
93 			overwrite = 1;
94 			break;
95 		case 'p':
96 			if ((fs_path = strdup(optarg)) == NULL) {
97 				perror("strdup");
98 				return(-1);
99 			}
100 			break;
101 		case '?':
102 		default:
103 			usage();
104 		}
105 
106 	argc -= optind;
107 	argv += optind;
108 
109 	if (argc != 2)
110 		usage();
111 
112 	if (overwrite)
113 		flags = O_CREAT | O_WRONLY;
114 	else
115 		flags = O_CREAT | O_EXCL | O_WRONLY;
116 
117 	error = 0;
118 	if ((i = open(argv[1], flags, 0600)) != -1) {
119 		uef.uef_magic = UFS_EXTATTR_MAGIC;
120 		uef.uef_version = UFS_EXTATTR_VERSION;
121 		uef.uef_size = atoi(argv[0]);
122 		if (write(i, &uef, sizeof(uef)) == -1)
123 			error = -1;
124 		else if (fs_path) {
125 			zero_buf = (char *) (malloc(uef.uef_size));
126 			if (zero_buf == NULL) {
127 				perror("malloc");
128 				unlink(argv[1]);
129 				return (-1);
130 			}
131 			memset(zero_buf, 0, uef.uef_size);
132 			num_inodes = num_inodes_by_path(fs_path);
133 			chunksize = sizeof(struct ufs_extattr_header) +
134 			    uef.uef_size;
135 			for (loop = 0; loop < num_inodes; loop++) {
136 				error = write(i, zero_buf, chunksize);
137 				if (error != chunksize) {
138 					perror("write");
139 					unlink(argv[1]);
140 					return (-1);
141 				}
142 			}
143 		}
144 	}
145 	if (i == -1) {
146 		/* unable to open file */
147 		perror(argv[1]);
148 		return (-1);
149 	}
150 	if (error == -1) {
151 		perror(argv[1]);
152 		unlink(argv[1]);
153 		return (-1);
154 	}
155 
156 	return (0);
157 }
158 
159 int
160 main(int argc, char *argv[])
161 {
162 	int	error = 0, attrnamespace;
163 
164 	if (argc < 2)
165 		usage();
166 
167 	if (!strcmp(argv[1], "start")) {
168 		if (argc != 3)
169 			usage();
170 		error = extattrctl(argv[2], UFS_EXTATTR_CMD_START, NULL, 0,
171 		    NULL);
172 		if (error) {
173 			perror("extattrctl start");
174 			return (-1);
175 		}
176 		return (0);
177 	} else if (!strcmp(argv[1], "stop")) {
178 		if (argc != 3)
179 			usage();
180 		error = extattrctl(argv[2], UFS_EXTATTR_CMD_STOP, NULL, 0,
181 		   NULL);
182 		if (error) {
183 			perror("extattrctl stop");
184 			return (-1);
185 		}
186 		return (0);
187 	} else if (!strcmp(argv[1], "enable")) {
188 		if (argc != 6)
189 			usage();
190 		error = extattr_string_to_namespace(argv[3], &attrnamespace);
191 		if (error) {
192 			perror("extattrctl enable");
193 			return (-1);
194 		}
195 		error = extattrctl(argv[2], UFS_EXTATTR_CMD_ENABLE, argv[5],
196 		    attrnamespace, argv[4]);
197 		if (error) {
198 			perror("extattrctl enable");
199 			return (-1);
200 		}
201 		return (0);
202 	} else if (!strcmp(argv[1], "disable")) {
203 		if (argc != 5)
204 			usage();
205 		error = extattr_string_to_namespace(argv[3], &attrnamespace);
206 		if (error) {
207 			perror("extattrctl disable");
208 			return (-1);
209 		}
210 		error = extattrctl(argv[2], UFS_EXTATTR_CMD_DISABLE, NULL,
211 		    attrnamespace, argv[4]);
212 		if (error) {
213 			perror("extattrctl disable");
214 			return (-1);
215 		}
216 		return (0);
217 	} else if (!strcmp(argv[1], "initattr")) {
218 		argc -= 2;
219 		argv += 2;
220 		error = initattr(argc, argv);
221 		if (error)
222 			return (-1);
223 		return (0);
224 	} else
225 		usage();
226 }
227