Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / usr.sbin / extattrctl / extattrctl.c
blob3775f98de9d3b4ccb7e0f724812ae42ea3db8799
1 /* $NetBSD: extattrctl.c,v 1.1 2005/08/28 19:37:59 thorpej Exp $ */
3 /*-
4 * Copyright (c) 1999-2002 Robert N. M. Watson
5 * All rights reserved.
7 * This software was developed by Robert Watson for the TrustedBSD Project.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
30 * $FreeBSD: src/usr.sbin/extattrctl/extattrctl.c,v 1.19 2002/04/19 01:42:55 rwatson Exp $
34 * Developed by the TrustedBSD Project.
35 * Support for file system extended attribute.
38 #include <sys/types.h>
39 #include <sys/uio.h>
40 #include <sys/extattr.h>
41 #include <sys/param.h>
42 #include <sys/mount.h>
44 #include <ufs/ufs/extattr.h>
46 #include <err.h>
47 #include <fcntl.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <unistd.h>
52 #include <util.h>
54 #include <machine/bswap.h>
55 #include <machine/endian.h>
57 static int needswap;
59 static uint32_t
60 rw32(uint32_t v)
62 if (needswap)
63 return (bswap32(v));
64 return (v);
67 static void
68 usage(void)
71 fprintf(stderr,
72 "usage:\n"
73 " %s start path\n"
74 " %s stop path\n"
75 " %s initattr [-f] [-p path] attrsize attrfile\n"
76 " %s showattr attrfile\n"
77 " %s enable path attrnamespace attrname attrfile\n"
78 " %s disable path attrnamespace attrname\n",
79 getprogname(), getprogname(), getprogname(),
80 getprogname(), getprogname(), getprogname());
81 exit(1);
84 static uint64_t
85 num_inodes_by_path(const char *path)
87 struct statvfs buf;
89 if (statvfs(path, &buf) == -1) {
90 warn("statvfs(%s)", path);
91 return (-1);
94 return (buf.f_files);
97 static const char zero_buf[8192];
99 static int
100 initattr(int argc, char *argv[])
102 struct ufs_extattr_fileheader uef;
103 char *fs_path = NULL;
104 int ch, i, error, flags;
105 ssize_t wlen;
106 size_t easize;
108 flags = O_CREAT | O_WRONLY | O_TRUNC | O_EXCL;
109 optind = 0;
110 while ((ch = getopt(argc, argv, "fp:r:w:")) != -1) {
111 switch (ch) {
112 case 'f':
113 flags &= ~O_EXCL;
114 break;
115 case 'p':
116 fs_path = optarg;
117 break;
118 case 'B':
119 #if BYTE_ORDER == LITTLE_ENDIAN
120 if (strcmp(optarg, "le") == 0)
121 needswap = 0;
122 else if (strcmp(optarg, "be") == 0)
123 needswap = 1;
124 else
125 usage();
126 #else
127 if (strcmp(optarg, "be") == 0)
128 needswap = 0;
129 else if (strcmp(optarg, "le") == 0)
130 needswap = 1;
131 else
132 usage();
133 #endif
134 break;
135 case '?':
136 default:
137 usage();
141 argc -= optind;
142 argv += optind;
144 if (argc != 2)
145 usage();
147 error = 0;
148 if ((i = open(argv[1], flags, 0600)) == -1) {
149 warn("open(%s)", argv[1]);
150 return (-1);
152 uef.uef_magic = rw32(UFS_EXTATTR_MAGIC);
153 uef.uef_version = rw32(UFS_EXTATTR_VERSION);
154 uef.uef_size = rw32(atoi(argv[0]));
155 if (write(i, &uef, sizeof(uef)) != sizeof(uef)) {
156 warn("unable to write arribute file header");
157 error = -1;
158 } else if (fs_path != NULL) {
159 easize = (sizeof(uef) + uef.uef_size) *
160 num_inodes_by_path(fs_path);
161 while (easize > 0) {
162 size_t x = (easize > sizeof(zero_buf)) ?
163 sizeof(zero_buf) : easize;
164 wlen = write(i, zero_buf, x);
165 if ((size_t)wlen != x) {
166 warn("unable to write attribute file");
167 error = -1;
168 break;
170 easize -= wlen;
173 if (error == -1) {
174 unlink(argv[1]);
175 return (-1);
178 return (0);
181 static int
182 showattr(int argc, char *argv[])
184 struct ufs_extattr_fileheader uef;
185 int i, fd;
186 const char *bo;
188 if (argc != 1)
189 usage();
191 fd = open(argv[0], O_RDONLY);
192 if (fd == -1) {
193 warn("open(%s)", argv[0]);
194 return (-1);
197 i = read(fd, &uef, sizeof(uef));
198 if (i != sizeof(uef)) {
199 warn("unable to read attribute file header");
200 return (-1);
203 if (rw32(uef.uef_magic) != UFS_EXTATTR_MAGIC) {
204 needswap = 1;
205 if (rw32(uef.uef_magic) != UFS_EXTATTR_MAGIC) {
206 fprintf(stderr, "%s: bad magic\n", argv[0]);
207 return (-1);
211 #if BYTE_ORDER == LITTLE_ENDIAN
212 bo = needswap ? "big-endian" : "little-endian";
213 #else
214 bo = needswap ? "little-endian" : "big-endian";
215 #endif
217 printf("%s: version %u, size %u, byte-order: %s\n",
218 argv[0], rw32(uef.uef_version), rw32(uef.uef_size), bo);
220 return (0);
224 main(int argc, char *argv[])
226 int error = 0, attrnamespace;
228 if (argc < 2)
229 usage();
231 if (!strcmp(argv[1], "start")) {
232 if (argc != 3)
233 usage();
234 error = extattrctl(argv[2], UFS_EXTATTR_CMD_START, NULL, 0,
235 NULL);
236 if (error)
237 err(1, "start");
238 } else if (!strcmp(argv[1], "stop")) {
239 if (argc != 3)
240 usage();
241 error = extattrctl(argv[2], UFS_EXTATTR_CMD_STOP, NULL, 0,
242 NULL);
243 if (error)
244 err(1, "stop");
245 } else if (!strcmp(argv[1], "enable")) {
246 if (argc != 6)
247 usage();
248 error = extattr_string_to_namespace(argv[3], &attrnamespace);
249 if (error)
250 errx(1, "bad namespace: %s", argv[3]);
251 error = extattrctl(argv[2], UFS_EXTATTR_CMD_ENABLE, argv[5],
252 attrnamespace, argv[4]);
253 if (error)
254 err(1, "enable");
255 } else if (!strcmp(argv[1], "disable")) {
256 if (argc != 5)
257 usage();
258 error = extattr_string_to_namespace(argv[3], &attrnamespace);
259 if (error)
260 errx(1, "bad namespace: %s", argv[3]);
261 error = extattrctl(argv[2], UFS_EXTATTR_CMD_DISABLE, NULL,
262 attrnamespace, argv[4]);
263 if (error)
264 err(1, "disable");
265 } else if (!strcmp(argv[1], "initattr")) {
266 argc -= 2;
267 argv += 2;
268 error = initattr(argc, argv);
269 if (error)
270 return (1);
271 } else if (!strcmp(argv[1], "showattr")) {
272 argc -= 2;
273 argv += 2;
274 error = showattr(argc, argv);
275 if (error)
276 return (1);
277 } else
278 usage();
280 return (0);