1a068c194SPoul-Henning Kamp /*- 252271f82SRobert Watson * Copyright (c) 2002, 2003 Networks Associates Technology, Inc. 3a068c194SPoul-Henning Kamp * Copyright (c) 2002 Poul-Henning Kamp. 4a068c194SPoul-Henning Kamp * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 5a068c194SPoul-Henning Kamp * All rights reserved. 6a068c194SPoul-Henning Kamp * 7a068c194SPoul-Henning Kamp * This software was developed for the FreeBSD Project by Poul-Henning 8a068c194SPoul-Henning Kamp * Kamp and Network Associates Laboratories, the Security Research Division 9a068c194SPoul-Henning Kamp * of Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 10a068c194SPoul-Henning Kamp * ("CBOSS"), as part of the DARPA CHATS research program 11a068c194SPoul-Henning Kamp * 12a068c194SPoul-Henning Kamp * Redistribution and use in source and binary forms, with or without 13a068c194SPoul-Henning Kamp * modification, are permitted provided that the following conditions 14a068c194SPoul-Henning Kamp * are met: 15a068c194SPoul-Henning Kamp * 1. Redistributions of source code must retain the above copyright 16a068c194SPoul-Henning Kamp * notice, this list of conditions and the following disclaimer. 17a068c194SPoul-Henning Kamp * 2. Redistributions in binary form must reproduce the above copyright 18a068c194SPoul-Henning Kamp * notice, this list of conditions and the following disclaimer in the 19a068c194SPoul-Henning Kamp * documentation and/or other materials provided with the distribution. 20a068c194SPoul-Henning Kamp * 3. The names of the authors may not be used to endorse or promote 21a068c194SPoul-Henning Kamp * products derived from this software without specific prior written 22a068c194SPoul-Henning Kamp * permission. 23a068c194SPoul-Henning Kamp * 24a068c194SPoul-Henning Kamp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 25a068c194SPoul-Henning Kamp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26a068c194SPoul-Henning Kamp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27a068c194SPoul-Henning Kamp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 28a068c194SPoul-Henning Kamp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29a068c194SPoul-Henning Kamp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30a068c194SPoul-Henning Kamp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31a068c194SPoul-Henning Kamp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32a068c194SPoul-Henning Kamp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33a068c194SPoul-Henning Kamp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34a068c194SPoul-Henning Kamp * SUCH DAMAGE. 35a068c194SPoul-Henning Kamp * 36a068c194SPoul-Henning Kamp * $FreeBSD$ 37a068c194SPoul-Henning Kamp */ 38a068c194SPoul-Henning Kamp 39a068c194SPoul-Henning Kamp #include <sys/types.h> 40a068c194SPoul-Henning Kamp #include <sys/uio.h> 41a068c194SPoul-Henning Kamp #include <sys/extattr.h> 42a068c194SPoul-Henning Kamp 437522ecb3SRobert Watson #include <libgen.h> 44a068c194SPoul-Henning Kamp #include <libutil.h> 45a068c194SPoul-Henning Kamp #include <stdio.h> 46a068c194SPoul-Henning Kamp #include <stdlib.h> 47a068c194SPoul-Henning Kamp #include <string.h> 48a068c194SPoul-Henning Kamp #include <unistd.h> 49a068c194SPoul-Henning Kamp #include <vis.h> 50a068c194SPoul-Henning Kamp #include <err.h> 51a068c194SPoul-Henning Kamp #include <errno.h> 52a068c194SPoul-Henning Kamp 53a068c194SPoul-Henning Kamp static enum { EADUNNO, EAGET, EASET, EARM, EALS } what = EADUNNO; 54a068c194SPoul-Henning Kamp 55a068c194SPoul-Henning Kamp static void __dead2 56a068c194SPoul-Henning Kamp usage(void) 57a068c194SPoul-Henning Kamp { 58a068c194SPoul-Henning Kamp 59a068c194SPoul-Henning Kamp switch (what) { 60a068c194SPoul-Henning Kamp case EAGET: 616c3fb112SRobert Watson fprintf(stderr, "usage: getextattr [-fhqsx] attrnamespace"); 62a068c194SPoul-Henning Kamp fprintf(stderr, " attrname filename ...\n"); 63a068c194SPoul-Henning Kamp exit(-1); 64a068c194SPoul-Henning Kamp case EASET: 65cb0187a0SBrian Feldman fprintf(stderr, "usage: setextattr [-fhnq] attrnamespace"); 66a068c194SPoul-Henning Kamp fprintf(stderr, " attrname attrvalue filename ...\n"); 67a068c194SPoul-Henning Kamp exit(-1); 68a068c194SPoul-Henning Kamp case EARM: 696c3fb112SRobert Watson fprintf(stderr, "usage: rmextattr [-fhq] attrnamespace"); 70a068c194SPoul-Henning Kamp fprintf(stderr, " attrname filename ...\n"); 71a068c194SPoul-Henning Kamp exit(-1); 72a068c194SPoul-Henning Kamp case EALS: 736c3fb112SRobert Watson fprintf(stderr, "usage: lsextattr [-fhq] attrnamespace"); 74a068c194SPoul-Henning Kamp fprintf(stderr, " filename ...\n"); 75a068c194SPoul-Henning Kamp exit(-1); 76a068c194SPoul-Henning Kamp case EADUNNO: 77a068c194SPoul-Henning Kamp default: 78a068c194SPoul-Henning Kamp fprintf(stderr, "usage: (getextattr|lsextattr|rmextattr"); 79a068c194SPoul-Henning Kamp fprintf(stderr, "|setextattr)\n"); 80a068c194SPoul-Henning Kamp exit (-1); 81a068c194SPoul-Henning Kamp } 82a068c194SPoul-Henning Kamp } 83a068c194SPoul-Henning Kamp 84a068c194SPoul-Henning Kamp static void 85a068c194SPoul-Henning Kamp mkbuf(char **buf, int *oldlen, int newlen) 86a068c194SPoul-Henning Kamp { 87a068c194SPoul-Henning Kamp 88a068c194SPoul-Henning Kamp if (*oldlen >= newlen) 89a068c194SPoul-Henning Kamp return; 90a068c194SPoul-Henning Kamp if (*buf != NULL) 91a068c194SPoul-Henning Kamp free(*buf); 92a068c194SPoul-Henning Kamp *buf = malloc(newlen); 93a068c194SPoul-Henning Kamp if (*buf == NULL) 94a068c194SPoul-Henning Kamp err(1, "malloc"); 95a068c194SPoul-Henning Kamp *oldlen = newlen; 96a068c194SPoul-Henning Kamp return; 97a068c194SPoul-Henning Kamp } 98a068c194SPoul-Henning Kamp 99a068c194SPoul-Henning Kamp int 100a068c194SPoul-Henning Kamp main(int argc, char *argv[]) 101a068c194SPoul-Henning Kamp { 102a068c194SPoul-Henning Kamp char *buf, *visbuf, *p; 103a068c194SPoul-Henning Kamp 104a068c194SPoul-Henning Kamp const char *options, *attrname; 105878382faSBrian Feldman int buflen, visbuflen, ch, error, i, arg_counter, attrnamespace, 106878382faSBrian Feldman minargc; 107a068c194SPoul-Henning Kamp 108a068c194SPoul-Henning Kamp int flag_force = 0; 1096c3fb112SRobert Watson int flag_nofollow = 0; 110cb0187a0SBrian Feldman int flag_null = 0; 111a068c194SPoul-Henning Kamp int flag_quiet = 0; 112a068c194SPoul-Henning Kamp int flag_string = 0; 113a068c194SPoul-Henning Kamp int flag_hex = 0; 114a068c194SPoul-Henning Kamp 115a068c194SPoul-Henning Kamp visbuflen = buflen = 0; 116a068c194SPoul-Henning Kamp visbuf = buf = NULL; 117a068c194SPoul-Henning Kamp 1187522ecb3SRobert Watson p = basename(argv[0]); 119a068c194SPoul-Henning Kamp if (p == NULL) 120a068c194SPoul-Henning Kamp p = argv[0]; 121a068c194SPoul-Henning Kamp if (!strcmp(p, "getextattr")) { 122a068c194SPoul-Henning Kamp what = EAGET; 1236c3fb112SRobert Watson options = "fhqsx"; 124878382faSBrian Feldman minargc = 3; 125a068c194SPoul-Henning Kamp } else if (!strcmp(p, "setextattr")) { 126a068c194SPoul-Henning Kamp what = EASET; 127cb0187a0SBrian Feldman options = "fhnq"; 128878382faSBrian Feldman minargc = 4; 129a068c194SPoul-Henning Kamp } else if (!strcmp(p, "rmextattr")) { 130a068c194SPoul-Henning Kamp what = EARM; 1316c3fb112SRobert Watson options = "fhq"; 132878382faSBrian Feldman minargc = 3; 133a068c194SPoul-Henning Kamp } else if (!strcmp(p, "lsextattr")) { 134a068c194SPoul-Henning Kamp what = EALS; 1356c3fb112SRobert Watson options = "fhq"; 136878382faSBrian Feldman minargc = 2; 137a068c194SPoul-Henning Kamp } else { 138a068c194SPoul-Henning Kamp usage(); 139a068c194SPoul-Henning Kamp } 140a068c194SPoul-Henning Kamp 141a068c194SPoul-Henning Kamp while ((ch = getopt(argc, argv, options)) != -1) { 142a068c194SPoul-Henning Kamp switch (ch) { 143a068c194SPoul-Henning Kamp case 'f': 144a068c194SPoul-Henning Kamp flag_force = 1; 145a068c194SPoul-Henning Kamp break; 1466c3fb112SRobert Watson case 'h': 1476c3fb112SRobert Watson flag_nofollow = 1; 1486c3fb112SRobert Watson break; 149cb0187a0SBrian Feldman case 'n': 150cb0187a0SBrian Feldman flag_null = 1; 151cb0187a0SBrian Feldman break; 152a068c194SPoul-Henning Kamp case 'q': 153a068c194SPoul-Henning Kamp flag_quiet = 1; 154a068c194SPoul-Henning Kamp break; 155a068c194SPoul-Henning Kamp case 's': 156a068c194SPoul-Henning Kamp flag_string = 1; 157a068c194SPoul-Henning Kamp break; 158a068c194SPoul-Henning Kamp case 'x': 159a068c194SPoul-Henning Kamp flag_hex = 1; 160a068c194SPoul-Henning Kamp break; 161a068c194SPoul-Henning Kamp case '?': 162a068c194SPoul-Henning Kamp default: 163a068c194SPoul-Henning Kamp usage(); 164a068c194SPoul-Henning Kamp } 165a068c194SPoul-Henning Kamp } 166a068c194SPoul-Henning Kamp 167a068c194SPoul-Henning Kamp argc -= optind; 168a068c194SPoul-Henning Kamp argv += optind; 169a068c194SPoul-Henning Kamp 170878382faSBrian Feldman if (argc < minargc) 171a068c194SPoul-Henning Kamp usage(); 172a068c194SPoul-Henning Kamp 173a068c194SPoul-Henning Kamp error = extattr_string_to_namespace(argv[0], &attrnamespace); 174a068c194SPoul-Henning Kamp if (error) 175a068c194SPoul-Henning Kamp err(-1, argv[0]); 176a068c194SPoul-Henning Kamp argc--; argv++; 177a068c194SPoul-Henning Kamp 17852271f82SRobert Watson if (what != EALS) { 179a068c194SPoul-Henning Kamp attrname = argv[0]; 180a068c194SPoul-Henning Kamp argc--; argv++; 18152271f82SRobert Watson } else 18252271f82SRobert Watson attrname = NULL; 183a068c194SPoul-Henning Kamp 184a068c194SPoul-Henning Kamp if (what == EASET) { 185a068c194SPoul-Henning Kamp mkbuf(&buf, &buflen, strlen(argv[0]) + 1); 186a068c194SPoul-Henning Kamp strcpy(buf, argv[0]); 187a068c194SPoul-Henning Kamp argc--; argv++; 188a068c194SPoul-Henning Kamp } 189a068c194SPoul-Henning Kamp 190a068c194SPoul-Henning Kamp for (arg_counter = 0; arg_counter < argc; arg_counter++) { 191a068c194SPoul-Henning Kamp switch (what) { 192a068c194SPoul-Henning Kamp case EARM: 1936c3fb112SRobert Watson if (flag_nofollow) 1946c3fb112SRobert Watson error = extattr_delete_link(argv[arg_counter], 1956c3fb112SRobert Watson attrnamespace, attrname); 1966c3fb112SRobert Watson else 197a068c194SPoul-Henning Kamp error = extattr_delete_file(argv[arg_counter], 198a068c194SPoul-Henning Kamp attrnamespace, attrname); 199a068c194SPoul-Henning Kamp if (error >= 0) 200a068c194SPoul-Henning Kamp continue; 201a068c194SPoul-Henning Kamp break; 202a068c194SPoul-Henning Kamp case EASET: 2036c3fb112SRobert Watson if (flag_nofollow) 2046c3fb112SRobert Watson error = extattr_set_link(argv[arg_counter], 205cb0187a0SBrian Feldman attrnamespace, attrname, buf, 206cb0187a0SBrian Feldman strlen(buf) + flag_null); 2076c3fb112SRobert Watson else 208a068c194SPoul-Henning Kamp error = extattr_set_file(argv[arg_counter], 209cb0187a0SBrian Feldman attrnamespace, attrname, buf, 210cb0187a0SBrian Feldman strlen(buf) + flag_null); 211a068c194SPoul-Henning Kamp if (error >= 0) 212a068c194SPoul-Henning Kamp continue; 213a068c194SPoul-Henning Kamp break; 214a068c194SPoul-Henning Kamp case EALS: 21552271f82SRobert Watson if (flag_nofollow) 21652271f82SRobert Watson error = extattr_list_link(argv[arg_counter], 21752271f82SRobert Watson attrnamespace, NULL, 0); 21852271f82SRobert Watson else 21952271f82SRobert Watson error = extattr_list_file(argv[arg_counter], 22052271f82SRobert Watson attrnamespace, NULL, 0); 22152271f82SRobert Watson if (error < 0) 22252271f82SRobert Watson break; 22352271f82SRobert Watson mkbuf(&buf, &buflen, error); 22452271f82SRobert Watson if (flag_nofollow) 22552271f82SRobert Watson error = extattr_list_link(argv[arg_counter], 22652271f82SRobert Watson attrnamespace, buf, buflen); 22752271f82SRobert Watson else 22852271f82SRobert Watson error = extattr_list_file(argv[arg_counter], 22952271f82SRobert Watson attrnamespace, buf, buflen); 23052271f82SRobert Watson if (error < 0) 23152271f82SRobert Watson break; 23252271f82SRobert Watson if (!flag_quiet) 23352271f82SRobert Watson printf("%s\t", argv[arg_counter]); 23452271f82SRobert Watson for (i = 0; i < error; i += buf[i] + 1) 23552271f82SRobert Watson printf("%s%*.*s", i ? "\t" : "", 23652271f82SRobert Watson buf[i], buf[i], buf + i + 1); 23752271f82SRobert Watson printf("\n"); 23852271f82SRobert Watson continue; 239a068c194SPoul-Henning Kamp case EAGET: 2406c3fb112SRobert Watson if (flag_nofollow) 2416c3fb112SRobert Watson error = extattr_get_link(argv[arg_counter], 2426c3fb112SRobert Watson attrnamespace, attrname, NULL, 0); 2436c3fb112SRobert Watson else 244a068c194SPoul-Henning Kamp error = extattr_get_file(argv[arg_counter], 245a068c194SPoul-Henning Kamp attrnamespace, attrname, NULL, 0); 246a068c194SPoul-Henning Kamp if (error < 0) 247a068c194SPoul-Henning Kamp break; 248a068c194SPoul-Henning Kamp mkbuf(&buf, &buflen, error); 2496c3fb112SRobert Watson if (flag_nofollow) 2506c3fb112SRobert Watson error = extattr_get_link(argv[arg_counter], 2516c3fb112SRobert Watson attrnamespace, attrname, buf, buflen); 2526c3fb112SRobert Watson else 253a068c194SPoul-Henning Kamp error = extattr_get_file(argv[arg_counter], 254a068c194SPoul-Henning Kamp attrnamespace, attrname, buf, buflen); 255a068c194SPoul-Henning Kamp if (error < 0) 256a068c194SPoul-Henning Kamp break; 257a068c194SPoul-Henning Kamp if (!flag_quiet) 258a068c194SPoul-Henning Kamp printf("%s\t", argv[arg_counter]); 259a068c194SPoul-Henning Kamp if (flag_string) { 260a068c194SPoul-Henning Kamp mkbuf(&visbuf, &visbuflen, error * 4 + 1); 261a068c194SPoul-Henning Kamp strvisx(visbuf, buf, error, 262a068c194SPoul-Henning Kamp VIS_SAFE | VIS_WHITE); 263a068c194SPoul-Henning Kamp printf("\"%s\"\n", visbuf); 264a068c194SPoul-Henning Kamp continue; 265a068c194SPoul-Henning Kamp } else if (flag_hex) { 266a068c194SPoul-Henning Kamp for (i = 0; i < error; i++) 267a068c194SPoul-Henning Kamp printf("%s%02x", i ? " " : "", 268a068c194SPoul-Henning Kamp buf[i]); 269a068c194SPoul-Henning Kamp printf("\n"); 270a068c194SPoul-Henning Kamp continue; 271a068c194SPoul-Henning Kamp } else { 272a068c194SPoul-Henning Kamp fwrite(buf, buflen, 1, stdout); 273a068c194SPoul-Henning Kamp printf("\n"); 274a068c194SPoul-Henning Kamp continue; 275a068c194SPoul-Henning Kamp } 276a068c194SPoul-Henning Kamp default: 277a068c194SPoul-Henning Kamp break; 278a068c194SPoul-Henning Kamp } 279a068c194SPoul-Henning Kamp if (!flag_quiet) 280a068c194SPoul-Henning Kamp warn("%s: failed", argv[arg_counter]); 281a068c194SPoul-Henning Kamp if (flag_force) 282a068c194SPoul-Henning Kamp continue; 283a068c194SPoul-Henning Kamp return(1); 284a068c194SPoul-Henning Kamp } 285a068c194SPoul-Henning Kamp return (0); 286a068c194SPoul-Henning Kamp } 287