Whamcloud - gitweb
debugfs: improve how we display and parse extended attribute values
authorTheodore Ts'o <tytso@mit.edu>
Sat, 28 Jan 2017 18:09:53 +0000 (13:09 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Sun, 29 Jan 2017 02:11:19 +0000 (21:11 -0500)
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 <tytso@mit.edu>
debugfs/Makefile.in
debugfs/xattrs.c
tests/d_inline_dump/expect
tests/d_xattr_edits/expect
tests/d_xattr_edits/script
tests/d_xattr_sorting/expect
tests/d_xattr_sorting/script
tests/r_inline_xattr/expect
tests/r_inline_xattr/script

index a3fe13e..3ac80d9 100644 (file)
@@ -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
index b938cc0..bbf5863 100644 (file)
@@ -14,29 +14,71 @@ extern int optind;
 extern char *optarg;
 #endif
 #include <ctype.h>
+#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 <file> <attr> [-f outfile]\n",
-                              argv[0], argv[0]);
-                       goto out2;
+                       goto usage;
                }
        }
 
        if (optind != argc - 2) {
-               printf("%s: Usage: %s <file> <attr> [-f outfile]\n", argv[0],
-                      argv[0]);
+       usage:
+               printf("%s: Usage: %s <file> <attr> [-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);
index c84f64d..b685135 100644 (file)
@@ -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
index 4db5414..38f3030 100644 (file)
@@ -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
index 2e356e8..df2a530 100644 (file)
@@ -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=$?
index 30a6eab..3fd06fa 100644 (file)
@@ -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
index 8d5602e..459a66a 100644 (file)
@@ -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=$?
index 3feba08..885de59 100644 (file)
@@ -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
index d882587..eb2085d 100644 (file)
@@ -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