From 997e213ba44841b8523f15909c589d4d49190c1c Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 28 Jan 2017 13:09:53 -0500 Subject: [PATCH] debugfs: improve how we display and parse extended attribute values Use the new C string printing routine, and allow ea_get command to display the system.data extended attribute. Also allow the user to explicitly request that the string be printed using hex values. Signed-off-by: Theodore Ts'o --- debugfs/Makefile.in | 25 ++++++---- debugfs/xattrs.c | 109 +++++++++++++++++++++++++++++++------------ tests/d_inline_dump/expect | 8 ++-- tests/d_xattr_edits/expect | 15 ++++-- tests/d_xattr_edits/script | 6 +++ tests/d_xattr_sorting/expect | 13 ++++-- tests/d_xattr_sorting/script | 6 +++ tests/r_inline_xattr/expect | 8 ++-- tests/r_inline_xattr/script | 8 ++-- 9 files changed, 139 insertions(+), 59 deletions(-) diff --git a/debugfs/Makefile.in b/debugfs/Makefile.in index a3fe13e..3ac80d9 100644 --- a/debugfs/Makefile.in +++ b/debugfs/Makefile.in @@ -68,6 +68,11 @@ debugfs.static: $(DEBUG_OBJS) $(STATIC_DEPLIBS) $(Q) $(CC) $(LDFLAGS_STATIC) -o debugfs.static $(DEBUG_OBJS) \ $(STATIC_LIBS) $(READLINE_LIB) +debugfs.static-libs: $(DEBUG_OBJS) $(STATIC_DEPLIBS) + $(E) " LD $@" + $(Q) $(CC) -o debugfs.static-libs $(DEBUG_OBJS) \ + $(STATIC_LIBS) $(READLINE_LIB) + rdebugfs: $(RO_DEBUG_OBJS) $(DEPLIBS) $(E) " LD $@" $(Q) $(CC) $(ALL_LDFLAGS) -o rdebugfs $(RO_DEBUG_OBJS) $(LIBS) @@ -146,7 +151,7 @@ uninstall: clean:: $(RM) -f $(PROGS) debugfs.8 \#* *.s *.o *.a *~ debug_cmds.c \ extent_cmds.c ro_debug_cmds.c core rdebugfs debugfs.static \ - tst_set_fields + debugfs.static-libs tst_set_fields mostlyclean: clean distclean: clean @@ -335,7 +340,8 @@ create_inode.o: $(srcdir)/../misc/create_inode.c $(top_builddir)/lib/config.h \ $(top_srcdir)/lib/ext2fs/fiemap.h $(srcdir)/../misc/create_inode.h \ $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/lib/support/nls-enable.h xattrs.o: $(srcdir)/xattrs.c $(top_builddir)/lib/config.h \ - $(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \ + $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/support/cstring.h \ + $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \ $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \ $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ @@ -355,11 +361,11 @@ quota.o: $(srcdir)/quota.c $(top_builddir)/lib/config.h \ $(top_srcdir)/lib/support/quotaio.h $(top_srcdir)/lib/support/dqblk_v2.h \ $(top_srcdir)/lib/support/quotaio_tree.h journal.o: $(srcdir)/journal.c $(top_builddir)/lib/config.h \ - $(top_builddir)/lib/dirpaths.h $(srcdir)/../e2fsck/jfs_user.h \ - $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ - $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ - $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ - $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/journal.h \ + $(srcdir)/../e2fsck/jfs_user.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \ + $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2fs.h \ + $(top_srcdir)/lib/ext2fs/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ $(top_srcdir)/lib/ext2fs/kernel-jbd.h $(top_srcdir)/lib/ext2fs/jfs_compat.h \ $(top_srcdir)/lib/ext2fs/kernel-list.h @@ -388,6 +394,7 @@ do_journal.o: $(srcdir)/do_journal.c $(top_builddir)/lib/config.h \ $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ $(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \ $(top_srcdir)/lib/support/quotaio.h $(top_srcdir)/lib/support/dqblk_v2.h \ - $(top_srcdir)/lib/support/quotaio_tree.h $(srcdir)/../e2fsck/jfs_user.h \ + $(top_srcdir)/lib/support/quotaio_tree.h \ $(top_srcdir)/lib/ext2fs/kernel-jbd.h $(top_srcdir)/lib/ext2fs/jfs_compat.h \ - $(top_srcdir)/lib/ext2fs/kernel-list.h + $(top_srcdir)/lib/ext2fs/kernel-list.h $(srcdir)/journal.h \ + $(srcdir)/../e2fsck/jfs_user.h diff --git a/debugfs/xattrs.c b/debugfs/xattrs.c index b938cc0..bbf5863 100644 --- a/debugfs/xattrs.c +++ b/debugfs/xattrs.c @@ -14,29 +14,71 @@ extern int optind; extern char *optarg; #endif #include +#include "support/cstring.h" #include "debugfs.h" +#define PRINT_XATTR_HEX 0x01 +#define PRINT_XATTR_RAW 0x02 +#define PRINT_XATTR_C 0x04 +#define PRINT_XATTR_STATFMT 0x08 +#define PRINT_XATTR_NOQUOTES 0x10 + /* Dump extended attributes */ -static void dump_xattr_string(FILE *out, const char *str, int len) +static void print_xattr_hex(FILE *f, const char *str, int len) { - int printable = 0; int i; - /* check: is string "printable enough?" */ for (i = 0; i < len; i++) - if (isprint(str[i])) - printable++; + fprintf(f, "%02x ", (unsigned char)str[i]); +} - if (printable <= len*7/8) - printable = 0; +/* Dump extended attributes */ +static void print_xattr_string(FILE *f, const char *str, int len, int flags) +{ + int printable = 0; + int i; - for (i = 0; i < len; i++) - if (printable) - fprintf(out, isprint(str[i]) ? "%c" : "\\%03o", - (unsigned char)str[i]); - else - fprintf(out, "%02x ", (unsigned char)str[i]); + if (flags & PRINT_XATTR_RAW) { + fwrite(str, len, 1, f); + return; + } + + if ((flags & PRINT_XATTR_C) == 0) { + /* check: is string "printable enough?" */ + for (i = 0; i < len; i++) + if (isprint(str[i])) + printable++; + + if (printable <= len*7/8) + flags |= PRINT_XATTR_HEX; + } + + if (flags & PRINT_XATTR_HEX) { + print_xattr_hex(f, str, len); + } else { + if ((flags & PRINT_XATTR_NOQUOTES) == 0) + fputc('\"', f); + print_c_string(f, str, len); + if ((flags & PRINT_XATTR_NOQUOTES) == 0) + fputc('\"', f); + } +} + +static void print_xattr(FILE *f, char *name, char *value, size_t value_len, + int print_flags) +{ + print_xattr_string(f, name, strlen(name), PRINT_XATTR_NOQUOTES); + fprintf(f, " (%zu)", value_len); + if ((print_flags & PRINT_XATTR_STATFMT) && + (strcmp(name, "system.data") == 0)) + value_len = 0; + if (value_len != 0 && + (!(print_flags & PRINT_XATTR_STATFMT) || (value_len < 40))) { + fprintf(f, " = "); + print_xattr_string(f, value, value_len, print_flags); + } + fputc('\n', f); } static int dump_attr(char *name, char *value, size_t value_len, void *data) @@ -44,14 +86,7 @@ static int dump_attr(char *name, char *value, size_t value_len, void *data) FILE *out = data; fprintf(out, " "); - dump_xattr_string(out, name, strlen(name)); - if (strcmp(name, "system.data") != 0) { - fprintf(out, " = \""); - dump_xattr_string(out, value, value_len); - fprintf(out, "\""); - } - fprintf(out, " (%zu)\n", value_len); - + print_xattr(out, name, value, value_len, PRINT_XATTR_STATFMT); return 0; } @@ -110,10 +145,11 @@ void do_get_xattr(int argc, char **argv) char *buf = NULL; size_t buflen; int i; + int print_flags = 0; errcode_t err; reset_getopt(); - while ((i = getopt(argc, argv, "f:")) != -1) { + while ((i = getopt(argc, argv, "Cf:xV")) != -1) { switch (i) { case 'f': if (fp) @@ -124,16 +160,24 @@ void do_get_xattr(int argc, char **argv) return; } break; + case 'x': + print_flags |= PRINT_XATTR_HEX; + break; + case 'V': + print_flags |= PRINT_XATTR_RAW; + break; + case 'C': + print_flags |= PRINT_XATTR_C; + break; default: - printf("%s: Usage: %s [-f outfile]\n", - argv[0], argv[0]); - goto out2; + goto usage; } } if (optind != argc - 2) { - printf("%s: Usage: %s [-f outfile]\n", argv[0], - argv[0]); + usage: + printf("%s: Usage: %s [-f outfile]|[-xVC]\n", + argv[0], argv[0]); goto out2; } @@ -159,7 +203,14 @@ void do_get_xattr(int argc, char **argv) if (fp) { fwrite(buf, buflen, 1, fp); } else { - dump_xattr_string(stdout, buf, buflen); + if (print_flags & PRINT_XATTR_RAW) { + if (print_flags & PRINT_XATTR_HEX|PRINT_XATTR_C) + print_flags &= ~PRINT_XATTR_RAW; + print_xattr_string(stdout, buf, buflen, print_flags); + } else { + print_xattr(stdout, argv[optind + 1], + buf, buflen, print_flags); + } printf("\n"); } @@ -233,7 +284,7 @@ void do_set_xattr(int argc, char **argv) buflen = fread(buf, 1, current_fs->blocksize, fp); } else { buf = argv[optind + 2]; - buflen = strlen(argv[optind + 2]); + buflen = parse_c_string(buf); } err = ext2fs_xattr_set(h, argv[optind + 1], buf, buflen); diff --git a/tests/d_inline_dump/expect b/tests/d_inline_dump/expect index c84f64d..b685135 100644 --- a/tests/d_inline_dump/expect +++ b/tests/d_inline_dump/expect @@ -12,7 +12,7 @@ crtime: 0x53cec3c8:4a3fd000 -- Tue Jul 22 20:04:24 2014 Size of extra inode fields: 28 Extended attributes: system.data (20) - user.a = "b" (1) + user.a (1) = "b" Size of inline data: 80 *** short file Inode: 18 Type: regular Mode: 0644 Flags: 0x10000000 @@ -28,7 +28,7 @@ crtime: 0x53cec443:bda4d400 -- Tue Jul 22 20:06:27 2014 Size of extra inode fields: 28 Extended attributes: system.data (0) - user.a = "b" (1) + user.a (1) = "b" Size of inline data: 60 *** long dir @@ -45,7 +45,7 @@ crtime: 0x53cec3fe:c8226000 -- Tue Jul 22 20:05:18 2014 Size of extra inode fields: 28 Extended attributes: system.data (72) - user.a = "b" (1) + user.a (1) = "b" Size of inline data: 132 *** short dir Inode: 20 Type: directory Mode: 0755 Flags: 0x10000000 @@ -61,7 +61,7 @@ crtime: 0x53cec477:9a5ba000 -- Tue Jul 22 20:07:19 2014 Size of extra inode fields: 28 Extended attributes: system.data (0) - user.a = "b" (1) + user.a (1) = "b" Size of inline data: 60 *** long link diff --git a/tests/d_xattr_edits/expect b/tests/d_xattr_edits/expect index 4db5414..38f3030 100644 --- a/tests/d_xattr_edits/expect +++ b/tests/d_xattr_edits/expect @@ -7,11 +7,12 @@ ea_set / user.moo FEE_FIE_FOE_FUMMMMMM Exit status is 0 ea_list / Extended attributes: - user.joe = "smith" (5) - user.moo = "FEE_FIE_FOE_FUMMMMMM" (20) + user.joe (5) = "smith" + user.moo (20) = "FEE_FIE_FOE_FUMMMMMM" Exit status is 0 ea_get / user.moo -FEE_FIE_FOE_FUMMMMMM +user.moo (20) = "FEE_FIE_FOE_FUMMMMMM" + Exit status is 0 ea_get / nosuchea ea_get: Extended attribute key not found while getting extended attribute @@ -22,7 +23,7 @@ ea_rm / nosuchea Exit status is 0 ea_list / Extended attributes: - user.joe = "smith" (5) + user.joe (5) = "smith" Exit status is 0 ea_get / user.moo ea_get: Extended attribute key not found while getting extended attribute @@ -35,7 +36,11 @@ ea_set -f d_xattr_edits.tmp / user.file_based_xattr Exit status is 0 ea_list / Extended attributes: - user.file_based_xattr = "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567\012" (108) + user.file_based_xattr (108) +Exit status is 0 +ea_get / user.file_based_xattr +user.file_based_xattr (108) = "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567\n" + Exit status is 0 ea_get -f d_xattr_edits.ver.tmp / user.file_based_xattr Exit status is 0 diff --git a/tests/d_xattr_edits/script b/tests/d_xattr_edits/script index 2e356e8..df2a530 100644 --- a/tests/d_xattr_edits/script +++ b/tests/d_xattr_edits/script @@ -96,6 +96,12 @@ status=$? echo Exit status is $status >> $OUT.new sed -f $cmd_dir/filter.sed $OUT.new >> $OUT +echo "ea_get / user.file_based_xattr" > $OUT.new +$DEBUGFS -w -R "ea_get / user.file_based_xattr" $TMPFILE >> $OUT.new 2>&1 +status=$? +echo Exit status is $status >> $OUT.new +sed -f $cmd_dir/filter.sed $OUT.new >> $OUT + echo "ea_get -f $VERIFY_DATA / user.file_based_xattr" > $OUT.new $DEBUGFS -w -R "ea_get -f $VERIFY_DATA / user.file_based_xattr" $TMPFILE >> $OUT.new 2>&1 status=$? diff --git a/tests/d_xattr_sorting/expect b/tests/d_xattr_sorting/expect index 30a6eab..3fd06fa 100644 --- a/tests/d_xattr_sorting/expect +++ b/tests/d_xattr_sorting/expect @@ -9,12 +9,17 @@ ea_set / user.moo cow Exit status is 0 ea_list / Extended attributes: - user.moo = "cow" (3) - security.imb = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" (256) - security.SMEG64 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" (256) + user.moo (3) = "cow" + security.imb (256) + security.SMEG64 (256) Exit status is 0 ea_get / security.imb -xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +security.imb (256) = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +Exit status is 0 +ea_get / security.SMEG64 +security.SMEG64 (256) = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + Exit status is 0 ea_get / nosuchea ea_get: Extended attribute key not found while getting extended attribute diff --git a/tests/d_xattr_sorting/script b/tests/d_xattr_sorting/script index 8d5602e..459a66a 100644 --- a/tests/d_xattr_sorting/script +++ b/tests/d_xattr_sorting/script @@ -54,6 +54,12 @@ status=$? echo Exit status is $status >> $OUT.new sed -f $cmd_dir/filter.sed $OUT.new >> $OUT +echo "ea_get / security.SMEG64" > $OUT.new +$DEBUGFS -w -R "ea_get / security.SMEG64" $TMPFILE >> $OUT.new 2>&1 +status=$? +echo Exit status is $status >> $OUT.new +sed -f $cmd_dir/filter.sed $OUT.new >> $OUT + echo "ea_get / nosuchea" > $OUT.new $DEBUGFS -w -R "ea_get / nosuchea" $TMPFILE >> $OUT.new 2>&1 status=$? diff --git a/tests/r_inline_xattr/expect b/tests/r_inline_xattr/expect index 3feba08..885de59 100644 --- a/tests/r_inline_xattr/expect +++ b/tests/r_inline_xattr/expect @@ -1,14 +1,14 @@ resize2fs test -debugfs -R ''stat file'' test.img 2>&1 | grep ''^Inode\|in inode body\|name = '' +debugfs -R ''stat file'' test.img 2>&1 | grep ''^Inode\|in inode body\|user.name ('' Inode: 1550 Type: regular Mode: 0644 Flags: 0x0 - user.name = "propervalue" (11) + user.name (11) = "propervalue" Exit status is 0 resize2fs test.img 5M Resizing the filesystem on test.img to 5120 (1k) blocks. The filesystem on test.img is now 5120 (1k) blocks long. Exit status is 0 -debugfs -R ''stat file'' test.img 2>&1 | grep ''^Inode\|in inode body\|name = '' +debugfs -R ''stat file'' test.img 2>&1 | grep ''^Inode\|in inode body\|user.name ('' Inode: 12 Type: regular Mode: 0644 Flags: 0x0 - user.name = "propervalue" (11) + user.name (11) = "propervalue" Exit status is 0 diff --git a/tests/r_inline_xattr/script b/tests/r_inline_xattr/script index d882587..eb2085d 100644 --- a/tests/r_inline_xattr/script +++ b/tests/r_inline_xattr/script @@ -10,8 +10,8 @@ gunzip < $IMAGE > $TMPFILE echo "resize2fs test" > $OUT # Look at existing inline extended attribute -echo "debugfs -R ''stat file'' test.img 2>&1 | grep ''^Inode\|in inode body\|name = ''" >> $OUT -$DEBUGFS -R "stat file" $TMPFILE 2>&1 | grep "^Inode\|in inode body\|name = " >> $OUT +echo "debugfs -R ''stat file'' test.img 2>&1 | grep ''^Inode\|in inode body\|user.name (''" >> $OUT +$DEBUGFS -R "stat file" $TMPFILE 2>&1 | grep "^Inode\|in inode body\|user.name (" >> $OUT status=$? echo Exit status is $status >> $OUT @@ -23,8 +23,8 @@ echo Exit status is $status >> $OUT.new sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT # Look at inline extended attribute in resized fs -echo "debugfs -R ''stat file'' test.img 2>&1 | grep ''^Inode\|in inode body\|name = ''" >> $OUT -$DEBUGFS -R "stat file" $TMPFILE 2>&1 | grep "^Inode\|in inode body\|name = " >> $OUT +echo "debugfs -R ''stat file'' test.img 2>&1 | grep ''^Inode\|in inode body\|user.name (''" >> $OUT +$DEBUGFS -R "stat file" $TMPFILE 2>&1 | grep "^Inode\|in inode body\|user.name (" >> $OUT status=$? echo Exit status is $status >> $OUT -- 1.8.3.1