1/* $NetBSD: extattrctl.c,v 1.3 2011/01/04 09:28:44 wiz Exp $ */ 2 3/*- 4 * Copyright (c) 1999-2002 Robert N. M. Watson 5 * All rights reserved. 6 * 7 * This software was developed by Robert Watson for the TrustedBSD Project. 8 * 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. 17 * 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. 29 * 30 * $FreeBSD: src/usr.sbin/extattrctl/extattrctl.c,v 1.19 2002/04/19 01:42:55 rwatson Exp $ 31 */ 32 33/* 34 * Developed by the TrustedBSD Project. 35 * Support for file system extended attribute. 36 */ 37 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> 43 44#include <ufs/ufs/extattr.h> 45 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> 53 54#include <machine/bswap.h> 55#include <machine/endian.h> 56 57static int needswap; 58 59static uint32_t 60rw32(uint32_t v) 61{ 62 if (needswap) 63 return (bswap32(v)); 64 return (v); 65} 66 67__dead static void 68usage(void) 69{ 70 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); 82} 83 84static uint64_t 85num_inodes_by_path(const char *path) 86{ 87 struct statvfs buf; 88 89 if (statvfs(path, &buf) == -1) { 90 warn("statvfs(%s)", path); 91 return (-1); 92 } 93 94 return (buf.f_files); 95} 96 97static const char zero_buf[8192]; 98 99static int 100initattr(int argc, char *argv[]) 101{ 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; 107 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(); 138 } 139 } 140 141 argc -= optind; 142 argv += optind; 143 144 if (argc != 2) 145 usage(); 146 147 error = 0; 148 if ((i = open(argv[1], flags, 0600)) == -1) { 149 warn("open(%s)", argv[1]); 150 return (-1); 151 } 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 attribute 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; 169 } 170 easize -= wlen; 171 } 172 } 173 close(i); 174 if (error == -1) { 175 unlink(argv[1]); 176 return (-1); 177 } 178 179 return (0); 180} 181 182static int 183showattr(int argc, char *argv[]) 184{ 185 struct ufs_extattr_fileheader uef; 186 int i, fd; 187 const char *bo; 188 189 if (argc != 1) 190 usage(); 191 192 fd = open(argv[0], O_RDONLY); 193 if (fd == -1) { 194 warn("open(%s)", argv[0]); 195 return (-1); 196 } 197 198 i = read(fd, &uef, sizeof(uef)); 199 if (i != sizeof(uef)) { 200 warn("unable to read attribute file header"); 201 (void)close(fd); 202 return (-1); 203 } 204 205 if (rw32(uef.uef_magic) != UFS_EXTATTR_MAGIC) { 206 needswap = 1; 207 if (rw32(uef.uef_magic) != UFS_EXTATTR_MAGIC) { 208 fprintf(stderr, "%s: bad magic\n", argv[0]); 209 (void)close(fd); 210 return (-1); 211 } 212 } 213 214#if BYTE_ORDER == LITTLE_ENDIAN 215 bo = needswap ? "big-endian" : "little-endian"; 216#else 217 bo = needswap ? "little-endian" : "big-endian"; 218#endif 219 220 printf("%s: version %u, size %u, byte-order: %s\n", 221 argv[0], rw32(uef.uef_version), rw32(uef.uef_size), bo); 222 223 close(fd); 224 return (0); 225} 226 227int 228main(int argc, char *argv[]) 229{ 230 int error = 0, attrnamespace; 231 232 if (argc < 2) 233 usage(); 234 235 if (!strcmp(argv[1], "start")) { 236 if (argc != 3) 237 usage(); 238 error = extattrctl(argv[2], UFS_EXTATTR_CMD_START, NULL, 0, 239 NULL); 240 if (error) 241 err(1, "start"); 242 } else if (!strcmp(argv[1], "stop")) { 243 if (argc != 3) 244 usage(); 245 error = extattrctl(argv[2], UFS_EXTATTR_CMD_STOP, NULL, 0, 246 NULL); 247 if (error) 248 err(1, "stop"); 249 } else if (!strcmp(argv[1], "enable")) { 250 if (argc != 6) 251 usage(); 252 error = extattr_string_to_namespace(argv[3], &attrnamespace); 253 if (error) 254 errx(1, "bad namespace: %s", argv[3]); 255 error = extattrctl(argv[2], UFS_EXTATTR_CMD_ENABLE, argv[5], 256 attrnamespace, argv[4]); 257 if (error) 258 err(1, "enable"); 259 } else if (!strcmp(argv[1], "disable")) { 260 if (argc != 5) 261 usage(); 262 error = extattr_string_to_namespace(argv[3], &attrnamespace); 263 if (error) 264 errx(1, "bad namespace: %s", argv[3]); 265 error = extattrctl(argv[2], UFS_EXTATTR_CMD_DISABLE, NULL, 266 attrnamespace, argv[4]); 267 if (error) 268 err(1, "disable"); 269 } else if (!strcmp(argv[1], "initattr")) { 270 argc -= 2; 271 argv += 2; 272 error = initattr(argc, argv); 273 if (error) 274 return (1); 275 } else if (!strcmp(argv[1], "showattr")) { 276 argc -= 2; 277 argv += 2; 278 error = showattr(argc, argv); 279 if (error) 280 return (1); 281 } else 282 usage(); 283 284 return (0); 285} 286