extattrctl.c revision 65777
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: head/usr.sbin/extattrctl/extattrctl.c 65777 2000-09-12 14:35:48Z rwatson $
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
46extern char	*optarg;
47extern int	optind;
48
49void
50usage(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
63long
64num_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
78int
79initattr(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
154int
155main(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