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