1 /* $NetBSD: getextattr.c,v 1.3 2006/06/17 08:32:42 elad 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 options = NULL; 124 minargc = 0; 125 visbuflen = buflen = 0; 126 visbuf = buf = NULL; 127 128 p = getprogname(); 129 if (strcmp(p, "getextattr") == 0) { 130 what = EAGET; 131 options = "fhqsx"; 132 minargc = 3; 133 } else if (strcmp(p, "setextattr") == 0) { 134 what = EASET; 135 options = "fhnq"; 136 minargc = 4; 137 } else if (strcmp(p, "rmextattr") == 0) { 138 what = EARM; 139 options = "fhq"; 140 minargc = 3; 141 } else if (strcmp(p, "lsextattr") == 0) { 142 what = EALS; 143 options = "fhq"; 144 minargc = 2; 145 } else 146 usage(); 147 148 while ((ch = getopt(argc, argv, options)) != -1) { 149 switch (ch) { 150 case 'f': 151 flag_force = 1; 152 break; 153 case 'h': 154 flag_nofollow = 1; 155 break; 156 case 'n': 157 flag_null = 1; 158 break; 159 case 'q': 160 flag_quiet = 1; 161 break; 162 case 's': 163 flag_string = 1; 164 break; 165 case 'x': 166 flag_hex = 1; 167 break; 168 default: 169 usage(); 170 } 171 } 172 173 argc -= optind; 174 argv += optind; 175 176 if (argc < minargc) 177 usage(); 178 179 error = extattr_string_to_namespace(argv[0], &attrnamespace); 180 if (error) 181 err(1, argv[0]); 182 argc--; argv++; 183 184 if (what != EALS) { 185 attrname = argv[0]; 186 argc--; argv++; 187 } else 188 attrname = NULL; 189 190 if (what == EASET) { 191 mkbuf(&buf, &buflen, strlen(argv[0]) + 1); 192 strcpy(buf, argv[0]); /* safe */ 193 argc--; argv++; 194 } 195 196 for (arg_counter = 0; arg_counter < argc; arg_counter++) { 197 switch (what) { 198 case EARM: 199 if (flag_nofollow) 200 error = extattr_delete_link(argv[arg_counter], 201 attrnamespace, attrname); 202 else 203 error = extattr_delete_file(argv[arg_counter], 204 attrnamespace, attrname); 205 if (error >= 0) 206 continue; 207 break; 208 case EASET: 209 if (flag_nofollow) 210 error = extattr_set_link(argv[arg_counter], 211 attrnamespace, attrname, buf, 212 strlen(buf) + flag_null); 213 else 214 error = extattr_set_file(argv[arg_counter], 215 attrnamespace, attrname, buf, 216 strlen(buf) + flag_null); 217 if (error >= 0) 218 continue; 219 break; 220 case EALS: 221 if (flag_nofollow) 222 error = extattr_list_link(argv[arg_counter], 223 attrnamespace, NULL, 0); 224 else 225 error = extattr_list_file(argv[arg_counter], 226 attrnamespace, NULL, 0); 227 if (error < 0) 228 break; 229 mkbuf(&buf, &buflen, error); 230 if (flag_nofollow) 231 error = extattr_list_link(argv[arg_counter], 232 attrnamespace, buf, buflen); 233 else 234 error = extattr_list_file(argv[arg_counter], 235 attrnamespace, buf, buflen); 236 if (error < 0) 237 break; 238 if (!flag_quiet) 239 printf("%s\t", argv[arg_counter]); 240 for (i = 0; i < error; i += buf[i] + 1) 241 printf("%s%*.*s", i ? "\t" : "", 242 buf[i], buf[i], buf + i + 1); 243 printf("\n"); 244 continue; 245 case EAGET: 246 if (flag_nofollow) 247 error = extattr_get_link(argv[arg_counter], 248 attrnamespace, attrname, NULL, 0); 249 else 250 error = extattr_get_file(argv[arg_counter], 251 attrnamespace, attrname, NULL, 0); 252 if (error < 0) 253 break; 254 mkbuf(&buf, &buflen, error); 255 if (flag_nofollow) 256 error = extattr_get_link(argv[arg_counter], 257 attrnamespace, attrname, buf, buflen); 258 else 259 error = extattr_get_file(argv[arg_counter], 260 attrnamespace, attrname, buf, buflen); 261 if (error < 0) 262 break; 263 if (!flag_quiet) 264 printf("%s\t", argv[arg_counter]); 265 if (flag_string) { 266 mkbuf(&visbuf, &visbuflen, error * 4 + 1); 267 strvisx(visbuf, buf, error, 268 VIS_SAFE | VIS_WHITE); 269 printf("\"%s\"\n", visbuf); 270 continue; 271 } else if (flag_hex) { 272 for (i = 0; i < error; i++) 273 printf("%s%02x", i ? " " : "", 274 buf[i]); 275 printf("\n"); 276 continue; 277 } else { 278 fwrite(buf, buflen, 1, stdout); 279 printf("\n"); 280 continue; 281 } 282 default: 283 break; 284 } 285 if (!flag_quiet) 286 warn("%s: failed", argv[arg_counter]); 287 if (flag_force) 288 continue; 289 return(1); 290 } 291 return (0); 292 } 293