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