2 * xattrs.c --- Modify extended attributes via debugfs.
4 * Copyright (C) 2014 Oracle. This file may be redistributed
5 * under the terms of the GNU Public License.
17 #include "support/cstring.h"
21 #define PRINT_XATTR_HEX 0x01
22 #define PRINT_XATTR_RAW 0x02
23 #define PRINT_XATTR_C 0x04
24 #define PRINT_XATTR_STATFMT 0x08
25 #define PRINT_XATTR_NOQUOTES 0x10
27 /* Dump extended attributes */
28 static void print_xattr_hex(FILE *f
, const char *str
, int len
)
32 for (i
= 0; i
< len
; i
++)
33 fprintf(f
, "%02x ", (unsigned char)str
[i
]);
36 /* Dump extended attributes */
37 static void print_xattr_string(FILE *f
, const char *str
, int len
, int flags
)
42 if (flags
& PRINT_XATTR_RAW
) {
43 fwrite(str
, len
, 1, f
);
47 if ((flags
& PRINT_XATTR_C
) == 0) {
48 /* check: is string "printable enough?" */
49 for (i
= 0; i
< len
; i
++)
53 if (printable
<= len
*7/8)
54 flags
|= PRINT_XATTR_HEX
;
57 if (flags
& PRINT_XATTR_HEX
) {
58 print_xattr_hex(f
, str
, len
);
60 if ((flags
& PRINT_XATTR_NOQUOTES
) == 0)
62 print_c_string(f
, str
, len
);
63 if ((flags
& PRINT_XATTR_NOQUOTES
) == 0)
68 static void print_xattr(FILE *f
, char *name
, char *value
, size_t value_len
,
71 print_xattr_string(f
, name
, strlen(name
), PRINT_XATTR_NOQUOTES
);
72 fprintf(f
, " (%zu)", value_len
);
73 if ((print_flags
& PRINT_XATTR_STATFMT
) &&
74 (strcmp(name
, "system.data") == 0))
77 (!(print_flags
& PRINT_XATTR_STATFMT
) || (value_len
< 40))) {
79 print_xattr_string(f
, value
, value_len
, print_flags
);
84 static int dump_attr(char *name
, char *value
, size_t value_len
, void *data
)
89 print_xattr(out
, name
, value
, value_len
, PRINT_XATTR_STATFMT
);
93 void dump_inode_attributes(FILE *out
, ext2_ino_t ino
)
95 struct ext2_xattr_handle
*h
;
99 err
= ext2fs_xattrs_open(current_fs
, ino
, &h
);
103 err
= ext2fs_xattrs_read(h
);
107 err
= ext2fs_xattrs_count(h
, &sz
);
111 fprintf(out
, "Extended attributes:\n");
112 err
= ext2fs_xattrs_iterate(h
, dump_attr
, out
);
117 err
= ext2fs_xattrs_close(&h
);
120 void do_list_xattr(int argc
, char **argv
, int sci_idx
EXT2FS_ATTR((unused
)),
121 void *infop
EXT2FS_ATTR((unused
)))
126 printf("%s: Usage: %s <file>\n", argv
[0],
131 if (check_fs_open(argv
[0]))
134 ino
= string_to_inode(argv
[1]);
138 dump_inode_attributes(stdout
, ino
);
141 void do_get_xattr(int argc
, char **argv
, int sci_idx
EXT2FS_ATTR((unused
)),
142 void *infop
EXT2FS_ATTR((unused
)))
145 struct ext2_xattr_handle
*h
;
151 unsigned int handle_flags
= 0;
155 while ((i
= getopt(argc
, argv
, "Cf:rxV")) != -1) {
160 fp
= fopen(optarg
, "w");
167 handle_flags
|= XATTR_HANDLE_FLAG_RAW
;
170 print_flags
|= PRINT_XATTR_HEX
;
173 print_flags
|= PRINT_XATTR_RAW
|
174 PRINT_XATTR_NOQUOTES
;
177 print_flags
|= PRINT_XATTR_C
;
184 if (optind
!= argc
- 2) {
186 printf("%s: Usage: %s [-f outfile]|[-xVC] [-r] <file> <attr>\n",
192 if (check_fs_open(argv
[0]))
195 ino
= string_to_inode(argv
[optind
]);
199 err
= ext2fs_xattrs_open(current_fs
, ino
, &h
);
203 err
= ext2fs_xattrs_flags(h
, &handle_flags
, NULL
);
207 err
= ext2fs_xattrs_read(h
);
211 err
= ext2fs_xattr_get(h
, argv
[optind
+ 1], (void **)&buf
, &buflen
);
216 fwrite(buf
, buflen
, 1, fp
);
218 if (print_flags
& PRINT_XATTR_RAW
) {
219 if (print_flags
& (PRINT_XATTR_HEX
|PRINT_XATTR_C
))
220 print_flags
&= ~PRINT_XATTR_RAW
;
221 print_xattr_string(stdout
, buf
, buflen
, print_flags
);
223 print_xattr(stdout
, argv
[optind
+ 1],
224 buf
, buflen
, print_flags
);
229 ext2fs_free_mem(&buf
);
231 ext2fs_xattrs_close(&h
);
233 com_err(argv
[0], err
, "while getting extended attribute");
239 void do_set_xattr(int argc
, char **argv
, int sci_idx
EXT2FS_ATTR((unused
)),
240 void *infop
EXT2FS_ATTR((unused
)))
243 struct ext2_xattr_handle
*h
;
247 unsigned int handle_flags
= 0;
252 while ((i
= getopt(argc
, argv
, "f:r")) != -1) {
257 fp
= fopen(optarg
, "r");
264 handle_flags
|= XATTR_HANDLE_FLAG_RAW
;
271 if (!(fp
&& optind
== argc
- 2) && !(!fp
&& optind
== argc
- 3)) {
273 printf("Usage:\t%s [-r] <file> <attr> <value>\n", argv
[0]);
274 printf("\t%s -f <value_file> [-r] <file> <attr>\n", argv
[0]);
278 if (check_fs_open(argv
[0]))
280 if (check_fs_read_write(argv
[0]))
282 if (check_fs_bitmaps(argv
[0]))
285 ino
= string_to_inode(argv
[optind
]);
289 err
= ext2fs_xattrs_open(current_fs
, ino
, &h
);
293 err
= ext2fs_xattrs_flags(h
, &handle_flags
, NULL
);
297 err
= ext2fs_xattrs_read(h
);
302 err
= ext2fs_get_mem(current_fs
->blocksize
, &buf
);
305 buflen
= fread(buf
, 1, current_fs
->blocksize
, fp
);
307 buf
= argv
[optind
+ 2];
308 buflen
= parse_c_string(buf
);
311 err
= ext2fs_xattr_set(h
, argv
[optind
+ 1], buf
, buflen
);
313 ext2fs_xattrs_close(&h
);
315 com_err(argv
[0], err
, "while setting extended attribute");
319 ext2fs_free_mem(&buf
);
323 void do_rm_xattr(int argc
, char **argv
, int sci_idx
EXT2FS_ATTR((unused
)),
324 void *infop
EXT2FS_ATTR((unused
)))
327 struct ext2_xattr_handle
*h
;
332 printf("%s: Usage: %s <file> <attrs>...\n", argv
[0], argv
[0]);
336 if (check_fs_open(argv
[0]))
338 if (check_fs_read_write(argv
[0]))
340 if (check_fs_bitmaps(argv
[0]))
343 ino
= string_to_inode(argv
[1]);
347 err
= ext2fs_xattrs_open(current_fs
, ino
, &h
);
351 err
= ext2fs_xattrs_read(h
);
355 for (i
= 2; i
< argc
; i
++) {
356 err
= ext2fs_xattr_remove(h
, argv
[i
]);
361 ext2fs_xattrs_close(&h
);
363 com_err(argv
[0], err
, "while removing extended attribute");
367 * Return non-zero if the string has a minimal number of non-printable
370 static int is_mostly_printable(const char *cp
, int len
)
378 if (!isprint(*cp
++)) {
387 static void safe_print(FILE *f
, const char *cp
, int len
)
400 if ((ch
< 32) || (ch
== 0x7f)) {
402 ch
^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
408 static void dump_xattr_raw_entries(FILE *f
, unsigned char *buf
,
409 unsigned int start
, unsigned int len
,
410 unsigned value_start
)
412 struct ext2_ext_attr_entry ent
;
413 unsigned int off
= start
;
417 if ((*(__u16
*) (buf
+ off
)) == 0) {
418 fprintf(f
, "last entry found at offset %u (%04o)\n",
422 if ((off
+ sizeof(struct ext2_ext_attr_entry
)) >= len
) {
423 fprintf(f
, "xattr buffer overrun at %u (len = %u)\n",
428 ext2fs_swap_ext_attr_entry(&ent
,
429 (struct ext2_ext_attr_entry
*) (buf
+ off
));
431 ent
= *((struct ext2_ext_attr_entry
*) (buf
+ off
));
433 fprintf(f
, "offset = %d (%04o), name_len = %u, "
435 off
, off
, ent
.e_name_len
, ent
.e_name_index
);
436 vstart
= value_start
+ ent
.e_value_offs
;
437 fprintf(f
, "value_offset = %d (%04o), value_inum = %u, "
438 "value_size = %u\n", ent
.e_value_offs
,
439 vstart
, ent
.e_value_inum
, ent
.e_value_size
);
440 off
+= sizeof(struct ext2_ext_attr_entry
);
441 fprintf(f
, "name = ");
442 if ((off
+ ent
.e_name_len
) >= len
)
443 fprintf(f
, "<runs off end>");
445 safe_print(f
, (char *)(buf
+ off
), ent
.e_name_len
);
447 if (ent
.e_value_size
== 0)
449 fprintf(f
, "value = ");
450 if (ent
.e_value_inum
)
451 fprintf(f
, "<ino %u>", ent
.e_value_inum
);
452 else if (ent
.e_value_offs
>= len
||
453 (vstart
+ ent
.e_value_size
) > len
)
454 fprintf(f
, "<runs off end>");
455 if (is_mostly_printable((char *)(buf
+ vstart
),
457 safe_print(f
, (char *)(buf
+ vstart
),
460 fprintf(f
, "<hexdump>\n");
461 do_byte_hexdump(f
, (unsigned char *)(buf
+ vstart
),
467 off
+= (ent
.e_name_len
+ 3) & ~3;
471 void raw_inode_xattr_dump(FILE *f
, unsigned char *buf
, unsigned int len
)
473 __u32 magic
= ext2fs_le32_to_cpu(*((__le32
*) buf
));
475 fprintf(f
, "magic = %08x, length = %u, value_start =4 \n\n",
477 if (magic
== EXT2_EXT_ATTR_MAGIC
)
478 dump_xattr_raw_entries(f
, buf
, 4, len
, 4);
481 void block_xattr_dump(FILE *f
, unsigned char *buf
, unsigned int len
)
483 struct ext2_ext_attr_header header
;
485 #ifdef WORDS_BIGENDIAN
486 ext2fs_swap_ext_attr_header(&header
,
487 (struct ext2_ext_attr_header
*) buf
);
489 header
= *((struct ext2_ext_attr_header
*) buf
);
491 fprintf(f
, "magic = %08x, length = %u\n", header
.h_magic
, len
);
492 if (header
.h_magic
!= EXT2_EXT_ATTR_MAGIC
)
494 fprintf(f
, "refcount = %u, blocks = %u\n", header
.h_refcount
,
496 fprintf(f
, "hash = %08x, checksum = %08x\n", header
.h_hash
,
498 fprintf(f
, "reserved: %08x %08x %08x\n\n", header
.h_reserved
[0],
499 header
.h_reserved
[1], header
.h_reserved
[2]);
501 dump_xattr_raw_entries(f
, buf
,
502 sizeof(struct ext2_ext_attr_header
), len
, 0);