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