extattrctl.c revision 59446
1234370Sjasone/*-
2234370Sjasone * Copyright (c) 1999, 2000 Robert N. M. Watson
3234370Sjasone * All rights reserved.
4234370Sjasone *
5234370Sjasone * Redistribution and use in source and binary forms, with or without
6234370Sjasone * modification, are permitted provided that the following conditions
7234370Sjasone * are met:
8234370Sjasone * 1. Redistributions of source code must retain the above copyright
9234370Sjasone *    notice, this list of conditions and the following disclaimer.
10234370Sjasone * 2. Redistributions in binary form must reproduce the above copyright
11234370Sjasone *    notice, this list of conditions and the following disclaimer in the
12234370Sjasone *    documentation and/or other materials provided with the distribution.
13234370Sjasone *
14234370Sjasone * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15234370Sjasone * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16234370Sjasone * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17234370Sjasone * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18234370Sjasone * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19234370Sjasone * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20234370Sjasone * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21234370Sjasone * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22234370Sjasone * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23234370Sjasone * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24234370Sjasone * SUCH DAMAGE.
25234370Sjasone *
26234370Sjasone *	$FreeBSD: head/usr.sbin/extattrctl/extattrctl.c 59446 2000-04-20 20:32:43Z rwatson $
27234370Sjasone */
28234370Sjasone/*
29234370Sjasone * TrustedBSD Project - extended attribute support for UFS-like file systems
30234370Sjasone */
31234370Sjasone
32234370Sjasone#include <sys/types.h>
33234370Sjasone#include <sys/uio.h>
34234370Sjasone#include <sys/extattr.h>
35234370Sjasone#include <sys/param.h>
36234370Sjasone#include <sys/mount.h>
37234370Sjasone
38234370Sjasone#include <ufs/ufs/extattr.h>
39234370Sjasone
40234370Sjasone#include <fcntl.h>
41234370Sjasone#include <stdio.h>
42234370Sjasone#include <stdlib.h>
43234370Sjasone#include <string.h>
44234370Sjasone#include <unistd.h>
45234370Sjasone
46234370Sjasoneextern char	*optarg;
47234370Sjasoneextern int	optind;
48234370Sjasone
49234370Sjasonevoid
50234370Sjasoneusage(void)
51234370Sjasone{
52234370Sjasone
53234370Sjasone	fprintf(stderr,
54234370Sjasone	    "usage:\n"
55234370Sjasone	    "  extattrctl start [path]\n"
56234370Sjasone	    "  extattrctl stop [path]\n"
57234370Sjasone	    "  extattrctl initattr [-p path] [-r [kroa]] [-w [kroa]] "
58234370Sjasone	    "[attrsize] [attrfile]\n"
59234370Sjasone	    "  extattrctl enable [path] [attrname] [attrfile]\n"
60234370Sjasone	    "  extattrctl disable [path] [attrname]\n");
61234370Sjasone	exit(-1);
62234370Sjasone}
63234370Sjasone
64234370Sjasone/*
65234370Sjasone * Return a level, or -1
66234370Sjasone */
67234370Sjasoneint
68234370Sjasoneextattr_level_from_string(char *string)
69234370Sjasone{
70234370Sjasone
71234370Sjasone	if (strlen(string) != 1)
72234370Sjasone		return (-1);
73234370Sjasone
74234370Sjasone	switch(string[0]) {
75234370Sjasone	case 'k':
76234370Sjasone	case 'K':
77234370Sjasone		return (UFS_EXTATTR_PERM_KERNEL);
78234370Sjasone	case 'r':
79234370Sjasone	case 'R':
80234370Sjasone		return (UFS_EXTATTR_PERM_ROOT);
81234370Sjasone	case 'o':
82234370Sjasone	case 'O':
83234370Sjasone		return (UFS_EXTATTR_PERM_OWNER);
84234370Sjasone	case 'a':
85234370Sjasone	case 'A':
86234370Sjasone		return (UFS_EXTATTR_PERM_ANYONE);
87234370Sjasone	default:
88234370Sjasone		return (-1);
89234370Sjasone	}
90234370Sjasone}
91234370Sjasone
92234370Sjasonelong
93234370Sjasonenum_inodes_by_path(char *path)
94234370Sjasone{
95234370Sjasone	struct statfs	buf;
96234370Sjasone	int	error;
97234370Sjasone
98234370Sjasone	error = statfs(path, &buf);
99234370Sjasone	if (error) {
100234370Sjasone		perror("statfs");
101234370Sjasone		return (-1);
102234370Sjasone	}
103234370Sjasone
104234370Sjasone	return (buf.f_files);
105234370Sjasone}
106234370Sjasone
107234370Sjasoneint
108234370Sjasoneinitattr(int argc, char *argv[])
109234370Sjasone{
110234370Sjasone	struct ufs_extattr_fileheader	uef;
111234370Sjasone	char	*fs_path = NULL;
112234370Sjasone	char	*zero_buf = NULL;
113234370Sjasone	long	loop, num_inodes;
114234370Sjasone	int	initattr_rlevel = UFS_EXTATTR_PERM_ROOT;
115234370Sjasone	int	initattr_wlevel = UFS_EXTATTR_PERM_ROOT;
116	int	ch, i, error;
117
118	optind = 0;
119	while ((ch = getopt(argc, argv, "p:rw")) != -1)
120		switch (ch) {
121		case 'p':
122			fs_path = strdup(optarg);
123			break;
124		case 'r':
125			initattr_rlevel = extattr_level_from_string(optarg);
126			if (initattr_rlevel == -1)
127				usage();
128			break;
129		case 'w':
130			initattr_wlevel = extattr_level_from_string(optarg);
131			if (initattr_wlevel == -1)
132				usage();
133			break;
134		case '?':
135		default:
136			usage();
137		}
138
139	argc -= optind;
140	argv += optind;
141
142	if (argc != 2)
143		usage();
144
145	error = 0;
146	if ((i = open(argv[1], O_CREAT | O_EXCL | O_WRONLY, 0600)) != -1) {
147		uef.uef_magic = UFS_EXTATTR_MAGIC;
148		uef.uef_version = UFS_EXTATTR_VERSION;
149		uef.uef_write_perm = initattr_wlevel;
150		uef.uef_read_perm = initattr_rlevel;
151		uef.uef_size = atoi(argv[0]);
152		if (write(i, &uef, sizeof(uef)) == -1)
153			error = -1;
154		else if (fs_path) {
155			zero_buf = (char *) (malloc(uef.uef_size));
156			if (zero_buf == NULL) {
157				perror("malloc");
158				unlink(argv[1]);
159				return (-1);
160			}
161			memset(zero_buf, 0, uef.uef_size);
162			num_inodes = num_inodes_by_path(fs_path);
163			for (loop = 0; loop < num_inodes; loop++) {
164				error = write(i, zero_buf, uef.uef_size);
165				if (error != uef.uef_size) {
166					perror("write");
167					unlink(argv[1]);
168					return (-1);
169				}
170			}
171		}
172	}
173	if (i == -1 || error == -1) {
174		perror(argv[1]);
175		unlink(argv[1]);
176		return (-1);
177	}
178
179	return (0);
180}
181
182int
183main(int argc, char *argv[])
184{
185	int	error = 0;
186
187	if (argc < 2)
188		usage();
189
190	if (!strcmp(argv[1], "start")) {
191		if (argc != 3)
192			usage();
193		error = extattrctl(argv[2], UFS_EXTATTR_CMD_START, 0, 0);
194	} else if (!strcmp(argv[1], "stop")) {
195		if (argc != 3)
196			usage();
197		error = extattrctl(argv[2], UFS_EXTATTR_CMD_STOP, 0, 0);
198	} else if (!strcmp(argv[1], "enable")) {
199		if (argc != 5)
200			usage();
201		error = extattrctl(argv[2], UFS_EXTATTR_CMD_ENABLE, argv[3],
202		    argv[4]);
203	} else if (!strcmp(argv[1], "disable")) {
204		if (argc != 4)
205			usage();
206		error = extattrctl(argv[2], UFS_EXTATTR_CMD_DISABLE, argv[3],
207		    NULL);
208	} else if (!strcmp(argv[1], "initattr")) {
209		argc -= 2;
210		argv += 2;
211		error = initattr(argc, argv);
212	} else
213		usage();
214
215	if (error)
216		perror(argv[1]);
217
218	return(error);
219}
220