xref: /freebsd/usr.sbin/extattrctl/extattrctl.c (revision 77a0943ded95b9e6438f7db70c4a28e4d93946d4)
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 [-f] [-p path] [attrsize] [attrfile]\n"
58 	    "  extattrctl enable [path] [attrname] [attrfile]\n"
59 	    "  extattrctl disable [path] [attrname]\n");
60 	exit(-1);
61 }
62 
63 long
64 num_inodes_by_path(char *path)
65 {
66 	struct statfs	buf;
67 	int	error;
68 
69 	error = statfs(path, &buf);
70 	if (error) {
71 		perror("statfs");
72 		return (-1);
73 	}
74 
75 	return (buf.f_files);
76 }
77 
78 int
79 initattr(int argc, char *argv[])
80 {
81 	struct ufs_extattr_fileheader	uef;
82 	char	*fs_path = NULL;
83 	char	*zero_buf = NULL;
84 	long	loop, num_inodes;
85 	int	ch, i, error, chunksize, overwrite = 0, flags;
86 
87 	optind = 0;
88 	while ((ch = getopt(argc, argv, "fp:r:w:")) != -1)
89 		switch (ch) {
90 		case 'f':
91 			overwrite = 1;
92 			break;
93 		case 'p':
94 			fs_path = strdup(optarg);
95 			break;
96 		case '?':
97 		default:
98 			usage();
99 		}
100 
101 	argc -= optind;
102 	argv += optind;
103 
104 	if (argc != 2)
105 		usage();
106 
107 	if (overwrite)
108 		flags = O_CREAT | O_WRONLY;
109 	else
110 		flags = O_CREAT | O_EXCL | O_WRONLY;
111 
112 	error = 0;
113 	if ((i = open(argv[1], flags, 0600)) != -1) {
114 		uef.uef_magic = UFS_EXTATTR_MAGIC;
115 		uef.uef_version = UFS_EXTATTR_VERSION;
116 		uef.uef_size = atoi(argv[0]);
117 		if (write(i, &uef, sizeof(uef)) == -1)
118 			error = -1;
119 		else if (fs_path) {
120 			zero_buf = (char *) (malloc(uef.uef_size));
121 			if (zero_buf == NULL) {
122 				perror("malloc");
123 				unlink(argv[1]);
124 				return (-1);
125 			}
126 			memset(zero_buf, 0, uef.uef_size);
127 			num_inodes = num_inodes_by_path(fs_path);
128 			chunksize = sizeof(struct ufs_extattr_header) +
129 			    uef.uef_size;
130 			for (loop = 0; loop < num_inodes; loop++) {
131 				error = write(i, zero_buf, chunksize);
132 				if (error != chunksize) {
133 					perror("write");
134 					unlink(argv[1]);
135 					return (-1);
136 				}
137 			}
138 		}
139 	}
140 	if (i == -1) {
141 		/* unable to open file */
142 		perror(argv[1]);
143 		return (-1);
144 	}
145 	if (error == -1) {
146 		perror(argv[1]);
147 		unlink(argv[1]);
148 		return (-1);
149 	}
150 
151 	return (0);
152 }
153 
154 int
155 main(int argc, char *argv[])
156 {
157 	int	error = 0;
158 
159 	if (argc < 2)
160 		usage();
161 
162 	if (!strcmp(argv[1], "start")) {
163 		if (argc != 3)
164 			usage();
165 		error = extattrctl(argv[2], UFS_EXTATTR_CMD_START, 0, 0);
166 		if (error)
167 			perror("extattrctl start");
168 	} else if (!strcmp(argv[1], "stop")) {
169 		if (argc != 3)
170 			usage();
171 		error = extattrctl(argv[2], UFS_EXTATTR_CMD_STOP, 0, 0);
172 		if (error)
173 			perror("extattrctl stop");
174 	} else if (!strcmp(argv[1], "enable")) {
175 		if (argc != 5)
176 			usage();
177 		error = extattrctl(argv[2], UFS_EXTATTR_CMD_ENABLE, argv[3],
178 		    argv[4]);
179 		if (error)
180 			perror("extattrctl enable");
181 	} else if (!strcmp(argv[1], "disable")) {
182 		if (argc != 4)
183 			usage();
184 		error = extattrctl(argv[2], UFS_EXTATTR_CMD_DISABLE, argv[3],
185 		    NULL);
186 		if (error)
187 			perror("extattrctl disable");
188 	} else if (!strcmp(argv[1], "initattr")) {
189 		argc -= 2;
190 		argv += 2;
191 		error = initattr(argc, argv);
192 	} else
193 		usage();
194 	return(error);
195 }
196