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