1 /* $NetBSD: extattrctl.c,v 1.2 2009/04/15 06:01:01 lukem 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 57 static int needswap; 58 59 static uint32_t 60 rw32(uint32_t v) 61 { 62 if (needswap) 63 return (bswap32(v)); 64 return (v); 65 } 66 67 static void 68 usage(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 84 static uint64_t 85 num_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 97 static const char zero_buf[8192]; 98 99 static int 100 initattr(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 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; 169 } 170 easize -= wlen; 171 } 172 } 173 if (error == -1) { 174 unlink(argv[1]); 175 return (-1); 176 } 177 178 return (0); 179 } 180 181 static int 182 showattr(int argc, char *argv[]) 183 { 184 struct ufs_extattr_fileheader uef; 185 int i, fd; 186 const char *bo; 187 188 if (argc != 1) 189 usage(); 190 191 fd = open(argv[0], O_RDONLY); 192 if (fd == -1) { 193 warn("open(%s)", argv[0]); 194 return (-1); 195 } 196 197 i = read(fd, &uef, sizeof(uef)); 198 if (i != sizeof(uef)) { 199 warn("unable to read attribute file header"); 200 return (-1); 201 } 202 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); 208 } 209 } 210 211 #if BYTE_ORDER == LITTLE_ENDIAN 212 bo = needswap ? "big-endian" : "little-endian"; 213 #else 214 bo = needswap ? "little-endian" : "big-endian"; 215 #endif 216 217 printf("%s: version %u, size %u, byte-order: %s\n", 218 argv[0], rw32(uef.uef_version), rw32(uef.uef_size), bo); 219 220 return (0); 221 } 222 223 int 224 main(int argc, char *argv[]) 225 { 226 int error = 0, attrnamespace; 227 228 if (argc < 2) 229 usage(); 230 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(); 279 280 return (0); 281 } 282