xref: /freebsd/usr.sbin/extattr/rmextattr.c (revision 52271f82d65caa9870aa3d9fcf7307fe504ae059)
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