]> www.infradead.org Git - mtd-utils.git/commitdiff
Add XATTR support to mkfs.jffs2
authorDavid Woodhouse <dwmw2@infradead.org>
Sat, 6 May 2006 11:53:55 +0000 (12:53 +0100)
committerDavid Woodhouse <dwmw2@infradead.org>
Sat, 6 May 2006 11:53:55 +0000 (12:53 +0100)
Since this is optional, it might as well go in immediately.

include/linux/jffs2.h
include/mtd/jffs2-user.h
mkfs.jffs2.1
mkfs.jffs2.c
summary.h
sumtool.c

index cf792bb3c72655beafc28d29c72f25f14bf96a4b..2cac60e55322a8f408bfb106dc6b59c6a1b0918c 100644 (file)
 
 #define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6)
 
+#define JFFS2_NODETYPE_XATTR (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 8)
+#define JFFS2_NODETYPE_XREF (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 9)
+
+/* XATTR Related */
+#define JFFS2_XPREFIX_USER             1       /* for "user." */
+#define JFFS2_XPREFIX_SECURITY         2       /* for "security." */
+#define JFFS2_XPREFIX_ACL_ACCESS       3       /* for "system.posix_acl_access" */
+#define JFFS2_XPREFIX_ACL_DEFAULT      4       /* for "system.posix_acl_default" */
+#define JFFS2_XPREFIX_TRUSTED          5       /* for "trusted.*" */
+
+#define JFFS2_ACL_VERSION              0x0001
+
 // Maybe later...
 //#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)
 //#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4)
@@ -151,6 +163,32 @@ struct jffs2_raw_inode
        uint8_t data[0];
 } __attribute__((packed));
 
+struct jffs2_raw_xattr {
+       jint16_t magic;
+       jint16_t nodetype;      /* = JFFS2_NODETYPE_XATTR */
+       jint32_t totlen;
+       jint32_t hdr_crc;
+       jint32_t xid;           /* XATTR identifier number */
+       jint32_t version;
+       uint8_t xprefix;
+       uint8_t name_len;
+       jint16_t value_len;
+       jint32_t data_crc;
+       jint32_t node_crc;
+       uint8_t data[0];
+} __attribute__((packed));
+
+struct jffs2_raw_xref
+{
+       jint16_t magic;
+       jint16_t nodetype;      /* = JFFS2_NODETYPE_XREF */
+       jint32_t totlen;
+       jint32_t hdr_crc;
+       jint32_t ino;           /* inode number */
+       jint32_t xid;           /* XATTR identifier number */
+       jint32_t node_crc;
+} __attribute__((packed));
+
 struct jffs2_raw_summary
 {
        jint16_t magic;
@@ -169,6 +207,8 @@ union jffs2_node_union
 {
        struct jffs2_raw_inode i;
        struct jffs2_raw_dirent d;
+       struct jffs2_raw_xattr x;
+       struct jffs2_raw_xref r;
        struct jffs2_raw_summary s;
        struct jffs2_unknown_node u;
 };
index d508ef0ae091bd2c76b549461f3065679cb012dc..8b53990159e03ce2ef491c2b867d673e1e536c16 100644 (file)
@@ -32,4 +32,51 @@ extern int target_endian;
 #define je32_to_cpu(x) (t32((x).v32))
 #define jemode_to_cpu(x) (t32((x).m))
 
+#define le16_to_cpu(x) (__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_16(x))
+#define le32_to_cpu(x) (__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_32(x))
+#define cpu_to_le16(x) (__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_16(x))
+#define cpu_to_le32(x) (__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_32(x))
+
+/* XATTR/POSIX-ACL related definition */
+/* Namespaces copied from xattr.h and posix_acl_xattr.h */
+#define XATTR_USER_PREFIX              "user."
+#define XATTR_USER_PREFIX_LEN          (sizeof (XATTR_USER_PREFIX) - 1)
+#define XATTR_SECURITY_PREFIX          "security."
+#define XATTR_SECURITY_PREFIX_LEN      (sizeof (XATTR_SECURITY_PREFIX) - 1)
+#define POSIX_ACL_XATTR_ACCESS         "system.posix_acl_access"
+#define POSIX_ACL_XATTR_ACCESS_LEN     (sizeof (POSIX_ACL_XATTR_ACCESS) - 1)
+#define POSIX_ACL_XATTR_DEFAULT                "system.posix_acl_default"
+#define POSIX_ACL_XATTR_DEFAULT_LEN    (sizeof (POSIX_ACL_XATTR_DEFAULT) - 1)
+#define XATTR_TRUSTED_PREFIX           "trusted."
+#define XATTR_TRUSTED_PREFIX_LEN       (sizeof (XATTR_TRUSTED_PREFIX) - 1)
+
+typedef struct {
+       jint16_t        e_tag;
+       jint16_t        e_perm;
+       jint32_t        e_id;
+} jffs2_acl_entry;
+
+typedef struct {
+       jint16_t        e_tag;
+       jint16_t        e_perm;
+} jffs2_acl_entry_short;
+
+typedef struct {
+       jint32_t        a_version;
+} jffs2_acl_header;
+
+/* copied from include/linux/posix_acl_xattr.h */
+#define POSIX_ACL_XATTR_VERSION 0x0002
+
+typedef struct {
+       uint16_t                e_tag;
+       uint16_t                e_perm;
+       uint32_t                e_id;
+} posix_acl_xattr_entry;
+
+typedef struct {
+       uint32_t                a_version;
+       posix_acl_xattr_entry   a_entries[0];
+} posix_acl_xattr_header;
+
 #endif /* __JFFS2_USER_H__ */
index 7e32c9205e70fac038341719cb725d5e4e286970..1b31ee990524eadf326595a912c5ad9bab76bf86 100644 (file)
@@ -49,6 +49,15 @@ mkfs.jffs2 \- Create a JFFS2 file system image from directory
 .B -P,--squash-perms
 ]
 [
+.B --with-xattr
+]
+[
+.B --with-selinux
+]
+[
+.B --with-posix-acl
+]
+[
 .B -m,--compression-mode=MODE
 ]
 [
@@ -178,6 +187,15 @@ Squash owners making all files be owned by root.
 .B -P, --squash-perms
 Squash permissions, removing write permission for \'group\' and \'other\'.
 .TP
+.B --with-xattr
+Enables xattr, stuff all xattr entries into jffs2 image file.
+.TP
+.B --with-selinux
+Enables xattr, stuff only SELinux Labels into jffs2 image file.
+.TP
+.B --with-posix-acl
+Enable xattr, stuff only POSIX ACL entries into jffs2 image file.
+.TP
 .B -m, --compression-mode=MODE
 Set the default compression mode. The default mode is 
 .B priority 
index a708f14bf0da987b6ddaa9746ed5d029030058fc..02f57f9aa67a0489f87ebad3fdb43ebd0c317dde 100644 (file)
@@ -7,6 +7,7 @@
  *           2002 Axis Communications AB
  *           2001, 2002 Erik Andersen <andersen@codepoet.org>
  *           2004 University of Szeged, Hungary
+ *           2006 KaiGai Kohei <kaigai@ak.jp.nec.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -63,6 +64,8 @@
 #include <ctype.h>
 #include <time.h>
 #include <getopt.h>
+#include <sys/xattr.h>
+#include <sys/acl.h>
 #include <byteswap.h>
 #define crc32 __complete_crap
 #include <zlib.h>
@@ -1022,6 +1025,233 @@ static void write_special_file(struct filesystem_entry *e)
        padword();
 }
 
+typedef struct xattr_entry {
+       struct xattr_entry *next;
+       uint32_t xid;
+       int xprefix;
+       char *xname;
+       char *xvalue;
+       int name_len;
+       int value_len;
+} xattr_entry_t;
+
+#define XATTR_BUFFER_SIZE              (64 * 1024)     /* 64KB */
+static uint32_t enable_xattr = 0;
+static uint32_t highest_xid = 0;
+
+static struct {
+       int xprefix;
+       char *string;
+       int length;
+} xprefix_tbl[] = {
+       { JFFS2_XPREFIX_USER, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN },
+       { JFFS2_XPREFIX_SECURITY, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN },
+       { JFFS2_XPREFIX_ACL_ACCESS, POSIX_ACL_XATTR_ACCESS, POSIX_ACL_XATTR_ACCESS_LEN },
+       { JFFS2_XPREFIX_ACL_DEFAULT, POSIX_ACL_XATTR_DEFAULT, POSIX_ACL_XATTR_DEFAULT_LEN },
+       { JFFS2_XPREFIX_TRUSTED, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN },
+       { 0, NULL, 0 }
+};
+
+static void formalize_posix_acl(char *xvalue, int *value_len)
+{
+       posix_acl_xattr_header *pacl_header;
+       posix_acl_xattr_entry *pent, *plim;
+       jffs2_acl_header *jacl_header;
+       jffs2_acl_entry *jent;
+       jffs2_acl_entry_short *jent_s;
+       char buffer[XATTR_BUFFER_SIZE];
+       int offset = 0;
+
+       pacl_header = (posix_acl_xattr_header *)xvalue;;
+       pent = pacl_header->a_entries;
+       plim = (posix_acl_xattr_entry *)(xvalue + *value_len);
+
+       jacl_header = (jffs2_acl_header *)buffer;
+       offset += sizeof(jffs2_acl_header);
+       jacl_header->a_version = cpu_to_je32(JFFS2_ACL_VERSION);
+
+       while (pent < plim) {
+               switch(le16_to_cpu(pent->e_tag)) {
+               case ACL_USER_OBJ:
+               case ACL_GROUP_OBJ:
+               case ACL_MASK:
+               case ACL_OTHER:
+                       jent_s = (jffs2_acl_entry_short *)(buffer + offset);
+                       offset += sizeof(jffs2_acl_entry_short);
+                       jent_s->e_tag = cpu_to_je16(le16_to_cpu(pent->e_tag));
+                       jent_s->e_perm = cpu_to_je16(le16_to_cpu(pent->e_perm));
+                       break;
+               case ACL_USER:
+               case ACL_GROUP:
+                       jent = (jffs2_acl_entry *)(buffer + offset);
+                       offset += sizeof(jffs2_acl_entry);
+                       jent->e_tag = cpu_to_je16(le16_to_cpu(pent->e_tag));
+                       jent->e_perm = cpu_to_je16(le16_to_cpu(pent->e_perm));
+                       jent->e_id = cpu_to_je32(le32_to_cpu(pent->e_id));
+                       break;
+               default:
+                       printf("%04x : Unknown XATTR entry tag.\n", le16_to_cpu(pent->e_tag));
+                       exit(1);
+               }
+               pent++;
+       }
+       if (offset > *value_len) {
+               printf("Length of JFFS2 ACL expression(%u) is longer than general one(%u).\n",
+                      offset, *value_len);
+               exit(1);
+       }
+       memcpy(xvalue, buffer, offset);
+       *value_len = offset;
+}
+
+static xattr_entry_t *create_xattr_entry(int xprefix, char *xname, char *xvalue, int value_len)
+{
+       xattr_entry_t *xe;
+       struct jffs2_raw_xattr rx;
+       int name_len;
+
+       /* create xattr entry */
+       name_len = strlen(xname);
+       xe = xcalloc(1, sizeof(xattr_entry_t) + name_len + 1 + value_len);
+       xe->next = NULL;
+       xe->xid = ++highest_xid;
+       xe->xprefix = xprefix;
+       xe->xname = ((char *)xe) + sizeof(xattr_entry_t);
+       xe->xvalue = xe->xname + name_len + 1;
+       xe->name_len = name_len;
+       xe->value_len = value_len;
+       strcpy(xe->xname, xname);
+       memcpy(xe->xvalue, xvalue, value_len);
+
+       /* write xattr node */
+       memset(&rx, 0, sizeof(rx));
+       rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+       rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR);
+       rx.totlen = cpu_to_je32(PAD(sizeof(rx) + xe->name_len + 1 + xe->value_len));
+       rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4));
+
+       rx.xid = cpu_to_je32(xe->xid);
+       rx.version = cpu_to_je32(1);    /* initial version */
+       rx.xprefix = xprefix;
+       rx.name_len = xe->name_len;
+       rx.value_len = cpu_to_je16(xe->value_len);
+       rx.data_crc = cpu_to_je32(crc32(0, xe->xname, xe->name_len + 1 + xe->value_len));
+       rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(rx) - 4));
+
+       pad_block_if_less_than(sizeof(rx) + xe->name_len + 1 + xe->value_len);
+       full_write(out_fd, &rx, sizeof(rx));
+       full_write(out_fd, xe->xname, xe->name_len + 1 + xe->value_len);
+       padword();
+
+       return xe;
+}
+
+#define XATTRENTRY_HASHSIZE    57
+static xattr_entry_t *find_xattr_entry(int xprefix, char *xname, char *xvalue, int value_len)
+{
+       static xattr_entry_t **xentry_hash = NULL;
+       xattr_entry_t *xe;
+       int index, name_len;
+
+       /* create hash table */
+       if (!xentry_hash)
+               xentry_hash = xcalloc(1, sizeof(xe) * XATTRENTRY_HASHSIZE);
+
+       if (xprefix == JFFS2_XPREFIX_ACL_ACCESS
+           || xprefix == JFFS2_XPREFIX_ACL_DEFAULT)
+               formalize_posix_acl(xvalue, &value_len);
+
+       name_len = strlen(xname);
+       index = (crc32(0, xname, name_len) ^ crc32(0, xvalue, value_len)) % XATTRENTRY_HASHSIZE;
+       for (xe = xentry_hash[index]; xe; xe = xe->next) {
+               if (xe->xprefix == xprefix
+                   && xe->value_len == value_len
+                   && !strcmp(xe->xname, xname)
+                   && !memcmp(xe->xvalue, xvalue, value_len))
+                       break;
+       }
+       if (!xe) {
+               xe = create_xattr_entry(xprefix, xname, xvalue, value_len);
+               xe->next = xentry_hash[index];
+               xentry_hash[index] = xe;
+       }
+       return xe;
+}
+
+static void write_xattr_entry(struct filesystem_entry *e)
+{
+       struct jffs2_raw_xref ref;
+       struct xattr_entry *xe;
+       char xlist[XATTR_BUFFER_SIZE], xvalue[XATTR_BUFFER_SIZE];
+       char *xname, *prefix_str;
+       int i, xprefix, prefix_len;
+       int list_sz, offset, name_len, value_len;
+
+       if (!enable_xattr)
+               return;
+
+       list_sz = llistxattr(e->hostname, xlist, XATTR_BUFFER_SIZE);
+       if (list_sz < 0) {
+               if (verbose)
+                       printf("llistxattr('%s') = %d : %s\n",
+                              e->hostname, errno, strerror(errno));
+               return;
+       }
+
+       for (offset = 0; offset < list_sz; offset += name_len) {
+               xname = xlist + offset;
+               name_len = strlen(xname) + 1;
+
+               for (i = 0; (xprefix = xprefix_tbl[i].xprefix); i++) {
+                       prefix_str = xprefix_tbl[i].string;
+                       prefix_len = xprefix_tbl[i].length;
+                       if (prefix_str[prefix_len - 1] == '.') {
+                               if (!strncmp(xname, prefix_str, prefix_len - 1))
+                                       break;
+                       } else {
+                               if (!strcmp(xname, prefix_str))
+                                       break;
+                       }
+               }
+               if (!xprefix) {
+                       if (verbose)
+                               printf("%s: xattr '%s' is not supported.\n",
+                                      e->hostname, xname);
+                       continue;
+               }
+               if ((enable_xattr & (1 << xprefix)) == 0)
+                       continue;
+
+               value_len = lgetxattr(e->hostname, xname, xvalue, XATTR_BUFFER_SIZE);
+               if (value_len < 0) {
+                       if (verbose)
+                               printf("lgetxattr('%s', '%s') = %d : %s\n",
+                                      e->hostname, xname, errno, strerror(errno));
+                       continue;
+               }
+               xe = find_xattr_entry(xprefix, xname + prefix_len, xvalue, value_len);
+               if (!xe) {
+                       if (verbose)
+                               printf("%s : xattr '%s' was ignored.\n",
+                                      e->hostname, xname);
+                       continue;
+               }
+
+               memset(&ref, 0, sizeof(ref));
+               ref.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+               ref.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF);
+               ref.totlen = cpu_to_je32(sizeof(ref));
+               ref.hdr_crc = cpu_to_je32(crc32(0, &ref, sizeof(struct jffs2_unknown_node) - 4));
+               ref.ino = cpu_to_je32(e->sb.st_ino);
+               ref.xid = cpu_to_je32(xe->xid);
+               ref.node_crc = cpu_to_je32(crc32(0, &ref, sizeof(ref) - 4));
+
+               pad_block_if_less_than(sizeof(ref));
+               full_write(out_fd, &ref, sizeof(ref));
+               padword();
+       }
+}
+
 static void recursive_populate_directory(struct filesystem_entry *dir)
 {
        struct filesystem_entry *e;
@@ -1029,6 +1259,8 @@ static void recursive_populate_directory(struct filesystem_entry *dir)
        if (verbose) {
                printf("%s\n", dir->fullname);
        }
+       write_xattr_entry(dir);         /* for '/' */
+
        e = dir->files;
        while (e) {
 
@@ -1041,6 +1273,7 @@ static void recursive_populate_directory(struct filesystem_entry *dir)
                                                        e->name);
                                }
                                write_pipe(e);
+                               write_xattr_entry(e);
                                break;
                        case S_IFSOCK:
                                if (verbose) {
@@ -1049,6 +1282,7 @@ static void recursive_populate_directory(struct filesystem_entry *dir)
                                                        (int) e->sb.st_uid, (int) e->sb.st_gid, e->name);
                                }
                                write_pipe(e);
+                               write_xattr_entry(e);
                                break;
                        case S_IFIFO:
                                if (verbose) {
@@ -1057,6 +1291,7 @@ static void recursive_populate_directory(struct filesystem_entry *dir)
                                                        (int) e->sb.st_uid, (int) e->sb.st_gid, e->name);
                                }
                                write_pipe(e);
+                               write_xattr_entry(e);
                                break;
                        case S_IFCHR:
                                if (verbose) {
@@ -1066,6 +1301,7 @@ static void recursive_populate_directory(struct filesystem_entry *dir)
                                                        (int) e->sb.st_gid, e->name);
                                }
                                write_special_file(e);
+                               write_xattr_entry(e);
                                break;
                        case S_IFBLK:
                                if (verbose) {
@@ -1075,6 +1311,7 @@ static void recursive_populate_directory(struct filesystem_entry *dir)
                                                        (int) e->sb.st_gid, e->name);
                                }
                                write_special_file(e);
+                               write_xattr_entry(e);
                                break;
                        case S_IFLNK:
                                if (verbose) {
@@ -1084,6 +1321,7 @@ static void recursive_populate_directory(struct filesystem_entry *dir)
                                                        e->link);
                                }
                                write_symlink(e);
+                               write_xattr_entry(e);
                                break;
                        case S_IFREG:
                                if (verbose) {
@@ -1092,6 +1330,7 @@ static void recursive_populate_directory(struct filesystem_entry *dir)
                                                        (int) e->sb.st_uid, (int) e->sb.st_gid, e->name);
                                }
                                write_regular_file(e);
+                               write_xattr_entry(e);
                                break;
                        default:
                                error_msg("Unknown mode %o for %s", e->sb.st_mode,
@@ -1169,6 +1408,9 @@ static struct option long_options[] = {
        {"test-compression", 0, NULL, 't'},
        {"compressor-priority", 1, NULL, 'y'},
        {"incremental", 1, NULL, 'i'},
+       {"with-xattr", 0, NULL, 1000 },
+       {"with-selinux", 0, NULL, 1001 },
+       {"with-posix-acl", 0, NULL, 1002 },
        {NULL, 0, NULL, 0}
 };
 
@@ -1201,6 +1443,9 @@ static char *helptext =
        "  -q, --squash            Squash permissions and owners making all files be owned by root\n"
        "  -U, --squash-uids       Squash owners making all files be owned by root\n"
        "  -P, --squash-perms      Squash permissions on all files\n"
+       "      --with-xattr        stuff all xattr entries into image\n"
+       "      --with-selinux      stuff only SELinux Labels into jffs2 image\n"
+       "      --with-posix-acl    stuff only POSIX ACL entries into jffs2 image\n"
        "  -h, --help              Display this help text\n"
        "  -v, --verbose           Verbose operation\n"
        "  -V, --version           Display version information\n"
@@ -1519,6 +1764,20 @@ int main(int argc, char **argv)
                                        perror_msg_and_die("cannot open (incremental) file");
                                }
                                break;
+                       case 1000:      /* --with-xattr  */
+                               enable_xattr |= (1 << JFFS2_XPREFIX_USER)
+                                               | (1 << JFFS2_XPREFIX_SECURITY)
+                                               | (1 << JFFS2_XPREFIX_ACL_ACCESS)
+                                               | (1 << JFFS2_XPREFIX_ACL_DEFAULT)
+                                               | (1 << JFFS2_XPREFIX_TRUSTED);
+                               break;
+                       case 1001:      /*  --with-selinux  */
+                               enable_xattr |= (1 << JFFS2_XPREFIX_SECURITY);
+                               break;
+                       case 1002:      /*  --with-posix-acl  */
+                               enable_xattr |= (1 << JFFS2_XPREFIX_ACL_ACCESS)
+                                               | (1 << JFFS2_XPREFIX_ACL_DEFAULT);
+                               break;
                }
        }
        if (out_fd == -1) {
index 198597f0e0f7ed45815f15598a5d9f88e5207a73..5715b1f7aa4b9066b975941d483dc7a202096592 100644 (file)
--- a/summary.h
+++ b/summary.h
@@ -45,6 +45,8 @@
 #define JFFS2_SUMMARY_NOSUM_SIZE 0xffffffff
 #define JFFS2_SUMMARY_INODE_SIZE (sizeof(struct jffs2_sum_inode_flash))
 #define JFFS2_SUMMARY_DIRENT_SIZE(x) (sizeof(struct jffs2_sum_dirent_flash) + (x))
+#define JFFS2_SUMMARY_XATTR_SIZE (sizeof(struct jffs2_sum_xattr_flash))
+#define JFFS2_SUMMARY_XREF_SIZE (sizeof(struct jffs2_sum_xref_flash))
 
 /* Summary structures used on flash */
 
@@ -75,11 +77,28 @@ struct jffs2_sum_dirent_flash
        uint8_t name[0];        /* dirent name */
 } __attribute__((packed));
 
+struct jffs2_sum_xattr_flash
+{
+       jint16_t nodetype;      /* == JFFS2_NODETYPE_XATR */
+       jint32_t xid;           /* xattr identifier */
+       jint32_t version;       /* version number */
+       jint32_t offset;        /* offset on jeb */
+       jint32_t totlen;        /* node length */
+} __attribute__((packed));
+
+struct jffs2_sum_xref_flash
+{
+       jint16_t nodetype;      /* == JFFS2_NODETYPE_XREF */
+       jint32_t offset;        /* offset on jeb */
+} __attribute__((packed));
+
 union jffs2_sum_flash
 {
        struct jffs2_sum_unknown_flash u;
        struct jffs2_sum_inode_flash i;
        struct jffs2_sum_dirent_flash d;
+       struct jffs2_sum_xattr_flash x;
+       struct jffs2_sum_xref_flash r;
 };
 
 /* Summary structures used in the memory */
@@ -114,11 +133,30 @@ struct jffs2_sum_dirent_mem
        uint8_t name[0];        /* dirent name */
 } __attribute__((packed));
 
+struct jffs2_sum_xattr_mem
+{
+       union jffs2_sum_mem *next;
+       jint16_t nodetype;
+       jint32_t xid;
+       jint32_t version;
+       jint32_t offset;
+       jint32_t totlen;
+} __attribute__((packed));
+
+struct jffs2_sum_xref_mem
+{
+       union jffs2_sum_mem *next;
+       jint16_t nodetype;
+       jint32_t offset;
+} __attribute__((packed));
+
 union jffs2_sum_mem
 {
        struct jffs2_sum_unknown_mem u;
        struct jffs2_sum_inode_mem i;
        struct jffs2_sum_dirent_mem d;
+       struct jffs2_sum_xattr_mem x;
+       struct jffs2_sum_xref_mem r;
 };
 
 struct jffs2_summary
index b2e5d2e552cdcf0572a9699e6979ec2e22182088..cb8739da024d82f613e358a43a78cc4144412bda 100644 (file)
--- a/sumtool.c
+++ b/sumtool.c
@@ -4,6 +4,7 @@
  *  Copyright (C) 2004 Zoltan Sogor <weth@inf.u-szeged.hu>,
  *                     Ferenc Havasi <havasi@inf.u-szeged.hu>
  *                     University of Szeged, Hungary
+ *                2006 KaiGai Kohei <kaigai@ak.jp.nec.com>
  *
  * $Id: sumtool.c,v 1.9 2006/01/23 08:22:45 havasi Exp $
  *
@@ -442,6 +443,29 @@ void dump_sum_records()
                                break;
                        }
 
+                       case JFFS2_NODETYPE_XATTR: {
+                               struct jffs2_sum_xattr_flash *sxattr_ptr = wpage;
+
+                               sxattr_ptr->nodetype = sum_collected->sum_list_head->x.nodetype;
+                               sxattr_ptr->xid = sum_collected->sum_list_head->x.xid;
+                               sxattr_ptr->version = sum_collected->sum_list_head->x.version;
+                               sxattr_ptr->offset = sum_collected->sum_list_head->x.offset;
+                               sxattr_ptr->totlen = sum_collected->sum_list_head->x.totlen;
+
+                               wpage += JFFS2_SUMMARY_XATTR_SIZE;
+                               break;
+                       }
+
+                       case JFFS2_NODETYPE_XREF: {
+                               struct jffs2_sum_xref_flash *sxref_ptr = wpage;
+
+                               sxref_ptr->nodetype = sum_collected->sum_list_head->r.nodetype;
+                               sxref_ptr->offset = sum_collected->sum_list_head->r.offset;
+
+                               wpage += JFFS2_SUMMARY_XREF_SIZE;
+                               break;
+                       }
+
                        default : {
                                printf("Unknown node type!\n");
                        }
@@ -577,6 +601,16 @@ int add_sum_mem(union jffs2_sum_mem *item)
                        sum_collected->sum_num++;
                        break;
 
+               case JFFS2_NODETYPE_XATTR:
+                       sum_collected->sum_size += JFFS2_SUMMARY_XATTR_SIZE;
+                       sum_collected->sum_num++;
+                       break;
+
+               case JFFS2_NODETYPE_XREF:
+                       sum_collected->sum_size += JFFS2_SUMMARY_XREF_SIZE;
+                       sum_collected->sum_num++;
+                       break;
+
                default:
                        error_msg_and_die("__jffs2_add_sum_mem(): UNKNOWN node type %d\n", je16_to_cpu(item->u.nodetype));
        }
@@ -622,6 +656,37 @@ void add_sum_dirent_mem(union jffs2_node_union *node)
        add_sum_mem((union jffs2_sum_mem *) temp);
 }
 
+void add_sum_xattr_mem(union jffs2_node_union *node)
+{
+       struct jffs2_sum_xattr_mem *temp = (struct jffs2_sum_xattr_mem *)
+                       malloc(sizeof(struct jffs2_sum_xattr_mem));
+       if (!temp)
+               error_msg_and_die("Can't allocate memory for summary information!\n");
+
+       temp->nodetype = node->x.nodetype;
+       temp->xid = node->x.xid;
+       temp->version = node->x.version;
+       temp->offset = cpu_to_je32(data_ofs);
+       temp->totlen = node->x.totlen;
+       temp->next = NULL;
+
+       add_sum_mem((union jffs2_sum_mem *) temp);
+}
+
+void add_sum_xref_mem(union jffs2_node_union *node)
+{
+       struct jffs2_sum_xref_mem *temp = (struct jffs2_sum_xref_mem *)
+                       malloc(sizeof(struct jffs2_sum_xref_mem));
+       if (!temp)
+               error_msg_and_die("Can't allocate memory for summary information!\n");
+
+       temp->nodetype = node->r.nodetype;
+       temp->offset = cpu_to_je32(data_ofs);
+       temp->next = NULL;
+
+       add_sum_mem((union jffs2_sum_mem *) temp);
+}
+
 void write_dirent_to_buff(union jffs2_node_union *node)
 {
        pad_block_if_less_than(je32_to_cpu (node->d.totlen),JFFS2_SUMMARY_DIRENT_SIZE(node->d.nsize));
@@ -639,11 +704,27 @@ void write_inode_to_buff(union jffs2_node_union *node)
        padword();
 }
 
+void write_xattr_to_buff(union jffs2_node_union *node)
+{
+       pad_block_if_less_than(je32_to_cpu(node->x.totlen), JFFS2_SUMMARY_XATTR_SIZE);
+       add_sum_xattr_mem(node);        /* Add xdatum summary mem to summary list */
+       full_write(data_buffer + data_ofs, &(node->x), je32_to_cpu(node->x.totlen));
+       padword();
+}
+
+void write_xref_to_buff(union jffs2_node_union *node)
+{
+       pad_block_if_less_than(je32_to_cpu(node->r.totlen), JFFS2_SUMMARY_XREF_SIZE);
+       add_sum_xref_mem(node);         /* Add xref summary mem to summary list */
+       full_write(data_buffer + data_ofs, &(node->r), je32_to_cpu(node->r.totlen));
+       padword();
+}
+
 void create_summed_image(int inp_size)
 {
        uint8_t *p = file_buffer;
        union jffs2_node_union *node;
-       uint32_t crc;
+       uint32_t crc, length;
        uint16_t type;
        int bitchbitmask = 0;
        int obsolete;
@@ -743,6 +824,56 @@ void create_summed_image(int inp_size)
                                p += PAD(je32_to_cpu (node->d.totlen));
                                break;
 
+                       case JFFS2_NODETYPE_XATTR:
+                               if (je32_to_cpu(node->x.node_crc) == 0xffffffff)
+                                       obsolete = 1;
+                               if (verbose)
+                                       printf("%8s Xdatum     node at 0x%08x, totlen 0x%08x, "
+                                              "#xid  %5u, version %5u\n",
+                                              obsolete ? "Obsolete" : "",
+                                              p - file_buffer, je32_to_cpu (node->x.totlen),
+                                              je32_to_cpu(node->x.xid), je32_to_cpu(node->x.version));
+                               crc = crc32(0, node, sizeof (struct jffs2_raw_xattr) - 4);
+                               if (crc != je32_to_cpu(node->x.node_crc)) {
+                                       printf("Wrong node_crc at 0x%08x, 0x%08x instead of 0x%08x\n",
+                                              p - file_buffer, je32_to_cpu(node->x.node_crc), crc);
+                                       p += PAD(je32_to_cpu (node->x.totlen));
+                                       continue;
+                               }
+                               length = node->x.name_len + 1 + je16_to_cpu(node->x.value_len);
+                               crc = crc32(0, node->x.data, length);
+                               if (crc != je32_to_cpu(node->x.data_crc)) {
+                                       printf("Wrong data_crc at 0x%08x, 0x%08x instead of 0x%08x\n",
+                                              p - file_buffer, je32_to_cpu(node->x.data_crc), crc);
+                                       p += PAD(je32_to_cpu (node->x.totlen));
+                                       continue;
+                               }
+
+                               write_xattr_to_buff(node);
+                               p += PAD(je32_to_cpu (node->x.totlen));
+                               break;
+
+                       case JFFS2_NODETYPE_XREF:
+                               if (je32_to_cpu(node->r.node_crc) == 0xffffffff)
+                                       obsolete = 1;
+                               if (verbose)
+                                       printf("%8s Xref       node at 0x%08x, totlen 0x%08x, "
+                                              "#ino  %5u, xid     %5u\n",
+                                              obsolete ? "Obsolete" : "",
+                                              p - file_buffer, je32_to_cpu(node->r.totlen),
+                                              je32_to_cpu(node->r.ino), je32_to_cpu(node->r.xid));
+                               crc = crc32(0, node, sizeof (struct jffs2_raw_xref) - 4);
+                               if (crc != je32_to_cpu(node->r.node_crc)) {
+                                       printf("Wrong node_crc at 0x%08x, 0x%08x instead of 0x%08x\n",
+                                              p - file_buffer, je32_to_cpu(node->r.node_crc), crc);
+                                       p += PAD(je32_to_cpu (node->r.totlen));
+                                       continue;
+                               }
+
+                               write_xref_to_buff(node);
+                               p += PAD(je32_to_cpu (node->r.totlen));
+                               break;
+
                        case JFFS2_NODETYPE_CLEANMARKER:
                                if (verbose) {
                                        printf ("%8s Cleanmarker     at 0x%08x, totlen 0x%08x\n",