1 /*- 2 * Copyright (c) 1999-2002 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(void) 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 static const char zero_buf[8192]; 87 88 int 89 initattr(int argc, char *argv[]) 90 { 91 struct ufs_extattr_fileheader uef; 92 char *fs_path = NULL; 93 int ch, i, error, flags; 94 ssize_t wlen; 95 size_t easize; 96 97 flags = O_CREAT | O_WRONLY | O_TRUNC | O_EXCL; 98 optind = 0; 99 while ((ch = getopt(argc, argv, "fp:r:w:")) != -1) 100 switch (ch) { 101 case 'f': 102 flags &= ~O_EXCL; 103 break; 104 case 'p': 105 fs_path = optarg; 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 error = 0; 119 if ((i = open(argv[1], flags, 0600)) == -1) { 120 /* unable to open file */ 121 perror(argv[1]); 122 return (-1); 123 } 124 uef.uef_magic = UFS_EXTATTR_MAGIC; 125 uef.uef_version = UFS_EXTATTR_VERSION; 126 uef.uef_size = atoi(argv[0]); 127 if (write(i, &uef, sizeof(uef)) == -1) 128 error = -1; 129 else if (fs_path != NULL) { 130 easize = (sizeof uef + uef.uef_size) * 131 num_inodes_by_path(fs_path); 132 while (easize > 0) { 133 if (easize > sizeof zero_buf) 134 wlen = write(i, zero_buf, sizeof zero_buf); 135 else 136 wlen = write(i, zero_buf, easize); 137 if (wlen == -1) { 138 error = -1; 139 break; 140 } 141 easize -= wlen; 142 } 143 } 144 if (error == -1) { 145 perror(argv[1]); 146 unlink(argv[1]); 147 return (-1); 148 } 149 150 return (0); 151 } 152 153 int 154 showattr(int argc, char *argv[]) 155 { 156 struct ufs_extattr_fileheader uef; 157 int i, fd; 158 159 if (argc != 1) 160 usage(); 161 162 fd = open(argv[0], O_RDONLY); 163 if (fd == -1) { 164 perror(argv[0]); 165 return (-1); 166 } 167 168 i = read(fd, &uef, sizeof(uef)); 169 if (i == -1) { 170 perror(argv[0]); 171 return (-1); 172 } 173 if (i != sizeof(uef)) { 174 fprintf(stderr, "%s: invalid file header\n", argv[0]); 175 return (-1); 176 } 177 178 if (uef.uef_magic != UFS_EXTATTR_MAGIC) { 179 fprintf(stderr, "%s: bad magic\n", argv[0]); 180 return (-1); 181 } 182 183 printf("%s: version %d, size %d\n", argv[0], uef.uef_version, 184 uef.uef_size); 185 186 return (0); 187 } 188 189 int 190 main(int argc, char *argv[]) 191 { 192 int error = 0, attrnamespace; 193 194 if (argc < 2) 195 usage(); 196 197 if (!strcmp(argv[1], "start")) { 198 if (argc != 3) 199 usage(); 200 error = extattrctl(argv[2], UFS_EXTATTR_CMD_START, NULL, 0, 201 NULL); 202 if (error) { 203 perror("extattrctl start"); 204 return (-1); 205 } 206 } else if (!strcmp(argv[1], "stop")) { 207 if (argc != 3) 208 usage(); 209 error = extattrctl(argv[2], UFS_EXTATTR_CMD_STOP, NULL, 0, 210 NULL); 211 if (error) { 212 perror("extattrctl stop"); 213 return (-1); 214 } 215 } else if (!strcmp(argv[1], "enable")) { 216 if (argc != 6) 217 usage(); 218 error = extattr_string_to_namespace(argv[3], &attrnamespace); 219 if (error) { 220 perror("extattrctl enable"); 221 return (-1); 222 } 223 error = extattrctl(argv[2], UFS_EXTATTR_CMD_ENABLE, argv[5], 224 attrnamespace, argv[4]); 225 if (error) { 226 perror("extattrctl enable"); 227 return (-1); 228 } 229 } else if (!strcmp(argv[1], "disable")) { 230 if (argc != 5) 231 usage(); 232 error = extattr_string_to_namespace(argv[3], &attrnamespace); 233 if (error) { 234 perror("extattrctl disable"); 235 return (-1); 236 } 237 error = extattrctl(argv[2], UFS_EXTATTR_CMD_DISABLE, NULL, 238 attrnamespace, argv[4]); 239 if (error) { 240 perror("extattrctl disable"); 241 return (-1); 242 } 243 } else if (!strcmp(argv[1], "initattr")) { 244 argc -= 2; 245 argv += 2; 246 error = initattr(argc, argv); 247 if (error) 248 return (-1); 249 } else if (!strcmp(argv[1], "showattr")) { 250 argc -= 2; 251 argv += 2; 252 error = showattr(argc, argv); 253 if (error) 254 return (-1); 255 } else 256 usage(); 257 258 return (0); 259 } 260