xref: /aosp_15_r20/external/e2fsprogs/debugfs/xattrs.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker  * xattrs.c --- Modify extended attributes via debugfs.
3*6a54128fSAndroid Build Coastguard Worker  *
4*6a54128fSAndroid Build Coastguard Worker  * Copyright (C) 2014 Oracle.  This file may be redistributed
5*6a54128fSAndroid Build Coastguard Worker  * under the terms of the GNU Public License.
6*6a54128fSAndroid Build Coastguard Worker  */
7*6a54128fSAndroid Build Coastguard Worker 
8*6a54128fSAndroid Build Coastguard Worker #include "config.h"
9*6a54128fSAndroid Build Coastguard Worker #include <stdio.h>
10*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_GETOPT_H
11*6a54128fSAndroid Build Coastguard Worker #include <getopt.h>
12*6a54128fSAndroid Build Coastguard Worker #else
13*6a54128fSAndroid Build Coastguard Worker extern int optind;
14*6a54128fSAndroid Build Coastguard Worker extern char *optarg;
15*6a54128fSAndroid Build Coastguard Worker #endif
16*6a54128fSAndroid Build Coastguard Worker #include <ctype.h>
17*6a54128fSAndroid Build Coastguard Worker #include "support/cstring.h"
18*6a54128fSAndroid Build Coastguard Worker 
19*6a54128fSAndroid Build Coastguard Worker #include "debugfs.h"
20*6a54128fSAndroid Build Coastguard Worker 
21*6a54128fSAndroid Build Coastguard Worker #define PRINT_XATTR_HEX		0x01
22*6a54128fSAndroid Build Coastguard Worker #define PRINT_XATTR_RAW		0x02
23*6a54128fSAndroid Build Coastguard Worker #define PRINT_XATTR_C		0x04
24*6a54128fSAndroid Build Coastguard Worker #define PRINT_XATTR_STATFMT	0x08
25*6a54128fSAndroid Build Coastguard Worker #define PRINT_XATTR_NOQUOTES	0x10
26*6a54128fSAndroid Build Coastguard Worker 
27*6a54128fSAndroid Build Coastguard Worker /* Dump extended attributes */
print_xattr_hex(FILE * f,const char * str,int len)28*6a54128fSAndroid Build Coastguard Worker static void print_xattr_hex(FILE *f, const char *str, int len)
29*6a54128fSAndroid Build Coastguard Worker {
30*6a54128fSAndroid Build Coastguard Worker 	int i;
31*6a54128fSAndroid Build Coastguard Worker 
32*6a54128fSAndroid Build Coastguard Worker 	for (i = 0; i < len; i++)
33*6a54128fSAndroid Build Coastguard Worker 		fprintf(f, "%02x ", (unsigned char)str[i]);
34*6a54128fSAndroid Build Coastguard Worker }
35*6a54128fSAndroid Build Coastguard Worker 
36*6a54128fSAndroid Build Coastguard Worker /* Dump extended attributes */
print_xattr_string(FILE * f,const char * str,int len,int flags)37*6a54128fSAndroid Build Coastguard Worker static void print_xattr_string(FILE *f, const char *str, int len, int flags)
38*6a54128fSAndroid Build Coastguard Worker {
39*6a54128fSAndroid Build Coastguard Worker 	int printable = 0;
40*6a54128fSAndroid Build Coastguard Worker 	int i;
41*6a54128fSAndroid Build Coastguard Worker 
42*6a54128fSAndroid Build Coastguard Worker 	if (flags & PRINT_XATTR_RAW) {
43*6a54128fSAndroid Build Coastguard Worker 		fwrite(str, len, 1, f);
44*6a54128fSAndroid Build Coastguard Worker 		return;
45*6a54128fSAndroid Build Coastguard Worker 	}
46*6a54128fSAndroid Build Coastguard Worker 
47*6a54128fSAndroid Build Coastguard Worker 	if ((flags & PRINT_XATTR_C) == 0) {
48*6a54128fSAndroid Build Coastguard Worker 		/* check: is string "printable enough?" */
49*6a54128fSAndroid Build Coastguard Worker 		for (i = 0; i < len; i++)
50*6a54128fSAndroid Build Coastguard Worker 			if (isprint(str[i]))
51*6a54128fSAndroid Build Coastguard Worker 				printable++;
52*6a54128fSAndroid Build Coastguard Worker 
53*6a54128fSAndroid Build Coastguard Worker 		if (printable <= len*7/8)
54*6a54128fSAndroid Build Coastguard Worker 			flags |= PRINT_XATTR_HEX;
55*6a54128fSAndroid Build Coastguard Worker 	}
56*6a54128fSAndroid Build Coastguard Worker 
57*6a54128fSAndroid Build Coastguard Worker 	if (flags & PRINT_XATTR_HEX) {
58*6a54128fSAndroid Build Coastguard Worker 		print_xattr_hex(f, str, len);
59*6a54128fSAndroid Build Coastguard Worker 	} else {
60*6a54128fSAndroid Build Coastguard Worker 		if ((flags & PRINT_XATTR_NOQUOTES) == 0)
61*6a54128fSAndroid Build Coastguard Worker 			fputc('\"', f);
62*6a54128fSAndroid Build Coastguard Worker 		print_c_string(f, str, len);
63*6a54128fSAndroid Build Coastguard Worker 		if ((flags & PRINT_XATTR_NOQUOTES) == 0)
64*6a54128fSAndroid Build Coastguard Worker 			fputc('\"', f);
65*6a54128fSAndroid Build Coastguard Worker 	}
66*6a54128fSAndroid Build Coastguard Worker }
67*6a54128fSAndroid Build Coastguard Worker 
print_xattr(FILE * f,char * name,char * value,size_t value_len,int print_flags)68*6a54128fSAndroid Build Coastguard Worker static void print_xattr(FILE *f, char *name, char *value, size_t value_len,
69*6a54128fSAndroid Build Coastguard Worker 			int print_flags)
70*6a54128fSAndroid Build Coastguard Worker {
71*6a54128fSAndroid Build Coastguard Worker 	print_xattr_string(f, name, strlen(name), PRINT_XATTR_NOQUOTES);
72*6a54128fSAndroid Build Coastguard Worker 	fprintf(f, " (%zu)", value_len);
73*6a54128fSAndroid Build Coastguard Worker 	if ((print_flags & PRINT_XATTR_STATFMT) &&
74*6a54128fSAndroid Build Coastguard Worker 	    (strcmp(name, "system.data") == 0))
75*6a54128fSAndroid Build Coastguard Worker 		value_len = 0;
76*6a54128fSAndroid Build Coastguard Worker 	if (value_len != 0 &&
77*6a54128fSAndroid Build Coastguard Worker 	    (!(print_flags & PRINT_XATTR_STATFMT) || (value_len < 40))) {
78*6a54128fSAndroid Build Coastguard Worker 		fprintf(f, " = ");
79*6a54128fSAndroid Build Coastguard Worker 		print_xattr_string(f, value, value_len, print_flags);
80*6a54128fSAndroid Build Coastguard Worker 	}
81*6a54128fSAndroid Build Coastguard Worker 	fputc('\n', f);
82*6a54128fSAndroid Build Coastguard Worker }
83*6a54128fSAndroid Build Coastguard Worker 
dump_attr(char * name,char * value,size_t value_len,void * data)84*6a54128fSAndroid Build Coastguard Worker static int dump_attr(char *name, char *value, size_t value_len, void *data)
85*6a54128fSAndroid Build Coastguard Worker {
86*6a54128fSAndroid Build Coastguard Worker 	FILE *out = data;
87*6a54128fSAndroid Build Coastguard Worker 
88*6a54128fSAndroid Build Coastguard Worker 	fprintf(out, "  ");
89*6a54128fSAndroid Build Coastguard Worker 	print_xattr(out, name, value, value_len, PRINT_XATTR_STATFMT);
90*6a54128fSAndroid Build Coastguard Worker 	return 0;
91*6a54128fSAndroid Build Coastguard Worker }
92*6a54128fSAndroid Build Coastguard Worker 
dump_inode_attributes(FILE * out,ext2_ino_t ino)93*6a54128fSAndroid Build Coastguard Worker void dump_inode_attributes(FILE *out, ext2_ino_t ino)
94*6a54128fSAndroid Build Coastguard Worker {
95*6a54128fSAndroid Build Coastguard Worker 	struct ext2_xattr_handle *h;
96*6a54128fSAndroid Build Coastguard Worker 	size_t sz;
97*6a54128fSAndroid Build Coastguard Worker 	errcode_t err;
98*6a54128fSAndroid Build Coastguard Worker 
99*6a54128fSAndroid Build Coastguard Worker 	err = ext2fs_xattrs_open(current_fs, ino, &h);
100*6a54128fSAndroid Build Coastguard Worker 	if (err)
101*6a54128fSAndroid Build Coastguard Worker 		return;
102*6a54128fSAndroid Build Coastguard Worker 
103*6a54128fSAndroid Build Coastguard Worker 	err = ext2fs_xattrs_read(h);
104*6a54128fSAndroid Build Coastguard Worker 	if (err)
105*6a54128fSAndroid Build Coastguard Worker 		goto out;
106*6a54128fSAndroid Build Coastguard Worker 
107*6a54128fSAndroid Build Coastguard Worker 	err = ext2fs_xattrs_count(h, &sz);
108*6a54128fSAndroid Build Coastguard Worker 	if (err || sz == 0)
109*6a54128fSAndroid Build Coastguard Worker 		goto out;
110*6a54128fSAndroid Build Coastguard Worker 
111*6a54128fSAndroid Build Coastguard Worker 	fprintf(out, "Extended attributes:\n");
112*6a54128fSAndroid Build Coastguard Worker 	err = ext2fs_xattrs_iterate(h, dump_attr, out);
113*6a54128fSAndroid Build Coastguard Worker 	if (err)
114*6a54128fSAndroid Build Coastguard Worker 		goto out;
115*6a54128fSAndroid Build Coastguard Worker 
116*6a54128fSAndroid Build Coastguard Worker out:
117*6a54128fSAndroid Build Coastguard Worker 	err = ext2fs_xattrs_close(&h);
118*6a54128fSAndroid Build Coastguard Worker }
119*6a54128fSAndroid Build Coastguard Worker 
do_list_xattr(int argc,char ** argv,int sci_idx EXT2FS_ATTR ((unused)),void * infop EXT2FS_ATTR ((unused)))120*6a54128fSAndroid Build Coastguard Worker void do_list_xattr(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)),
121*6a54128fSAndroid Build Coastguard Worker 		   void *infop EXT2FS_ATTR((unused)))
122*6a54128fSAndroid Build Coastguard Worker {
123*6a54128fSAndroid Build Coastguard Worker 	ext2_ino_t ino;
124*6a54128fSAndroid Build Coastguard Worker 
125*6a54128fSAndroid Build Coastguard Worker 	if (argc != 2) {
126*6a54128fSAndroid Build Coastguard Worker 		printf("%s: Usage: %s <file>\n", argv[0],
127*6a54128fSAndroid Build Coastguard Worker 		       argv[0]);
128*6a54128fSAndroid Build Coastguard Worker 		return;
129*6a54128fSAndroid Build Coastguard Worker 	}
130*6a54128fSAndroid Build Coastguard Worker 
131*6a54128fSAndroid Build Coastguard Worker 	if (check_fs_open(argv[0]))
132*6a54128fSAndroid Build Coastguard Worker 		return;
133*6a54128fSAndroid Build Coastguard Worker 
134*6a54128fSAndroid Build Coastguard Worker 	ino = string_to_inode(argv[1]);
135*6a54128fSAndroid Build Coastguard Worker 	if (!ino)
136*6a54128fSAndroid Build Coastguard Worker 		return;
137*6a54128fSAndroid Build Coastguard Worker 
138*6a54128fSAndroid Build Coastguard Worker 	dump_inode_attributes(stdout, ino);
139*6a54128fSAndroid Build Coastguard Worker }
140*6a54128fSAndroid Build Coastguard Worker 
do_get_xattr(int argc,char ** argv,int sci_idx EXT2FS_ATTR ((unused)),void * infop EXT2FS_ATTR ((unused)))141*6a54128fSAndroid Build Coastguard Worker void do_get_xattr(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)),
142*6a54128fSAndroid Build Coastguard Worker 		  void *infop EXT2FS_ATTR((unused)))
143*6a54128fSAndroid Build Coastguard Worker {
144*6a54128fSAndroid Build Coastguard Worker 	ext2_ino_t ino;
145*6a54128fSAndroid Build Coastguard Worker 	struct ext2_xattr_handle *h;
146*6a54128fSAndroid Build Coastguard Worker 	FILE *fp = NULL;
147*6a54128fSAndroid Build Coastguard Worker 	char *buf = NULL;
148*6a54128fSAndroid Build Coastguard Worker 	size_t buflen;
149*6a54128fSAndroid Build Coastguard Worker 	int i;
150*6a54128fSAndroid Build Coastguard Worker 	int print_flags = 0;
151*6a54128fSAndroid Build Coastguard Worker 	unsigned int handle_flags = 0;
152*6a54128fSAndroid Build Coastguard Worker 	errcode_t err;
153*6a54128fSAndroid Build Coastguard Worker 
154*6a54128fSAndroid Build Coastguard Worker 	reset_getopt();
155*6a54128fSAndroid Build Coastguard Worker 	while ((i = getopt(argc, argv, "Cf:rxV")) != -1) {
156*6a54128fSAndroid Build Coastguard Worker 		switch (i) {
157*6a54128fSAndroid Build Coastguard Worker 		case 'f':
158*6a54128fSAndroid Build Coastguard Worker 			if (fp)
159*6a54128fSAndroid Build Coastguard Worker 				fclose(fp);
160*6a54128fSAndroid Build Coastguard Worker 			fp = fopen(optarg, "w");
161*6a54128fSAndroid Build Coastguard Worker 			if (fp == NULL) {
162*6a54128fSAndroid Build Coastguard Worker 				perror(optarg);
163*6a54128fSAndroid Build Coastguard Worker 				return;
164*6a54128fSAndroid Build Coastguard Worker 			}
165*6a54128fSAndroid Build Coastguard Worker 			break;
166*6a54128fSAndroid Build Coastguard Worker 		case 'r':
167*6a54128fSAndroid Build Coastguard Worker 			handle_flags |= XATTR_HANDLE_FLAG_RAW;
168*6a54128fSAndroid Build Coastguard Worker 			break;
169*6a54128fSAndroid Build Coastguard Worker 		case 'x':
170*6a54128fSAndroid Build Coastguard Worker 			print_flags |= PRINT_XATTR_HEX;
171*6a54128fSAndroid Build Coastguard Worker 			break;
172*6a54128fSAndroid Build Coastguard Worker 		case 'V':
173*6a54128fSAndroid Build Coastguard Worker 			print_flags |= PRINT_XATTR_RAW|
174*6a54128fSAndroid Build Coastguard Worker 				PRINT_XATTR_NOQUOTES;
175*6a54128fSAndroid Build Coastguard Worker 			break;
176*6a54128fSAndroid Build Coastguard Worker 		case 'C':
177*6a54128fSAndroid Build Coastguard Worker 			print_flags |= PRINT_XATTR_C;
178*6a54128fSAndroid Build Coastguard Worker 			break;
179*6a54128fSAndroid Build Coastguard Worker 		default:
180*6a54128fSAndroid Build Coastguard Worker 			goto usage;
181*6a54128fSAndroid Build Coastguard Worker 		}
182*6a54128fSAndroid Build Coastguard Worker 	}
183*6a54128fSAndroid Build Coastguard Worker 
184*6a54128fSAndroid Build Coastguard Worker 	if (optind != argc - 2) {
185*6a54128fSAndroid Build Coastguard Worker 	usage:
186*6a54128fSAndroid Build Coastguard Worker 		printf("%s: Usage: %s [-f outfile]|[-xVC] [-r] <file> <attr>\n",
187*6a54128fSAndroid Build Coastguard Worker 			       argv[0], argv[0]);
188*6a54128fSAndroid Build Coastguard Worker 
189*6a54128fSAndroid Build Coastguard Worker 		goto out2;
190*6a54128fSAndroid Build Coastguard Worker 	}
191*6a54128fSAndroid Build Coastguard Worker 
192*6a54128fSAndroid Build Coastguard Worker 	if (check_fs_open(argv[0]))
193*6a54128fSAndroid Build Coastguard Worker 		goto out2;
194*6a54128fSAndroid Build Coastguard Worker 
195*6a54128fSAndroid Build Coastguard Worker 	ino = string_to_inode(argv[optind]);
196*6a54128fSAndroid Build Coastguard Worker 	if (!ino)
197*6a54128fSAndroid Build Coastguard Worker 		goto out2;
198*6a54128fSAndroid Build Coastguard Worker 
199*6a54128fSAndroid Build Coastguard Worker 	err = ext2fs_xattrs_open(current_fs, ino, &h);
200*6a54128fSAndroid Build Coastguard Worker 	if (err)
201*6a54128fSAndroid Build Coastguard Worker 		goto out2;
202*6a54128fSAndroid Build Coastguard Worker 
203*6a54128fSAndroid Build Coastguard Worker 	err = ext2fs_xattrs_flags(h, &handle_flags, NULL);
204*6a54128fSAndroid Build Coastguard Worker 	if (err)
205*6a54128fSAndroid Build Coastguard Worker 		goto out;
206*6a54128fSAndroid Build Coastguard Worker 
207*6a54128fSAndroid Build Coastguard Worker 	err = ext2fs_xattrs_read(h);
208*6a54128fSAndroid Build Coastguard Worker 	if (err)
209*6a54128fSAndroid Build Coastguard Worker 		goto out;
210*6a54128fSAndroid Build Coastguard Worker 
211*6a54128fSAndroid Build Coastguard Worker 	err = ext2fs_xattr_get(h, argv[optind + 1], (void **)&buf, &buflen);
212*6a54128fSAndroid Build Coastguard Worker 	if (err)
213*6a54128fSAndroid Build Coastguard Worker 		goto out;
214*6a54128fSAndroid Build Coastguard Worker 
215*6a54128fSAndroid Build Coastguard Worker 	if (fp) {
216*6a54128fSAndroid Build Coastguard Worker 		fwrite(buf, buflen, 1, fp);
217*6a54128fSAndroid Build Coastguard Worker 	} else {
218*6a54128fSAndroid Build Coastguard Worker 		if (print_flags & PRINT_XATTR_RAW) {
219*6a54128fSAndroid Build Coastguard Worker 			if (print_flags & (PRINT_XATTR_HEX|PRINT_XATTR_C))
220*6a54128fSAndroid Build Coastguard Worker 				print_flags &= ~PRINT_XATTR_RAW;
221*6a54128fSAndroid Build Coastguard Worker 			print_xattr_string(stdout, buf, buflen, print_flags);
222*6a54128fSAndroid Build Coastguard Worker 		} else {
223*6a54128fSAndroid Build Coastguard Worker 			print_xattr(stdout, argv[optind + 1],
224*6a54128fSAndroid Build Coastguard Worker 				    buf, buflen, print_flags);
225*6a54128fSAndroid Build Coastguard Worker 		}
226*6a54128fSAndroid Build Coastguard Worker 		printf("\n");
227*6a54128fSAndroid Build Coastguard Worker 	}
228*6a54128fSAndroid Build Coastguard Worker 
229*6a54128fSAndroid Build Coastguard Worker 	ext2fs_free_mem(&buf);
230*6a54128fSAndroid Build Coastguard Worker out:
231*6a54128fSAndroid Build Coastguard Worker 	ext2fs_xattrs_close(&h);
232*6a54128fSAndroid Build Coastguard Worker 	if (err)
233*6a54128fSAndroid Build Coastguard Worker 		com_err(argv[0], err, "while getting extended attribute");
234*6a54128fSAndroid Build Coastguard Worker out2:
235*6a54128fSAndroid Build Coastguard Worker 	if (fp)
236*6a54128fSAndroid Build Coastguard Worker 		fclose(fp);
237*6a54128fSAndroid Build Coastguard Worker }
238*6a54128fSAndroid Build Coastguard Worker 
do_set_xattr(int argc,char ** argv,int sci_idx EXT2FS_ATTR ((unused)),void * infop EXT2FS_ATTR ((unused)))239*6a54128fSAndroid Build Coastguard Worker void do_set_xattr(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)),
240*6a54128fSAndroid Build Coastguard Worker 		  void *infop EXT2FS_ATTR((unused)))
241*6a54128fSAndroid Build Coastguard Worker {
242*6a54128fSAndroid Build Coastguard Worker 	ext2_ino_t ino;
243*6a54128fSAndroid Build Coastguard Worker 	struct ext2_xattr_handle *h;
244*6a54128fSAndroid Build Coastguard Worker 	FILE *fp = NULL;
245*6a54128fSAndroid Build Coastguard Worker 	char *buf = NULL;
246*6a54128fSAndroid Build Coastguard Worker 	size_t buflen;
247*6a54128fSAndroid Build Coastguard Worker 	unsigned int handle_flags = 0;
248*6a54128fSAndroid Build Coastguard Worker 	int i;
249*6a54128fSAndroid Build Coastguard Worker 	errcode_t err;
250*6a54128fSAndroid Build Coastguard Worker 
251*6a54128fSAndroid Build Coastguard Worker 	reset_getopt();
252*6a54128fSAndroid Build Coastguard Worker 	while ((i = getopt(argc, argv, "f:r")) != -1) {
253*6a54128fSAndroid Build Coastguard Worker 		switch (i) {
254*6a54128fSAndroid Build Coastguard Worker 		case 'f':
255*6a54128fSAndroid Build Coastguard Worker 			if (fp)
256*6a54128fSAndroid Build Coastguard Worker 				fclose(fp);
257*6a54128fSAndroid Build Coastguard Worker 			fp = fopen(optarg, "r");
258*6a54128fSAndroid Build Coastguard Worker 			if (fp == NULL) {
259*6a54128fSAndroid Build Coastguard Worker 				perror(optarg);
260*6a54128fSAndroid Build Coastguard Worker 				return;
261*6a54128fSAndroid Build Coastguard Worker 			}
262*6a54128fSAndroid Build Coastguard Worker 			break;
263*6a54128fSAndroid Build Coastguard Worker 		case 'r':
264*6a54128fSAndroid Build Coastguard Worker 			handle_flags |= XATTR_HANDLE_FLAG_RAW;
265*6a54128fSAndroid Build Coastguard Worker 			break;
266*6a54128fSAndroid Build Coastguard Worker 		default:
267*6a54128fSAndroid Build Coastguard Worker 			goto print_usage;
268*6a54128fSAndroid Build Coastguard Worker 		}
269*6a54128fSAndroid Build Coastguard Worker 	}
270*6a54128fSAndroid Build Coastguard Worker 
271*6a54128fSAndroid Build Coastguard Worker 	if (!(fp && optind == argc - 2) && !(!fp && optind == argc - 3)) {
272*6a54128fSAndroid Build Coastguard Worker 	print_usage:
273*6a54128fSAndroid Build Coastguard Worker 		printf("Usage:\t%s [-r] <file> <attr> <value>\n", argv[0]);
274*6a54128fSAndroid Build Coastguard Worker 		printf("\t%s -f <value_file> [-r] <file> <attr>\n", argv[0]);
275*6a54128fSAndroid Build Coastguard Worker 		goto out2;
276*6a54128fSAndroid Build Coastguard Worker 	}
277*6a54128fSAndroid Build Coastguard Worker 
278*6a54128fSAndroid Build Coastguard Worker 	if (check_fs_open(argv[0]))
279*6a54128fSAndroid Build Coastguard Worker 		goto out2;
280*6a54128fSAndroid Build Coastguard Worker 	if (check_fs_read_write(argv[0]))
281*6a54128fSAndroid Build Coastguard Worker 		goto out2;
282*6a54128fSAndroid Build Coastguard Worker 	if (check_fs_bitmaps(argv[0]))
283*6a54128fSAndroid Build Coastguard Worker 		goto out2;
284*6a54128fSAndroid Build Coastguard Worker 
285*6a54128fSAndroid Build Coastguard Worker 	ino = string_to_inode(argv[optind]);
286*6a54128fSAndroid Build Coastguard Worker 	if (!ino)
287*6a54128fSAndroid Build Coastguard Worker 		goto out2;
288*6a54128fSAndroid Build Coastguard Worker 
289*6a54128fSAndroid Build Coastguard Worker 	err = ext2fs_xattrs_open(current_fs, ino, &h);
290*6a54128fSAndroid Build Coastguard Worker 	if (err)
291*6a54128fSAndroid Build Coastguard Worker 		goto out2;
292*6a54128fSAndroid Build Coastguard Worker 
293*6a54128fSAndroid Build Coastguard Worker 	err = ext2fs_xattrs_flags(h, &handle_flags, NULL);
294*6a54128fSAndroid Build Coastguard Worker 	if (err)
295*6a54128fSAndroid Build Coastguard Worker 		goto out;
296*6a54128fSAndroid Build Coastguard Worker 
297*6a54128fSAndroid Build Coastguard Worker 	err = ext2fs_xattrs_read(h);
298*6a54128fSAndroid Build Coastguard Worker 	if (err)
299*6a54128fSAndroid Build Coastguard Worker 		goto out;
300*6a54128fSAndroid Build Coastguard Worker 
301*6a54128fSAndroid Build Coastguard Worker 	if (fp) {
302*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_get_mem(current_fs->blocksize, &buf);
303*6a54128fSAndroid Build Coastguard Worker 		if (err)
304*6a54128fSAndroid Build Coastguard Worker 			goto out;
305*6a54128fSAndroid Build Coastguard Worker 		buflen = fread(buf, 1, current_fs->blocksize, fp);
306*6a54128fSAndroid Build Coastguard Worker 	} else {
307*6a54128fSAndroid Build Coastguard Worker 		buf = argv[optind + 2];
308*6a54128fSAndroid Build Coastguard Worker 		buflen = parse_c_string(buf);
309*6a54128fSAndroid Build Coastguard Worker 	}
310*6a54128fSAndroid Build Coastguard Worker 
311*6a54128fSAndroid Build Coastguard Worker 	err = ext2fs_xattr_set(h, argv[optind + 1], buf, buflen);
312*6a54128fSAndroid Build Coastguard Worker out:
313*6a54128fSAndroid Build Coastguard Worker 	ext2fs_xattrs_close(&h);
314*6a54128fSAndroid Build Coastguard Worker 	if (err)
315*6a54128fSAndroid Build Coastguard Worker 		com_err(argv[0], err, "while setting extended attribute");
316*6a54128fSAndroid Build Coastguard Worker out2:
317*6a54128fSAndroid Build Coastguard Worker 	if (fp) {
318*6a54128fSAndroid Build Coastguard Worker 		fclose(fp);
319*6a54128fSAndroid Build Coastguard Worker 		ext2fs_free_mem(&buf);
320*6a54128fSAndroid Build Coastguard Worker 	}
321*6a54128fSAndroid Build Coastguard Worker }
322*6a54128fSAndroid Build Coastguard Worker 
do_rm_xattr(int argc,char ** argv,int sci_idx EXT2FS_ATTR ((unused)),void * infop EXT2FS_ATTR ((unused)))323*6a54128fSAndroid Build Coastguard Worker void do_rm_xattr(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)),
324*6a54128fSAndroid Build Coastguard Worker 		 void *infop EXT2FS_ATTR((unused)))
325*6a54128fSAndroid Build Coastguard Worker {
326*6a54128fSAndroid Build Coastguard Worker 	ext2_ino_t ino;
327*6a54128fSAndroid Build Coastguard Worker 	struct ext2_xattr_handle *h;
328*6a54128fSAndroid Build Coastguard Worker 	int i;
329*6a54128fSAndroid Build Coastguard Worker 	errcode_t err;
330*6a54128fSAndroid Build Coastguard Worker 
331*6a54128fSAndroid Build Coastguard Worker 	if (argc < 3) {
332*6a54128fSAndroid Build Coastguard Worker 		printf("%s: Usage: %s <file> <attrs>...\n", argv[0], argv[0]);
333*6a54128fSAndroid Build Coastguard Worker 		return;
334*6a54128fSAndroid Build Coastguard Worker 	}
335*6a54128fSAndroid Build Coastguard Worker 
336*6a54128fSAndroid Build Coastguard Worker 	if (check_fs_open(argv[0]))
337*6a54128fSAndroid Build Coastguard Worker 		return;
338*6a54128fSAndroid Build Coastguard Worker 	if (check_fs_read_write(argv[0]))
339*6a54128fSAndroid Build Coastguard Worker 		return;
340*6a54128fSAndroid Build Coastguard Worker 	if (check_fs_bitmaps(argv[0]))
341*6a54128fSAndroid Build Coastguard Worker 		return;
342*6a54128fSAndroid Build Coastguard Worker 
343*6a54128fSAndroid Build Coastguard Worker 	ino = string_to_inode(argv[1]);
344*6a54128fSAndroid Build Coastguard Worker 	if (!ino)
345*6a54128fSAndroid Build Coastguard Worker 		return;
346*6a54128fSAndroid Build Coastguard Worker 
347*6a54128fSAndroid Build Coastguard Worker 	err = ext2fs_xattrs_open(current_fs, ino, &h);
348*6a54128fSAndroid Build Coastguard Worker 	if (err)
349*6a54128fSAndroid Build Coastguard Worker 		return;
350*6a54128fSAndroid Build Coastguard Worker 
351*6a54128fSAndroid Build Coastguard Worker 	err = ext2fs_xattrs_read(h);
352*6a54128fSAndroid Build Coastguard Worker 	if (err)
353*6a54128fSAndroid Build Coastguard Worker 		goto out;
354*6a54128fSAndroid Build Coastguard Worker 
355*6a54128fSAndroid Build Coastguard Worker 	for (i = 2; i < argc; i++) {
356*6a54128fSAndroid Build Coastguard Worker 		err = ext2fs_xattr_remove(h, argv[i]);
357*6a54128fSAndroid Build Coastguard Worker 		if (err)
358*6a54128fSAndroid Build Coastguard Worker 			goto out;
359*6a54128fSAndroid Build Coastguard Worker 	}
360*6a54128fSAndroid Build Coastguard Worker out:
361*6a54128fSAndroid Build Coastguard Worker 	ext2fs_xattrs_close(&h);
362*6a54128fSAndroid Build Coastguard Worker 	if (err)
363*6a54128fSAndroid Build Coastguard Worker 		com_err(argv[0], err, "while removing extended attribute");
364*6a54128fSAndroid Build Coastguard Worker }
365*6a54128fSAndroid Build Coastguard Worker 
366*6a54128fSAndroid Build Coastguard Worker /*
367*6a54128fSAndroid Build Coastguard Worker  * Return non-zero if the string has a minimal number of non-printable
368*6a54128fSAndroid Build Coastguard Worker  * characters.
369*6a54128fSAndroid Build Coastguard Worker  */
is_mostly_printable(const char * cp,int len)370*6a54128fSAndroid Build Coastguard Worker static int is_mostly_printable(const char *cp, int len)
371*6a54128fSAndroid Build Coastguard Worker {
372*6a54128fSAndroid Build Coastguard Worker 	int	np = 0;
373*6a54128fSAndroid Build Coastguard Worker 
374*6a54128fSAndroid Build Coastguard Worker 	if (len < 0)
375*6a54128fSAndroid Build Coastguard Worker 		len = strlen(cp);
376*6a54128fSAndroid Build Coastguard Worker 
377*6a54128fSAndroid Build Coastguard Worker 	while (len--) {
378*6a54128fSAndroid Build Coastguard Worker 		if (!isprint(*cp++)) {
379*6a54128fSAndroid Build Coastguard Worker 			np++;
380*6a54128fSAndroid Build Coastguard Worker 			if (np > 3)
381*6a54128fSAndroid Build Coastguard Worker 				return 0;
382*6a54128fSAndroid Build Coastguard Worker 		}
383*6a54128fSAndroid Build Coastguard Worker 	}
384*6a54128fSAndroid Build Coastguard Worker 	return 1;
385*6a54128fSAndroid Build Coastguard Worker }
386*6a54128fSAndroid Build Coastguard Worker 
safe_print(FILE * f,const char * cp,int len)387*6a54128fSAndroid Build Coastguard Worker static void safe_print(FILE *f, const char *cp, int len)
388*6a54128fSAndroid Build Coastguard Worker {
389*6a54128fSAndroid Build Coastguard Worker 	unsigned char	ch;
390*6a54128fSAndroid Build Coastguard Worker 
391*6a54128fSAndroid Build Coastguard Worker 	if (len < 0)
392*6a54128fSAndroid Build Coastguard Worker 		len = strlen(cp);
393*6a54128fSAndroid Build Coastguard Worker 
394*6a54128fSAndroid Build Coastguard Worker 	while (len--) {
395*6a54128fSAndroid Build Coastguard Worker 		ch = *cp++;
396*6a54128fSAndroid Build Coastguard Worker 		if (ch > 128) {
397*6a54128fSAndroid Build Coastguard Worker 			fputs("M-", f);
398*6a54128fSAndroid Build Coastguard Worker 			ch -= 128;
399*6a54128fSAndroid Build Coastguard Worker 		}
400*6a54128fSAndroid Build Coastguard Worker 		if ((ch < 32) || (ch == 0x7f)) {
401*6a54128fSAndroid Build Coastguard Worker 			fputc('^', f);
402*6a54128fSAndroid Build Coastguard Worker 			ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
403*6a54128fSAndroid Build Coastguard Worker 		}
404*6a54128fSAndroid Build Coastguard Worker 		fputc(ch, f);
405*6a54128fSAndroid Build Coastguard Worker 	}
406*6a54128fSAndroid Build Coastguard Worker }
407*6a54128fSAndroid Build Coastguard Worker 
dump_xattr_raw_entries(FILE * f,unsigned char * buf,unsigned int start,unsigned int len,unsigned value_start)408*6a54128fSAndroid Build Coastguard Worker static void dump_xattr_raw_entries(FILE *f, unsigned char *buf,
409*6a54128fSAndroid Build Coastguard Worker 				   unsigned int start, unsigned int len,
410*6a54128fSAndroid Build Coastguard Worker 				   unsigned value_start)
411*6a54128fSAndroid Build Coastguard Worker {
412*6a54128fSAndroid Build Coastguard Worker 	struct ext2_ext_attr_entry ent;
413*6a54128fSAndroid Build Coastguard Worker 	unsigned int off = start;
414*6a54128fSAndroid Build Coastguard Worker 	unsigned int vstart;
415*6a54128fSAndroid Build Coastguard Worker 
416*6a54128fSAndroid Build Coastguard Worker 	while (off < len) {
417*6a54128fSAndroid Build Coastguard Worker 		if ((*(__u16 *) (buf + off)) == 0) {
418*6a54128fSAndroid Build Coastguard Worker 			fprintf(f, "last entry found at offset %u (%04o)\n",
419*6a54128fSAndroid Build Coastguard Worker 				off, off);
420*6a54128fSAndroid Build Coastguard Worker 			break;
421*6a54128fSAndroid Build Coastguard Worker 		}
422*6a54128fSAndroid Build Coastguard Worker 		if ((off + sizeof(struct ext2_ext_attr_entry)) >= len) {
423*6a54128fSAndroid Build Coastguard Worker 			fprintf(f, "xattr buffer overrun at %u (len = %u)\n",
424*6a54128fSAndroid Build Coastguard Worker 				off, len);
425*6a54128fSAndroid Build Coastguard Worker 			break;
426*6a54128fSAndroid Build Coastguard Worker 		}
427*6a54128fSAndroid Build Coastguard Worker #if WORDS_BIGENDIAN
428*6a54128fSAndroid Build Coastguard Worker 		ext2fs_swap_ext_attr_entry(&ent,
429*6a54128fSAndroid Build Coastguard Worker 			(struct ext2_ext_attr_entry *) (buf + off));
430*6a54128fSAndroid Build Coastguard Worker #else
431*6a54128fSAndroid Build Coastguard Worker 		ent = *((struct ext2_ext_attr_entry *) (buf + off));
432*6a54128fSAndroid Build Coastguard Worker #endif
433*6a54128fSAndroid Build Coastguard Worker 		fprintf(f, "offset = %d (%04o), hash = %u, name_len = %u, "
434*6a54128fSAndroid Build Coastguard Worker 			"name_index = %u\n",
435*6a54128fSAndroid Build Coastguard Worker 			off, off, ent.e_hash, ent.e_name_len, ent.e_name_index);
436*6a54128fSAndroid Build Coastguard Worker 		vstart = value_start + ent.e_value_offs;
437*6a54128fSAndroid Build Coastguard Worker 		fprintf(f, "value_offset = %d (%04o), value_inum = %u, "
438*6a54128fSAndroid Build Coastguard Worker 			"value_size = %u\n", ent.e_value_offs,
439*6a54128fSAndroid Build Coastguard Worker 			vstart, ent.e_value_inum, ent.e_value_size);
440*6a54128fSAndroid Build Coastguard Worker 		off += sizeof(struct ext2_ext_attr_entry);
441*6a54128fSAndroid Build Coastguard Worker 		fprintf(f, "name = ");
442*6a54128fSAndroid Build Coastguard Worker 		if ((off + ent.e_name_len) >= len)
443*6a54128fSAndroid Build Coastguard Worker 			fprintf(f, "<runs off end>");
444*6a54128fSAndroid Build Coastguard Worker 		else
445*6a54128fSAndroid Build Coastguard Worker 			safe_print(f, (char *)(buf + off), ent.e_name_len);
446*6a54128fSAndroid Build Coastguard Worker 		fputc('\n', f);
447*6a54128fSAndroid Build Coastguard Worker 		if (ent.e_value_size == 0)
448*6a54128fSAndroid Build Coastguard Worker 			goto skip_value;
449*6a54128fSAndroid Build Coastguard Worker 		fprintf(f, "value = ");
450*6a54128fSAndroid Build Coastguard Worker 		if (ent.e_value_inum)
451*6a54128fSAndroid Build Coastguard Worker 			fprintf(f, "<ino %u>", ent.e_value_inum);
452*6a54128fSAndroid Build Coastguard Worker 		else if (ent.e_value_offs >= len ||
453*6a54128fSAndroid Build Coastguard Worker 			 (vstart + ent.e_value_size) > len)
454*6a54128fSAndroid Build Coastguard Worker 			fprintf(f, "<runs off end>");
455*6a54128fSAndroid Build Coastguard Worker 		else if (is_mostly_printable((char *)(buf + vstart),
456*6a54128fSAndroid Build Coastguard Worker 					ent.e_value_size))
457*6a54128fSAndroid Build Coastguard Worker 			safe_print(f, (char *)(buf + vstart),
458*6a54128fSAndroid Build Coastguard Worker 				   ent.e_value_size);
459*6a54128fSAndroid Build Coastguard Worker 		else {
460*6a54128fSAndroid Build Coastguard Worker 			fprintf(f, "<hexdump>\n");
461*6a54128fSAndroid Build Coastguard Worker 			do_byte_hexdump(f, (unsigned char *)(buf + vstart),
462*6a54128fSAndroid Build Coastguard Worker 					ent.e_value_size);
463*6a54128fSAndroid Build Coastguard Worker 		}
464*6a54128fSAndroid Build Coastguard Worker 		fputc('\n', f);
465*6a54128fSAndroid Build Coastguard Worker 	skip_value:
466*6a54128fSAndroid Build Coastguard Worker 		fputc('\n', f);
467*6a54128fSAndroid Build Coastguard Worker 		off += (ent.e_name_len + 3) & ~3;
468*6a54128fSAndroid Build Coastguard Worker 	}
469*6a54128fSAndroid Build Coastguard Worker }
470*6a54128fSAndroid Build Coastguard Worker 
raw_inode_xattr_dump(FILE * f,unsigned char * buf,unsigned int len)471*6a54128fSAndroid Build Coastguard Worker void raw_inode_xattr_dump(FILE *f, unsigned char *buf, unsigned int len)
472*6a54128fSAndroid Build Coastguard Worker {
473*6a54128fSAndroid Build Coastguard Worker 	__u32 magic = ext2fs_le32_to_cpu(*((__le32 *) buf));
474*6a54128fSAndroid Build Coastguard Worker 
475*6a54128fSAndroid Build Coastguard Worker 	fprintf(f, "magic = %08x, length = %u, value_start =4 \n\n",
476*6a54128fSAndroid Build Coastguard Worker 		magic, len);
477*6a54128fSAndroid Build Coastguard Worker 	if (magic == EXT2_EXT_ATTR_MAGIC)
478*6a54128fSAndroid Build Coastguard Worker 		dump_xattr_raw_entries(f, buf, 4, len, 4);
479*6a54128fSAndroid Build Coastguard Worker }
480*6a54128fSAndroid Build Coastguard Worker 
block_xattr_dump(FILE * f,unsigned char * buf,unsigned int len)481*6a54128fSAndroid Build Coastguard Worker void block_xattr_dump(FILE *f, unsigned char *buf, unsigned int len)
482*6a54128fSAndroid Build Coastguard Worker {
483*6a54128fSAndroid Build Coastguard Worker 	struct ext2_ext_attr_header header;
484*6a54128fSAndroid Build Coastguard Worker 
485*6a54128fSAndroid Build Coastguard Worker #ifdef WORDS_BIGENDIAN
486*6a54128fSAndroid Build Coastguard Worker 	ext2fs_swap_ext_attr_header(&header,
487*6a54128fSAndroid Build Coastguard Worker 				    (struct ext2_ext_attr_header *) buf);
488*6a54128fSAndroid Build Coastguard Worker #else
489*6a54128fSAndroid Build Coastguard Worker 	header = *((struct ext2_ext_attr_header *) buf);
490*6a54128fSAndroid Build Coastguard Worker #endif
491*6a54128fSAndroid Build Coastguard Worker 	fprintf(f, "magic = %08x, length = %u\n", header.h_magic, len);
492*6a54128fSAndroid Build Coastguard Worker 	if (header.h_magic != EXT2_EXT_ATTR_MAGIC)
493*6a54128fSAndroid Build Coastguard Worker 		return;
494*6a54128fSAndroid Build Coastguard Worker 	fprintf(f, "refcount = %u, blocks = %u\n", header.h_refcount,
495*6a54128fSAndroid Build Coastguard Worker 		header.h_blocks);
496*6a54128fSAndroid Build Coastguard Worker 	fprintf(f, "hash = %08x, checksum = %08x\n", header.h_hash,
497*6a54128fSAndroid Build Coastguard Worker 		header.h_checksum);
498*6a54128fSAndroid Build Coastguard Worker 	fprintf(f, "reserved: %08x %08x %08x\n\n", header.h_reserved[0],
499*6a54128fSAndroid Build Coastguard Worker 		header.h_reserved[1], header.h_reserved[2]);
500*6a54128fSAndroid Build Coastguard Worker 
501*6a54128fSAndroid Build Coastguard Worker 	dump_xattr_raw_entries(f, buf,
502*6a54128fSAndroid Build Coastguard Worker 			       sizeof(struct ext2_ext_attr_header), len, 0);
503*6a54128fSAndroid Build Coastguard Worker }
504