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 long num_inodes_by_path(char *path); 53 void usage(void); 54 55 void 56 usage() 57 { 58 59 fprintf(stderr, 60 "usage:\n" 61 " extattrctl start [path]\n" 62 " extattrctl stop [path]\n" 63 " extattrctl initattr [-f] [-p path] [attrsize] [attrfile]\n" 64 " extattrctl enable [path] [attrnamespace] [attrname] [attrfile]\n" 65 " extattrctl disable [path] [attrnamespace] [attrname]\n"); 66 exit(-1); 67 } 68 69 long 70 num_inodes_by_path(char *path) 71 { 72 struct statfs buf; 73 int error; 74 75 error = statfs(path, &buf); 76 if (error) { 77 perror("statfs"); 78 return (-1); 79 } 80 81 return (buf.f_files); 82 } 83 84 int 85 initattr(int argc, char *argv[]) 86 { 87 struct ufs_extattr_fileheader uef; 88 char *fs_path = NULL; 89 char *zero_buf = NULL; 90 long loop, num_inodes; 91 int ch, i, error, chunksize, overwrite = 0, flags; 92 93 optind = 0; 94 while ((ch = getopt(argc, argv, "fp:r:w:")) != -1) 95 switch (ch) { 96 case 'f': 97 overwrite = 1; 98 break; 99 case 'p': 100 if ((fs_path = strdup(optarg)) == NULL) { 101 perror("strdup"); 102 return(-1); 103 } 104 break; 105 case '?': 106 default: 107 usage(); 108 } 109 110 argc -= optind; 111 argv += optind; 112 113 if (argc != 2) 114 usage(); 115 116 if (overwrite) 117 flags = O_CREAT | O_WRONLY; 118 else 119 flags = O_CREAT | O_EXCL | O_WRONLY; 120 121 error = 0; 122 if ((i = open(argv[1], flags, 0600)) != -1) { 123 uef.uef_magic = UFS_EXTATTR_MAGIC; 124 uef.uef_version = UFS_EXTATTR_VERSION; 125 uef.uef_size = atoi(argv[0]); 126 if (write(i, &uef, sizeof(uef)) == -1) 127 error = -1; 128 else if (fs_path) { 129 chunksize = sizeof(struct ufs_extattr_header) + 130 uef.uef_size; 131 zero_buf = (char *) (malloc(chunksize)); 132 if (zero_buf == NULL) { 133 perror("malloc"); 134 unlink(argv[1]); 135 return (-1); 136 } 137 memset(zero_buf, 0, chunksize); 138 num_inodes = num_inodes_by_path(fs_path); 139 for (loop = 0; loop < num_inodes; loop++) { 140 error = write(i, zero_buf, chunksize); 141 if (error != chunksize) { 142 perror("write"); 143 unlink(argv[1]); 144 return (-1); 145 } 146 } 147 } 148 } 149 if (i == -1) { 150 /* unable to open file */ 151 perror(argv[1]); 152 return (-1); 153 } 154 if (error == -1) { 155 perror(argv[1]); 156 unlink(argv[1]); 157 return (-1); 158 } 159 160 return (0); 161 } 162 163 int 164 main(int argc, char *argv[]) 165 { 166 int error = 0, attrnamespace; 167 168 if (argc < 2) 169 usage(); 170 171 if (!strcmp(argv[1], "start")) { 172 if (argc != 3) 173 usage(); 174 error = extattrctl(argv[2], UFS_EXTATTR_CMD_START, NULL, 0, 175 NULL); 176 if (error) { 177 perror("extattrctl start"); 178 return (-1); 179 } 180 } else if (!strcmp(argv[1], "stop")) { 181 if (argc != 3) 182 usage(); 183 error = extattrctl(argv[2], UFS_EXTATTR_CMD_STOP, NULL, 0, 184 NULL); 185 if (error) { 186 perror("extattrctl stop"); 187 return (-1); 188 } 189 } else if (!strcmp(argv[1], "enable")) { 190 if (argc != 6) 191 usage(); 192 error = extattr_string_to_namespace(argv[3], &attrnamespace); 193 if (error) { 194 perror("extattrctl enable"); 195 return (-1); 196 } 197 error = extattrctl(argv[2], UFS_EXTATTR_CMD_ENABLE, argv[5], 198 attrnamespace, argv[4]); 199 if (error) { 200 perror("extattrctl enable"); 201 return (-1); 202 } 203 } else if (!strcmp(argv[1], "disable")) { 204 if (argc != 5) 205 usage(); 206 error = extattr_string_to_namespace(argv[3], &attrnamespace); 207 if (error) { 208 perror("extattrctl disable"); 209 return (-1); 210 } 211 error = extattrctl(argv[2], UFS_EXTATTR_CMD_DISABLE, NULL, 212 attrnamespace, argv[4]); 213 if (error) { 214 perror("extattrctl disable"); 215 return (-1); 216 } 217 } else if (!strcmp(argv[1], "initattr")) { 218 argc -= 2; 219 argv += 2; 220 error = initattr(argc, argv); 221 if (error) 222 return (-1); 223 } else 224 usage(); 225 226 return (0); 227 } 228