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