extattrctl.c revision 86994
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 86994 2001-11-27 18:58:56Z jedgar $
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[]);
52long num_inodes_by_path(char *path);
53void usage(void);
54
55void
56usage()
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
69long
70num_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
84int
85initattr(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
163int
164main(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