Whamcloud - gitweb
debugfs: teach set_super_value how to set the s_encoding field
[tools/e2fsprogs.git] / debugfs / xattrs.c
index 390165c..bd11450 100644 (file)
@@ -117,7 +117,8 @@ out:
        err = ext2fs_xattrs_close(&h);
 }
 
-void do_list_xattr(int argc, char **argv)
+void do_list_xattr(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)),
+                  void *infop EXT2FS_ATTR((unused)))
 {
        ext2_ino_t ino;
 
@@ -137,7 +138,8 @@ void do_list_xattr(int argc, char **argv)
        dump_inode_attributes(stdout, ino);
 }
 
-void do_get_xattr(int argc, char **argv)
+void do_get_xattr(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)),
+                 void *infop EXT2FS_ATTR((unused)))
 {
        ext2_ino_t ino;
        struct ext2_xattr_handle *h;
@@ -234,7 +236,8 @@ out2:
                fclose(fp);
 }
 
-void do_set_xattr(int argc, char **argv)
+void do_set_xattr(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)),
+                 void *infop EXT2FS_ATTR((unused)))
 {
        ext2_ino_t ino;
        struct ext2_xattr_handle *h;
@@ -317,7 +320,8 @@ out2:
        }
 }
 
-void do_rm_xattr(int argc, char **argv)
+void do_rm_xattr(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)),
+                void *infop EXT2FS_ATTR((unused)))
 {
        ext2_ino_t ino;
        struct ext2_xattr_handle *h;
@@ -358,3 +362,142 @@ out:
        if (err)
                com_err(argv[0], err, "while removing extended attribute");
 }
+
+/*
+ * Return non-zero if the string has a minimal number of non-printable
+ * characters.
+ */
+static int is_mostly_printable(const char *cp, int len)
+{
+       int     np = 0;
+
+       if (len < 0)
+               len = strlen(cp);
+
+       while (len--) {
+               if (!isprint(*cp++)) {
+                       np++;
+                       if (np > 3)
+                               return 0;
+               }
+       }
+       return 1;
+}
+
+static void safe_print(FILE *f, const char *cp, int len)
+{
+       unsigned char   ch;
+
+       if (len < 0)
+               len = strlen(cp);
+
+       while (len--) {
+               ch = *cp++;
+               if (ch > 128) {
+                       fputs("M-", f);
+                       ch -= 128;
+               }
+               if ((ch < 32) || (ch == 0x7f)) {
+                       fputc('^', f);
+                       ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
+               }
+               fputc(ch, f);
+       }
+}
+
+static void dump_xattr_raw_entries(FILE *f, unsigned char *buf,
+                                  unsigned int start, unsigned int len,
+                                  unsigned value_start)
+{
+       struct ext2_ext_attr_entry ent;
+       unsigned int off = start;
+       unsigned int vstart;
+
+       while (off < len) {
+               if ((*(__u16 *) (buf + off)) == 0) {
+                       fprintf(f, "last entry found at offset %u (%04o)\n",
+                               off, off);
+                       break;
+               }
+               if ((off + sizeof(struct ext2_ext_attr_entry)) >= len) {
+                       fprintf(f, "xattr buffer overrun at %u (len = %u)\n",
+                               off, len);
+                       break;
+               }
+#if WORDS_BIGENDIAN
+               ext2fs_swap_ext_attr_entry(&ent,
+                       (struct ext2_ext_attr_entry *) (buf + off));
+#else
+               ent = *((struct ext2_ext_attr_entry *) (buf + off));
+#endif
+               fprintf(f, "offset = %d (%04o), name_len = %u, "
+                       "name_index = %u\n",
+                       off, off, ent.e_name_len, ent.e_name_index);
+               vstart = value_start + ent.e_value_offs;
+               fprintf(f, "value_offset = %d (%04o), value_inum = %u, "
+                       "value_size = %u\n", ent.e_value_offs,
+                       vstart, ent.e_value_inum, ent.e_value_size);
+               off += sizeof(struct ext2_ext_attr_entry);
+               fprintf(f, "name = ");
+               if ((off + ent.e_name_len) >= len)
+                       fprintf(f, "<runs off end>");
+               else
+                       safe_print(f, (char *)(buf + off), ent.e_name_len);
+               fputc('\n', f);
+               if (ent.e_value_size == 0)
+                       goto skip_value;
+               fprintf(f, "value = ");
+               if (ent.e_value_inum)
+                       fprintf(f, "<ino %u>", ent.e_value_inum);
+               else if (ent.e_value_offs >= len ||
+                        (vstart + ent.e_value_size) > len)
+                       fprintf(f, "<runs off end>");
+               else if (is_mostly_printable((char *)(buf + vstart),
+                                       ent.e_value_size))
+                       safe_print(f, (char *)(buf + vstart),
+                                  ent.e_value_size);
+               else {
+                       fprintf(f, "<hexdump>\n");
+                       do_byte_hexdump(f, (unsigned char *)(buf + vstart),
+                                       ent.e_value_size);
+               }
+               fputc('\n', f);
+       skip_value:
+               fputc('\n', f);
+               off += (ent.e_name_len + 3) & ~3;
+       }
+}
+
+void raw_inode_xattr_dump(FILE *f, unsigned char *buf, unsigned int len)
+{
+       __u32 magic = ext2fs_le32_to_cpu(*((__le32 *) buf));
+
+       fprintf(f, "magic = %08x, length = %u, value_start =4 \n\n",
+               magic, len);
+       if (magic == EXT2_EXT_ATTR_MAGIC)
+               dump_xattr_raw_entries(f, buf, 4, len, 4);
+}
+
+void block_xattr_dump(FILE *f, unsigned char *buf, unsigned int len)
+{
+       struct ext2_ext_attr_header header;
+
+#ifdef WORDS_BIGENDIAN
+       ext2fs_swap_ext_attr_header(&header,
+                                   (struct ext2_ext_attr_header *) buf);
+#else
+       header = *((struct ext2_ext_attr_header *) buf);
+#endif
+       fprintf(f, "magic = %08x, length = %u\n", header.h_magic, len);
+       if (header.h_magic != EXT2_EXT_ATTR_MAGIC)
+               return;
+       fprintf(f, "refcount = %u, blocks = %u\n", header.h_refcount,
+               header.h_blocks);
+       fprintf(f, "hash = %08x, checksum = %08x\n", header.h_hash,
+               header.h_checksum);
+       fprintf(f, "reserved: %08x %08x %08x\n\n", header.h_reserved[0],
+               header.h_reserved[1], header.h_reserved[2]);
+
+       dump_xattr_raw_entries(f, buf,
+                              sizeof(struct ext2_ext_attr_header), len, 0);
+}