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