1 /* $NetBSD: getextattr.c,v 1.1 2005/01/02 17:55:48 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2002, 2003 Networks Associates Technology, Inc. 5 * Copyright (c) 2002 Poul-Henning Kamp. 6 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 7 * All rights reserved. 8 * 9 * This software was developed for the FreeBSD Project by Poul-Henning 10 * Kamp and Network Associates Laboratories, the Security Research Division 11 * of Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 12 * ("CBOSS"), as part of the DARPA CHATS research program 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. The names of the authors may not be used to endorse or promote 23 * products derived from this software without specific prior written 24 * permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * FreeBSD: src/usr.sbin/extattr/rmextattr.c,v 1.6 2003/06/05 04:30:00 rwatson Exp 39 */ 40 41 #include <sys/types.h> 42 #include <sys/uio.h> 43 #include <sys/extattr.h> 44 45 #include <err.h> 46 #include <errno.h> 47 //#include <libgen.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <unistd.h> 52 #include <vis.h> 53 //#include <util.h> 54 55 static enum { EADUNNO, EAGET, EASET, EARM, EALS } what = EADUNNO; 56 57 static void 58 usage(void) 59 { 60 61 switch (what) { 62 case EAGET: 63 fprintf(stderr, "usage: %s [-fhqsx] " 64 "attrnamespace attrname filename ...\n", getprogname()); 65 exit(1); 66 67 case EASET: 68 fprintf(stderr, "usage: %s [-fhnq] " 69 "attrnamespace attrname attrvalue filename ...\n", 70 getprogname()); 71 exit(1); 72 73 case EARM: 74 fprintf(stderr, "usage: %s [-fhq] " 75 "attrnamespace attrname filename ...\n", getprogname()); 76 exit(1); 77 78 case EALS: 79 fprintf(stderr, "usage: %s [-fhq] " 80 "attrnamespace filename ...\n", getprogname()); 81 exit(1); 82 83 case EADUNNO: 84 default: 85 fprintf(stderr, 86 "usage: (getextattr|lsextattr|rmextattr|setextattr)\n"); 87 exit (1); 88 } 89 } 90 91 static void 92 mkbuf(char **buf, int *oldlen, int newlen) 93 { 94 95 if (*oldlen >= newlen) 96 return; 97 if (*buf != NULL) 98 free(*buf); 99 *buf = malloc(newlen); 100 if (*buf == NULL) 101 err(1, "malloc"); 102 *oldlen = newlen; 103 return; 104 } 105 106 int 107 main(int argc, char *argv[]) 108 { 109 char *buf, *visbuf; 110 const char *p; 111 112 const char *options, *attrname; 113 int buflen, visbuflen, ch, error, i, arg_counter, attrnamespace, 114 minargc; 115 116 int flag_force = 0; 117 int flag_nofollow = 0; 118 int flag_null = 0; 119 int flag_quiet = 0; 120 int flag_string = 0; 121 int flag_hex = 0; 122 123 visbuflen = buflen = 0; 124 visbuf = buf = NULL; 125 126 p = getprogname(); 127 if (strcmp(p, "getextattr") == 0) { 128 what = EAGET; 129 options = "fhqsx"; 130 minargc = 3; 131 } else if (strcmp(p, "setextattr") == 0) { 132 what = EASET; 133 options = "fhnq"; 134 minargc = 4; 135 } else if (strcmp(p, "rmextattr") == 0) { 136 what = EARM; 137 options = "fhq"; 138 minargc = 3; 139 } else if (strcmp(p, "lsextattr") == 0) { 140 what = EALS; 141 options = "fhq"; 142 minargc = 2; 143 } else 144 usage(); 145 146 while ((ch = getopt(argc, argv, options)) != -1) { 147 switch (ch) { 148 case 'f': 149 flag_force = 1; 150 break; 151 case 'h': 152 flag_nofollow = 1; 153 break; 154 case 'n': 155 flag_null = 1; 156 break; 157 case 'q': 158 flag_quiet = 1; 159 break; 160 case 's': 161 flag_string = 1; 162 break; 163 case 'x': 164 flag_hex = 1; 165 break; 166 default: 167 usage(); 168 } 169 } 170 171 argc -= optind; 172 argv += optind; 173 174 if (argc < minargc) 175 usage(); 176 177 error = extattr_string_to_namespace(argv[0], &attrnamespace); 178 if (error) 179 err(1, argv[0]); 180 argc--; argv++; 181 182 if (what != EALS) { 183 attrname = argv[0]; 184 argc--; argv++; 185 } else 186 attrname = NULL; 187 188 if (what == EASET) { 189 mkbuf(&buf, &buflen, strlen(argv[0]) + 1); 190 strcpy(buf, argv[0]); 191 argc--; argv++; 192 } 193 194 for (arg_counter = 0; arg_counter < argc; arg_counter++) { 195 switch (what) { 196 case EARM: 197 if (flag_nofollow) 198 error = extattr_delete_link(argv[arg_counter], 199 attrnamespace, attrname); 200 else 201 error = extattr_delete_file(argv[arg_counter], 202 attrnamespace, attrname); 203 if (error >= 0) 204 continue; 205 break; 206 case EASET: 207 if (flag_nofollow) 208 error = extattr_set_link(argv[arg_counter], 209 attrnamespace, attrname, buf, 210 strlen(buf) + flag_null); 211 else 212 error = extattr_set_file(argv[arg_counter], 213 attrnamespace, attrname, buf, 214 strlen(buf) + flag_null); 215 if (error >= 0) 216 continue; 217 break; 218 case EALS: 219 if (flag_nofollow) 220 error = extattr_list_link(argv[arg_counter], 221 attrnamespace, NULL, 0); 222 else 223 error = extattr_list_file(argv[arg_counter], 224 attrnamespace, NULL, 0); 225 if (error < 0) 226 break; 227 mkbuf(&buf, &buflen, error); 228 if (flag_nofollow) 229 error = extattr_list_link(argv[arg_counter], 230 attrnamespace, buf, buflen); 231 else 232 error = extattr_list_file(argv[arg_counter], 233 attrnamespace, buf, buflen); 234 if (error < 0) 235 break; 236 if (!flag_quiet) 237 printf("%s\t", argv[arg_counter]); 238 for (i = 0; i < error; i += buf[i] + 1) 239 printf("%s%*.*s", i ? "\t" : "", 240 buf[i], buf[i], buf + i + 1); 241 printf("\n"); 242 continue; 243 case EAGET: 244 if (flag_nofollow) 245 error = extattr_get_link(argv[arg_counter], 246 attrnamespace, attrname, NULL, 0); 247 else 248 error = extattr_get_file(argv[arg_counter], 249 attrnamespace, attrname, NULL, 0); 250 if (error < 0) 251 break; 252 mkbuf(&buf, &buflen, error); 253 if (flag_nofollow) 254 error = extattr_get_link(argv[arg_counter], 255 attrnamespace, attrname, buf, buflen); 256 else 257 error = extattr_get_file(argv[arg_counter], 258 attrnamespace, attrname, buf, buflen); 259 if (error < 0) 260 break; 261 if (!flag_quiet) 262 printf("%s\t", argv[arg_counter]); 263 if (flag_string) { 264 mkbuf(&visbuf, &visbuflen, error * 4 + 1); 265 strvisx(visbuf, buf, error, 266 VIS_SAFE | VIS_WHITE); 267 printf("\"%s\"\n", visbuf); 268 continue; 269 } else if (flag_hex) { 270 for (i = 0; i < error; i++) 271 printf("%s%02x", i ? " " : "", 272 buf[i]); 273 printf("\n"); 274 continue; 275 } else { 276 fwrite(buf, buflen, 1, stdout); 277 printf("\n"); 278 continue; 279 } 280 default: 281 break; 282 } 283 if (!flag_quiet) 284 warn("%s: failed", argv[arg_counter]); 285 if (flag_force) 286 continue; 287 return(1); 288 } 289 return (0); 290 } 291