extattrctl.c revision 201387
1/*-
2 * Copyright (c) 1999-2002 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: head/usr.sbin/extattrctl/extattrctl.c 201387 2010-01-02 11:05:34Z ed $
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
51int initattr(int argc, char *argv[]);
52int showattr(int argc, char *argv[]);
53long num_inodes_by_path(char *path);
54void usage(void);
55
56void
57usage(void)
58{
59
60	fprintf(stderr,
61	    "usage:\n"
62	    "  extattrctl start path\n"
63	    "  extattrctl stop path\n"
64	    "  extattrctl initattr [-f] [-p path] attrsize attrfile\n"
65	    "  extattrctl showattr attrfile\n"
66	    "  extattrctl enable path attrnamespace attrname attrfile\n"
67	    "  extattrctl disable path attrnamespace attrname\n");
68	exit(-1);
69}
70
71long
72num_inodes_by_path(char *path)
73{
74	struct statfs	buf;
75	int	error;
76
77	error = statfs(path, &buf);
78	if (error) {
79		perror("statfs");
80		return (-1);
81	}
82
83	return (buf.f_files);
84}
85
86static const char zero_buf[8192];
87
88int
89initattr(int argc, char *argv[])
90{
91	struct ufs_extattr_fileheader	uef;
92	char	*fs_path = NULL;
93	int	ch, i, error, flags;
94	ssize_t	wlen;
95	size_t	easize;
96
97	flags = O_CREAT | O_WRONLY | O_TRUNC | O_EXCL;
98	optind = 0;
99	while ((ch = getopt(argc, argv, "fp:r:w:")) != -1)
100		switch (ch) {
101		case 'f':
102			flags &= ~O_EXCL;
103			break;
104		case 'p':
105			fs_path = optarg;
106			break;
107		case '?':
108		default:
109			usage();
110		}
111
112	argc -= optind;
113	argv += optind;
114
115	if (argc != 2)
116		usage();
117
118	error = 0;
119	if ((i = open(argv[1], flags, 0600)) == -1) {
120		/* unable to open file */
121		perror(argv[1]);
122		return (-1);
123	}
124	uef.uef_magic = UFS_EXTATTR_MAGIC;
125	uef.uef_version = UFS_EXTATTR_VERSION;
126	uef.uef_size = atoi(argv[0]);
127	if (write(i, &uef, sizeof(uef)) == -1)
128		error = -1;
129	else if (fs_path != NULL) {
130		easize = (sizeof uef + uef.uef_size) *
131		    num_inodes_by_path(fs_path);
132		while (easize > 0) {
133			if (easize > sizeof zero_buf)
134				wlen = write(i, zero_buf, sizeof zero_buf);
135			else
136				wlen = write(i, zero_buf, easize);
137			if (wlen == -1) {
138				error = -1;
139				break;
140			}
141			easize -= wlen;
142		}
143	}
144	if (error == -1) {
145		perror(argv[1]);
146		unlink(argv[1]);
147		return (-1);
148	}
149
150	return (0);
151}
152
153int
154showattr(int argc, char *argv[])
155{
156	struct ufs_extattr_fileheader	uef;
157	int i, fd;
158
159	if (argc != 1)
160		usage();
161
162	fd = open(argv[0], O_RDONLY);
163	if (fd == -1) {
164		perror(argv[0]);
165		return (-1);
166	}
167
168	i = read(fd, &uef, sizeof(uef));
169	if (i == -1) {
170		perror(argv[0]);
171		return (-1);
172	}
173	if (i != sizeof(uef)) {
174		fprintf(stderr, "%s: invalid file header\n", argv[0]);
175		return (-1);
176	}
177
178	if (uef.uef_magic != UFS_EXTATTR_MAGIC) {
179		fprintf(stderr, "%s: bad magic\n", argv[0]);
180		return (-1);
181	}
182
183	printf("%s: version %d, size %d\n", argv[0], uef.uef_version,
184	    uef.uef_size);
185
186	return (0);
187}
188
189int
190main(int argc, char *argv[])
191{
192	int	error = 0, attrnamespace;
193
194	if (argc < 2)
195		usage();
196
197	if (!strcmp(argv[1], "start")) {
198		if (argc != 3)
199			usage();
200		error = extattrctl(argv[2], UFS_EXTATTR_CMD_START, NULL, 0,
201		    NULL);
202		if (error) {
203			perror("extattrctl start");
204			return (-1);
205		}
206	} else if (!strcmp(argv[1], "stop")) {
207		if (argc != 3)
208			usage();
209		error = extattrctl(argv[2], UFS_EXTATTR_CMD_STOP, NULL, 0,
210		   NULL);
211		if (error) {
212			perror("extattrctl stop");
213			return (-1);
214		}
215	} else if (!strcmp(argv[1], "enable")) {
216		if (argc != 6)
217			usage();
218		error = extattr_string_to_namespace(argv[3], &attrnamespace);
219		if (error) {
220			perror("extattrctl enable");
221			return (-1);
222		}
223		error = extattrctl(argv[2], UFS_EXTATTR_CMD_ENABLE, argv[5],
224		    attrnamespace, argv[4]);
225		if (error) {
226			perror("extattrctl enable");
227			return (-1);
228		}
229	} else if (!strcmp(argv[1], "disable")) {
230		if (argc != 5)
231			usage();
232		error = extattr_string_to_namespace(argv[3], &attrnamespace);
233		if (error) {
234			perror("extattrctl disable");
235			return (-1);
236		}
237		error = extattrctl(argv[2], UFS_EXTATTR_CMD_DISABLE, NULL,
238		    attrnamespace, argv[4]);
239		if (error) {
240			perror("extattrctl disable");
241			return (-1);
242		}
243	} else if (!strcmp(argv[1], "initattr")) {
244		argc -= 2;
245		argv += 2;
246		error = initattr(argc, argv);
247		if (error)
248			return (-1);
249	} else if (!strcmp(argv[1], "showattr")) {
250		argc -= 2;
251		argv += 2;
252		error = showattr(argc, argv);
253		if (error)
254			return (-1);
255	} else
256		usage();
257
258	return (0);
259}
260