summaryrefslogtreecommitdiffstats
path: root/main/common/jffs2.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/common/jffs2.c')
-rw-r--r--main/common/jffs2.c3412
1 files changed, 1769 insertions, 1643 deletions
diff --git a/main/common/jffs2.c b/main/common/jffs2.c
index 50f0422..f139404 100644
--- a/main/common/jffs2.c
+++ b/main/common/jffs2.c
@@ -1,7 +1,7 @@
/**************************************************************************
*
* Copyright (c) 2013 Alcatel-Lucent
- *
+ *
* Alcatel Lucent licenses this file to You under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. A copy of the License is contained the
@@ -26,7 +26,7 @@
* by Bill Gatliff (bgat@billgatliff.com).
*
*/
-
+
#include "config.h"
#if INCLUDE_JFFS2
@@ -86,9 +86,9 @@
#define S_IWOTH 00002
#define S_IXOTH 00001
-#define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH)
-#define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH)
-#define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH)
+#define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH)
+#define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH)
+#define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH)
#define is_reg(mode) (((mode) & JFFS2_MODE_MASK) == JFFS2_MODE_REG)
#define is_lnk(mode) (((mode) & JFFS2_MODE_MASK) == JFFS2_MODE_LNK)
@@ -97,39 +97,39 @@
#define is_chr(mode) (((mode) & JFFS2_MODE_MASK) == JFFS2_MODE_CHR)
#define is_fifo(mode) (((mode) & JFFS2_MODE_MASK) == JFFS2_MODE_FIFO)
-#define JFFS2_MAGIC 0x1985
+#define JFFS2_MAGIC 0x1985
-#define JFFS2_COMPAT_MASK 0xc000
-#define JFFS2_FEATURE_INCOMPAT 0xc000
-#define JFFS2_FEATURE_ROCOMPAT 0x8000
-#define JFFS2_FEATURE_RWCOMPAT_COPY 0x4000
-#define JFFS2_FEATURE_RWCOMPAT_DELETE 0x0000
+#define JFFS2_COMPAT_MASK 0xc000
+#define JFFS2_FEATURE_INCOMPAT 0xc000
+#define JFFS2_FEATURE_ROCOMPAT 0x8000
+#define JFFS2_FEATURE_RWCOMPAT_COPY 0x4000
+#define JFFS2_FEATURE_RWCOMPAT_DELETE 0x0000
-#define JFFS2_NODE_ACCURATE 0x2000
+#define JFFS2_NODE_ACCURATE 0x2000
-#define JFFS2_NODETYPE_MASK 7
-#define JFFS2_NODETYPE_DIRENT 1
-#define JFFS2_NODETYPE_INODE 2
-#define JFFS2_NODETYPE_CLEANMARKER 3
-#define JFFS2_NODETYPE_PADDING 4
+#define JFFS2_NODETYPE_MASK 7
+#define JFFS2_NODETYPE_DIRENT 1
+#define JFFS2_NODETYPE_INODE 2
+#define JFFS2_NODETYPE_CLEANMARKER 3
+#define JFFS2_NODETYPE_PADDING 4
/* this is a "fake" type, not part of jffs2 proper */
-#define JFFS2_NODETYPE_CLEANREGION 8
+#define JFFS2_NODETYPE_CLEANREGION 8
-#define JFFS2_OBSOLETE_FLAG 1
-#define JFFS2_UNUSED_FLAG 2
+#define JFFS2_OBSOLETE_FLAG 1
+#define JFFS2_UNUSED_FLAG 2
-#define JFFS2_COMPR_NONE 0 /* no compression */
-#define JFFS2_COMPR_ZERO 1 /* data is all zeroes */
-#define JFFS2_COMPR_RTIME 2
-#define JFFS2_COMPR_RUBINMIPS 3
-#define JFFS2_COMPR_COPY 4
-#define JFFS2_COMPR_DYNRUBIN 5
-#define JFFS2_COMPR_ZLIB 6
+#define JFFS2_COMPR_NONE 0 /* no compression */
+#define JFFS2_COMPR_ZERO 1 /* data is all zeroes */
+#define JFFS2_COMPR_RTIME 2
+#define JFFS2_COMPR_RUBINMIPS 3
+#define JFFS2_COMPR_COPY 4
+#define JFFS2_COMPR_DYNRUBIN 5
+#define JFFS2_COMPR_ZLIB 6
-#define JFFS2_FNAME_STR "JFFS2FNAME"
-#define JFFS2_FTOT_STR "JFFS2FTOT"
-#define JFFS2_FSIZE_STR "JFFS2FSIZE"
+#define JFFS2_FNAME_STR "JFFS2FNAME"
+#define JFFS2_FTOT_STR "JFFS2FTOT"
+#define JFFS2_FSIZE_STR "JFFS2FSIZE"
/* TODO: find a better way to deal with char vs. jint8 */
typedef unsigned char jint8;
@@ -137,65 +137,65 @@ typedef unsigned short jint16;
typedef unsigned int jint32;
struct jffs2_unknown_node {
- jint16 magic;
- jint16 nodetype;
- jint32 totlen;
- jint32 hdr_crc;
+ jint16 magic;
+ jint16 nodetype;
+ jint32 totlen;
+ jint32 hdr_crc;
};
struct jffs2_raw_dirent {
- jint16 magic;
- jint16 nodetype;
- jint32 totlen;
- jint32 hdr_crc;
- jint32 pino;
- jint32 version;
- jint32 ino;
- jint32 mctime;
- jint8 nsize;
- jint8 type;
- jint8 unused[2];
- jint32 node_crc;
- jint32 name_crc;
- jint8 name[0];
+ jint16 magic;
+ jint16 nodetype;
+ jint32 totlen;
+ jint32 hdr_crc;
+ jint32 pino;
+ jint32 version;
+ jint32 ino;
+ jint32 mctime;
+ jint8 nsize;
+ jint8 type;
+ jint8 unused[2];
+ jint32 node_crc;
+ jint32 name_crc;
+ jint8 name[0];
};
struct jffs2_raw_inode {
- jint16 magic;
- jint16 nodetype;
- jint32 totlen;
- jint32 hdr_crc;
- jint32 ino;
- jint32 version;
- jint32 mode;
- jint16 uid;
- jint16 gid;
- jint32 isize;
- jint32 atime;
- jint32 mtime;
- jint32 ctime;
- jint32 offset;
- jint32 csize;
- jint32 dsize;
- jint8 compr;
- jint8 usercompr;
- jint16 flags;
- jint32 data_crc;
- jint32 node_crc;
- jint8 data[0];
+ jint16 magic;
+ jint16 nodetype;
+ jint32 totlen;
+ jint32 hdr_crc;
+ jint32 ino;
+ jint32 version;
+ jint32 mode;
+ jint16 uid;
+ jint16 gid;
+ jint32 isize;
+ jint32 atime;
+ jint32 mtime;
+ jint32 ctime;
+ jint32 offset;
+ jint32 csize;
+ jint32 dsize;
+ jint8 compr;
+ jint8 usercompr;
+ jint16 flags;
+ jint32 data_crc;
+ jint32 node_crc;
+ jint8 data[0];
};
struct jffs2_cleanregion_node {
- jint16 magic;
- jint16 nodetype;
- jint32 totlen;
- jint32 physaddr;
+ jint16 magic;
+ jint16 nodetype;
+ jint32 totlen;
+ jint32 physaddr;
};
struct jffs2_umoninfo {
- jint8 quiet;
- jint32 direntsize;
- char direntname[JFFS2_MAXPATH+1];
+ jint8 quiet;
+ jint32 direntsize;
+ char direntname[JFFS2_MAXPATH+1];
};
/*
@@ -240,160 +240,165 @@ struct jffs2_umoninfo {
*/
static const jint32 jffs2_crc32_table[256] = {
- 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
- 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
- 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
- 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
- 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
- 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
- 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
- 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
- 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
- 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
- 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
- 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
- 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
- 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
- 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
- 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
- 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
- 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
- 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
- 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
- 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
- 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
- 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
- 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
- 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
- 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
- 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
- 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
- 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
- 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
- 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
- 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
- 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
- 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
- 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
- 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
- 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
- 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
- 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
- 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
- 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
- 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
- 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
- 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
- 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
- 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
- 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
- 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
- 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
- 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
- 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
- 0x2d02ef8dL
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
};
static jint32
jffs2crc32(jint32 val, const void *ss, int len)
{
- const unsigned char *s = ss;
+ const unsigned char *s = ss;
- while (--len >= 0)
- val = jffs2_crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8);
+ while(--len >= 0) {
+ val = jffs2_crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8);
+ }
- return val;
+ return val;
}
static char *
compr2str(jint8 compr)
{
- switch(compr) {
- case JFFS2_COMPR_NONE:
- return "none";
- case JFFS2_COMPR_ZERO:
- return "zero";
- case JFFS2_COMPR_RTIME:
- return "rtime";
- case JFFS2_COMPR_RUBINMIPS:
- return "rubinmips";
- case JFFS2_COMPR_COPY:
- return "copy";
- case JFFS2_COMPR_DYNRUBIN:
- return "dynrubin";
- case JFFS2_COMPR_ZLIB:
- return "zlib";
- default:
- return "???";
- }
+ switch(compr) {
+ case JFFS2_COMPR_NONE:
+ return "none";
+ case JFFS2_COMPR_ZERO:
+ return "zero";
+ case JFFS2_COMPR_RTIME:
+ return "rtime";
+ case JFFS2_COMPR_RUBINMIPS:
+ return "rubinmips";
+ case JFFS2_COMPR_COPY:
+ return "copy";
+ case JFFS2_COMPR_DYNRUBIN:
+ return "dynrubin";
+ case JFFS2_COMPR_ZLIB:
+ return "zlib";
+ default:
+ return "???";
+ }
}
static void
showUnknown(int nodenum, struct jffs2_unknown_node *u)
{
- printf("Node %3d (%04x=UNKNOWN, size=%ld) 0x%08lx...\n",
- nodenum, u->nodetype, u->totlen, (long)u);
- printf(" type: 0x%04x\n",u->nodetype);
+ printf("Node %3d (%04x=UNKNOWN, size=%ld) 0x%08lx...\n",
+ nodenum, u->nodetype, u->totlen, (long)u);
+ printf(" type: 0x%04x\n",u->nodetype);
}
static void
showPadding(int nodenum, struct jffs2_raw_inode *i)
{
- printf("Node %3d (PADDING, size=%ld) @ 0x%08lx...\n",
- nodenum, i->totlen, (long)i);
+ printf("Node %3d (PADDING, size=%ld) @ 0x%08lx...\n",
+ nodenum, i->totlen, (long)i);
}
static void
showCleanmarker(int nodenum,struct jffs2_raw_inode *i)
{
- printf("Node %3d (CLEANMARKER, size=%ld) @ 0x%08lx...\n",
- nodenum,i->totlen, (long)i);
+ printf("Node %3d (CLEANMARKER, size=%ld) @ 0x%08lx...\n",
+ nodenum,i->totlen, (long)i);
}
static void
showInode(int nodenum,struct jffs2_raw_inode *i)
{
- printf("Node %3d (%04x=INODE, size=%ld) @ 0x%08lx",
- nodenum, i->nodetype, i->totlen, (long)i);
- if (i->dsize)
- printf(" (data at 0x%08lx)",&i->data);
- printf("...\n");
- printf(" ino: 0x%06lx, mode: 0x%06lx, version: 0x%06lx\n",
- i->ino,i->mode,i->version);
- printf(" isize: 0x%06lx, csize: 0x%06lx, dsize: 0x%06lx\n",
- i->isize, i->csize, i->dsize);
- printf(" offset: 0x%06lx, compr: %8s, ucompr: %s\n",
- i->offset,compr2str(i->compr),compr2str(i->usercompr));
+ printf("Node %3d (%04x=INODE, size=%ld) @ 0x%08lx",
+ nodenum, i->nodetype, i->totlen, (long)i);
+ if(i->dsize) {
+ printf(" (data at 0x%08lx)",&i->data);
+ }
+ printf("...\n");
+ printf(" ino: 0x%06lx, mode: 0x%06lx, version: 0x%06lx\n",
+ i->ino,i->mode,i->version);
+ printf(" isize: 0x%06lx, csize: 0x%06lx, dsize: 0x%06lx\n",
+ i->isize, i->csize, i->dsize);
+ printf(" offset: 0x%06lx, compr: %8s, ucompr: %s\n",
+ i->offset,compr2str(i->compr),compr2str(i->usercompr));
}
static void
showDirent(int nodenum, struct jffs2_raw_dirent *d)
{
- jint8 i;
+ jint8 i;
- printf("Node %3d (%04x=DIRENT <\"",nodenum,d->nodetype);
- for(i=0;i<d->nsize;i++)
- putchar(d->name[i]);
- printf("\">, size=%ld)",d->totlen);
- printf(" @ 0x%06lx",(long)d);
- if (d->ino == 0)
- printf(" (deleted)");
- if ((d->nodetype & JFFS2_NODE_ACCURATE) == 0)
- printf(" (obsolete)");
- printf("...\n");
- printf(" ino: 0x%06lx, pino: 0x%06lx, version: 0x%06lx\n",
- d->ino, d->pino, d->version);
- printf(" nsize: 0x%06lx, type: 0x%06lx\n",
- d->nsize, d->type);
+ printf("Node %3d (%04x=DIRENT <\"",nodenum,d->nodetype);
+ for(i=0; i<d->nsize; i++) {
+ putchar(d->name[i]);
+ }
+ printf("\">, size=%ld)",d->totlen);
+ printf(" @ 0x%06lx",(long)d);
+ if(d->ino == 0) {
+ printf(" (deleted)");
+ }
+ if((d->nodetype & JFFS2_NODE_ACCURATE) == 0) {
+ printf(" (obsolete)");
+ }
+ printf("...\n");
+ printf(" ino: 0x%06lx, pino: 0x%06lx, version: 0x%06lx\n",
+ d->ino, d->pino, d->version);
+ printf(" nsize: 0x%06lx, type: 0x%06lx\n",
+ d->nsize, d->type);
}
static void
showCleanregion(int nodenum, struct jffs2_cleanregion_node *c)
{
- printf("Node %3d (%04x=CLEANREGION)...\n",
- nodenum, c->nodetype);
- printf(" physaddr: 0x%06lx, size: %d\n",
- c->physaddr, c->totlen);
+ printf("Node %3d (%04x=CLEANREGION)...\n",
+ nodenum, c->nodetype);
+ printf(" physaddr: 0x%06lx, size: %d\n",
+ c->physaddr, c->totlen);
}
@@ -404,33 +409,34 @@ static int
jzlibcpy(char *src, char *dest, ulong srclen, ulong destlen)
{
#if INCLUDE_JFFS2ZLIB
- z_stream strm;
- int ret;
+ z_stream strm;
+ int ret;
+
+ if((strm.workspace = malloc(zlib_inflate_workspacesize())) == 0) {
+ return(-1);
+ }
- if ((strm.workspace = malloc(zlib_inflate_workspacesize())) == 0)
- return(-1);
+ if(Z_OK != zlib_inflateInit(&strm)) {
+ free(strm.workspace);
+ return -1;
+ }
- if (Z_OK != zlib_inflateInit(&strm)) {
- free(strm.workspace);
- return -1;
- }
-
- strm.next_in = (unsigned char *)src;
- strm.avail_in = srclen;
- strm.total_in = 0;
+ strm.next_in = (unsigned char *)src;
+ strm.avail_in = srclen;
+ strm.total_in = 0;
- strm.next_out = (unsigned char *)dest;
- strm.avail_out = destlen;
- strm.total_out = 0;
+ strm.next_out = (unsigned char *)dest;
+ strm.avail_out = destlen;
+ strm.total_out = 0;
- while((ret = zlib_inflate(&strm, Z_FINISH)) == Z_OK);
+ while((ret = zlib_inflate(&strm, Z_FINISH)) == Z_OK);
- zlib_inflateEnd(&strm);
- free(strm.workspace);
- return(strm.total_out);
+ zlib_inflateEnd(&strm);
+ free(strm.workspace);
+ return(strm.total_out);
#else
- printf("INCLUDE_JFFS2ZLIB not set in config.h, can't decompress\n");
- return -1;
+ printf("INCLUDE_JFFS2ZLIB not set in config.h, can't decompress\n");
+ return -1;
#endif
}
@@ -438,288 +444,308 @@ jzlibcpy(char *src, char *dest, ulong srclen, ulong destlen)
static int
is_accurate_node(struct jffs2_unknown_node *u)
{
- return ((u->magic == JFFS2_MAGIC)
- && (u->nodetype & JFFS2_NODE_ACCURATE)) ? 1 : 0;
+ return ((u->magic == JFFS2_MAGIC)
+ && (u->nodetype & JFFS2_NODE_ACCURATE)) ? 1 : 0;
}
static int
is_cleanmarker(struct jffs2_unknown_node *u)
{
- jint16 nodetype = u->nodetype & JFFS2_NODETYPE_MASK;
- return nodetype == JFFS2_NODETYPE_CLEANMARKER ? 1 : 0;
+ jint16 nodetype = u->nodetype & JFFS2_NODETYPE_MASK;
+ return nodetype == JFFS2_NODETYPE_CLEANMARKER ? 1 : 0;
}
static int
is_padding(struct jffs2_unknown_node *u)
{
- jint16 nodetype = u->nodetype & JFFS2_NODETYPE_MASK;
- return nodetype == JFFS2_NODETYPE_PADDING ? 1 : 0;
+ jint16 nodetype = u->nodetype & JFFS2_NODETYPE_MASK;
+ return nodetype == JFFS2_NODETYPE_PADDING ? 1 : 0;
}
static int
is_inode(struct jffs2_unknown_node *u)
{
- jint16 nodetype = u->nodetype & JFFS2_NODETYPE_MASK;
- return nodetype == JFFS2_NODETYPE_INODE ? 1 : 0;
+ jint16 nodetype = u->nodetype & JFFS2_NODETYPE_MASK;
+ return nodetype == JFFS2_NODETYPE_INODE ? 1 : 0;
}
static int
is_dirent(struct jffs2_unknown_node *u)
{
- jint16 nodetype = u->nodetype & JFFS2_NODETYPE_MASK;
- return nodetype == JFFS2_NODETYPE_DIRENT ? 1 : 0;
+ jint16 nodetype = u->nodetype & JFFS2_NODETYPE_MASK;
+ return nodetype == JFFS2_NODETYPE_DIRENT ? 1 : 0;
}
static int
is_deleted_dirent(struct jffs2_unknown_node *u)
{
- struct jffs2_raw_dirent *d;
+ struct jffs2_raw_dirent *d;
- if (is_dirent(u)) {
- d = (struct jffs2_raw_dirent *)u;
- if (d->ino == 0)
- return 1;
- }
+ if(is_dirent(u)) {
+ d = (struct jffs2_raw_dirent *)u;
+ if(d->ino == 0) {
+ return 1;
+ }
+ }
- return 0;
+ return 0;
}
static int
is_cleanregion(struct jffs2_unknown_node *u)
{
- return u->nodetype == JFFS2_NODETYPE_CLEANREGION ? 1 : 0;
+ return u->nodetype == JFFS2_NODETYPE_CLEANREGION ? 1 : 0;
}
static struct jffs2_unknown_node *
allocCleanRegion(jint32 base, jint32 size)
{
- struct jffs2_cleanregion_node *c;
+ struct jffs2_cleanregion_node *c;
- c = (struct jffs2_cleanregion_node*)malloc(sizeof(*c));
- if (c) {
- memset((void*)c, 0, sizeof(*c));
- c->nodetype = JFFS2_NODETYPE_CLEANREGION;
- c->physaddr = base;
- c->totlen = size;
- }
- else
- printf("%s: malloc() failed\n", __func__);
- return (struct jffs2_unknown_node*)c;
+ c = (struct jffs2_cleanregion_node *)malloc(sizeof(*c));
+ if(c) {
+ memset((void *)c, 0, sizeof(*c));
+ c->nodetype = JFFS2_NODETYPE_CLEANREGION;
+ c->physaddr = base;
+ c->totlen = size;
+ } else {
+ printf("%s: malloc() failed\n", __func__);
+ }
+ return (struct jffs2_unknown_node *)c;
}
static jint32
calcHdrCrc(struct jffs2_unknown_node *u)
{
- return jffs2crc32(0, (void*)u,
- sizeof(*u) - sizeof(u->hdr_crc));
+ return jffs2crc32(0, (void *)u,
+ sizeof(*u) - sizeof(u->hdr_crc));
}
static jint32
calcInodeCrc(struct jffs2_raw_inode *i)
{
- return jffs2crc32(0, (void*)i,
- sizeof(*i) - sizeof(i->node_crc)
- - sizeof(i->data_crc));
+ return jffs2crc32(0, (void *)i,
+ sizeof(*i) - sizeof(i->node_crc)
+ - sizeof(i->data_crc));
}
static jint32
calcDirentCrc(struct jffs2_raw_dirent *d)
{
- return jffs2crc32(0, (void*)d,
- sizeof(*d) - sizeof(d->node_crc)
- - sizeof(d->name_crc));
+ return jffs2crc32(0, (void *)d,
+ sizeof(*d) - sizeof(d->node_crc)
+ - sizeof(d->name_crc));
}
static jint32
calcDataCrc(void *data, int len)
{
- return jffs2crc32(0, data, len);
+ return jffs2crc32(0, data, len);
}
static int jffs2_verify_crc = 0;
static struct jffs2_unknown_node *
findRawNode(ulong jaddr, ulong jlen,
- ulong *newjaddr, ulong *newjlen)
-{
- struct jffs2_unknown_node *u;
- jint32 crc;
- ulong size = 0;
- long adj;
-
- while (jlen && !gotachar()) {
-
- adj = ulceil(jaddr, 4) - jaddr;
- jaddr += adj;
- jlen -= adj;
-
- u = (struct jffs2_unknown_node *)jaddr;
+ ulong *newjaddr, ulong *newjlen)
+{
+ struct jffs2_unknown_node *u;
+ jint32 crc;
+ ulong size = 0;
+ long adj;
+
+ while(jlen && !gotachar()) {
+
+ adj = ulceil(jaddr, 4) - jaddr;
+ jaddr += adj;
+ jlen -= adj;
+
+ u = (struct jffs2_unknown_node *)jaddr;
+
+ if(is_accurate_node(u)) {
+
+ if(jffs2_verify_crc) {
+
+ crc = calcHdrCrc(u);
+ if(crc != u->hdr_crc)
+ printf("hdr_crc @ 0x%x: "
+ "calculated 0x%x read 0x%x (ignored)\n",
+ u, crc, u->hdr_crc);
+
+ if(is_dirent(u)) {
+ struct jffs2_raw_dirent *d;
+
+ d = (struct jffs2_raw_dirent *)u;
+ crc = calcDirentCrc(d);
+ if(crc != d->node_crc)
+ printf("dirent node_crc @ 0x%x: "
+ "calculated 0x%x read 0x%x (ignored)\n",
+ d, crc, d->node_crc);
+
+ crc = calcDataCrc(d->name, d->nsize);
+ if(crc != d->name_crc)
+ printf("dirent name_crc @ 0x%x: "
+ "calculated 0x%x read 0x%x (ignored)\n",
+ d, crc, d->name_crc);
+ }
+
+ else if(is_inode(u)) {
+ struct jffs2_raw_inode *i;
+
+ i = (struct jffs2_raw_inode *)u;
+ crc = calcInodeCrc(i);
+ if(crc != i->node_crc)
+ printf("inode node_crc @ 0x%x: "
+ "calculated 0x%x read 0x%x (ignored)\n",
+ i, crc, i->node_crc);
+
+ crc = calcDataCrc(i->data,
+ (i->compr != JFFS2_COMPR_NONE) ?
+ i->csize : i->dsize);
+ if(crc != i->data_crc)
+ printf("inode data_crc @ 0x%x: "
+ "calculated 0x%x read 0x%x (ignored)\n",
+ i, crc, i->data_crc);
+ }
+ }
+
+ if(newjaddr) {
+ *newjaddr = jaddr;
+ }
+ if(newjlen) {
+ *newjlen = jlen;
+ }
+ return u;
+ }
+
+ else {
+ /* manufacture a node representing unused memory */
+
+ /* TODO: more-carefully verify that this memory is truly
+ "unused", e.g. make sure there is a valid cleanmarker at the
+ beginning of the flash block, we don't span the end of a
+ flash section, etc. */
+
+ /* TODO: it would be much faster to use a binary search for ff's
+ in the current flash sector, rather than a linear search for
+ them */
+
+ for(size = 0; jlen && !gotachar()
+ && *(ulong *)jaddr == 0xffffffffUL;
+ size += 4) {
+ jaddr += 4;
+ jlen -= 4;
+ }
+
+ if(size > sizeof(struct jffs2_raw_inode)) {
+ if(newjaddr) {
+ *newjaddr = jaddr - size;
+ }
+ if(newjlen) {
+ *newjlen = jlen + size;
+ }
+ return allocCleanRegion((ulong)u, size);
+ }
+
+ if(jlen) {
+ jaddr += 4;
+ jlen -= 4;
+ }
+ }
+ }
- if (is_accurate_node(u)) {
-
- if (jffs2_verify_crc) {
-
- crc = calcHdrCrc(u);
- if (crc != u->hdr_crc)
- printf("hdr_crc @ 0x%x: "
- "calculated 0x%x read 0x%x (ignored)\n",
- u, crc, u->hdr_crc);
-
- if (is_dirent(u)) {
- struct jffs2_raw_dirent *d;
-
- d = (struct jffs2_raw_dirent*)u;
- crc = calcDirentCrc(d);
- if (crc != d->node_crc)
- printf("dirent node_crc @ 0x%x: "
- "calculated 0x%x read 0x%x (ignored)\n",
- d, crc, d->node_crc);
-
- crc = calcDataCrc(d->name, d->nsize);
- if (crc != d->name_crc)
- printf("dirent name_crc @ 0x%x: "
- "calculated 0x%x read 0x%x (ignored)\n",
- d, crc, d->name_crc);
- }
-
- else if (is_inode(u)) {
- struct jffs2_raw_inode *i;
-
- i = (struct jffs2_raw_inode*)u;
- crc = calcInodeCrc(i);
- if (crc != i->node_crc)
- printf("inode node_crc @ 0x%x: "
- "calculated 0x%x read 0x%x (ignored)\n",
- i, crc, i->node_crc);
-
- crc = calcDataCrc(i->data,
- (i->compr != JFFS2_COMPR_NONE) ?
- i->csize : i->dsize);
- if (crc != i->data_crc)
- printf("inode data_crc @ 0x%x: "
- "calculated 0x%x read 0x%x (ignored)\n",
- i, crc, i->data_crc);
- }
- }
-
- if (newjaddr) *newjaddr = jaddr;
- if (newjlen) *newjlen = jlen;
- return u;
- }
-
- else {
- /* manufacture a node representing unused memory */
-
- /* TODO: more-carefully verify that this memory is truly
- "unused", e.g. make sure there is a valid cleanmarker at the
- beginning of the flash block, we don't span the end of a
- flash section, etc. */
-
- /* TODO: it would be much faster to use a binary search for ff's
- in the current flash sector, rather than a linear search for
- them */
-
- for (size = 0; jlen && !gotachar()
- && *(ulong*)jaddr == 0xffffffffUL;
- size += 4) {
- jaddr += 4;
- jlen -= 4;
- }
-
- if (size > sizeof(struct jffs2_raw_inode)) {
- if (newjaddr) *newjaddr = jaddr - size;
- if (newjlen) *newjlen = jlen + size;
- return allocCleanRegion((ulong)u, size);
- }
-
- if (jlen) {
- jaddr += 4;
- jlen -= 4;
- }
- }
- }
-
- return NULL;
+ return NULL;
}
struct jffs2_unknown_node_list {
- struct jffs2_unknown_node_list *next;
- struct jffs2_unknown_node_list *prev;
- ulong nodenum;
- struct jffs2_unknown_node *u;
+ struct jffs2_unknown_node_list *next;
+ struct jffs2_unknown_node_list *prev;
+ ulong nodenum;
+ struct jffs2_unknown_node *u;
};
static int
-is_empty_list (struct jffs2_unknown_node_list *l)
+is_empty_list(struct jffs2_unknown_node_list *l)
{
- if ((l == NULL) || (l->next == NULL)
- || (l->next->next == NULL)) return 1;
- return 0;
+ if((l == NULL) || (l->next == NULL)
+ || (l->next->next == NULL)) {
+ return 1;
+ }
+ return 0;
}
static struct jffs2_unknown_node_list *
allocListNode(ulong nodenum, struct jffs2_unknown_node *u)
{
- struct jffs2_unknown_node_list *cu;
-
- cu = (struct jffs2_unknown_node_list*)malloc(sizeof(*cu));
- if (cu) {
- cu->next = NULL;
- cu->prev = NULL;
- cu->u = u;
- cu->nodenum = nodenum;
- }
- else {
- /* TODO: report/handle allocation failure */
- printf("allocListNode: malloc() failed\n");
- }
- return cu;
+ struct jffs2_unknown_node_list *cu;
+
+ cu = (struct jffs2_unknown_node_list *)malloc(sizeof(*cu));
+ if(cu) {
+ cu->next = NULL;
+ cu->prev = NULL;
+ cu->u = u;
+ cu->nodenum = nodenum;
+ } else {
+ /* TODO: report/handle allocation failure */
+ printf("allocListNode: malloc() failed\n");
+ }
+ return cu;
}
static struct jffs2_unknown_node_list *
removeNodeFromList(struct jffs2_unknown_node_list *u)
{
- if (u->prev != NULL)
- u->prev->next = u->next;
- if (u->next != NULL)
- u->next->prev = u->prev;
- return u;
+ if(u->prev != NULL) {
+ u->prev->next = u->next;
+ }
+ if(u->next != NULL) {
+ u->next->prev = u->prev;
+ }
+ return u;
}
static int
delListNode(struct jffs2_unknown_node_list *u)
{
- removeNodeFromList(u);
- if (u->u != NULL && is_cleanregion(u->u))
- free(u->u);
- free(u);
- return 0;
+ removeNodeFromList(u);
+ if(u->u != NULL && is_cleanregion(u->u)) {
+ free(u->u);
+ }
+ free(u);
+ return 0;
}
static struct jffs2_unknown_node_list *
initNodeList(struct jffs2_unknown_node_list **a)
{
- /* create "sentinel" nodes */
- *a = allocListNode(-1, NULL);
- if (*a == NULL) return NULL;
- (*a)->next = allocListNode(-1, NULL);
- if ((*a)->next == NULL) return NULL;
- (*a)->next->prev = *a;
+ /* create "sentinel" nodes */
+ *a = allocListNode(-1, NULL);
+ if(*a == NULL) {
+ return NULL;
+ }
+ (*a)->next = allocListNode(-1, NULL);
+ if((*a)->next == NULL) {
+ return NULL;
+ }
+ (*a)->next->prev = *a;
- return *a;
+ return *a;
}
static struct jffs2_unknown_node_list *
discardNodeList(struct jffs2_unknown_node_list *list)
{
- if (list == NULL)
+ if(list == NULL) {
+ return NULL;
+ }
+ while(list->prev != NULL) {
+ list = list->prev;
+ }
+ while(list->next != NULL) {
+ delListNode(list->next);
+ }
+ delListNode(list);
return NULL;
- while (list->prev != NULL)
- list = list->prev;
- while (list->next != NULL)
- delListNode(list->next);
- delListNode(list);
- return NULL;
}
@@ -727,200 +753,206 @@ discardNodeList(struct jffs2_unknown_node_list *list)
static struct jffs2_unknown_node_list *
insertListNodeAfter(struct jffs2_unknown_node_list *after,
- struct jffs2_unknown_node_list *n)
+ struct jffs2_unknown_node_list *n)
{
- n->prev = after;
- n->next = after->next;
- after->next->prev = n;
- after->next = n;
+ n->prev = after;
+ n->next = after->next;
+ after->next->prev = n;
+ after->next = n;
- return n;
+ return n;
}
static int
scanMedium(ulong jaddr, ulong jlen,
- struct jffs2_unknown_node_list *list,
- void (*progress)(int percent))
-{
- struct jffs2_unknown_node *u;
- struct jffs2_unknown_node_list *n;
- ulong nodetot = 0UL;
- ulong jlen_orig = jlen;
-
- if (progress) {
- printf("scanning JFFS2 medium "
- "at 0x%x, %d bytes...\n",
- jaddr, jlen);
- progress(0);
- }
-
- while (!gotachar()
- && jlen
- && (u = findRawNode(jaddr, jlen, &jaddr, &jlen))) {
-
- if (progress)
- progress(((unsigned long long)(jlen_orig - jlen) * 100)
- / jlen_orig);
-
- if (is_inode(u)
- || is_dirent(u)
- || is_deleted_dirent(u)
- || is_cleanmarker(u)
- || is_cleanregion(u)) {
-
- n = allocListNode(nodetot++, u);
- if (n != NULL)
- insertListNodeAfter(list, n);
- else {
- printf("%s: allocListNode returned NULL (fatal)\n",
- __func__);
- return -1;
- }
- }
- else printf("%s: unrecognized nodetype %x (ignored)\n",
- __func__, u->nodetype & JFFS2_NODETYPE_MASK);
-
- jlen -= u->totlen;
- jaddr += u->totlen;
- }
-
- return nodetot;
-}
+ struct jffs2_unknown_node_list *list,
+ void (*progress)(int percent))
+{
+ struct jffs2_unknown_node *u;
+ struct jffs2_unknown_node_list *n;
+ ulong nodetot = 0UL;
+ ulong jlen_orig = jlen;
+
+ if(progress) {
+ printf("scanning JFFS2 medium "
+ "at 0x%x, %d bytes...\n",
+ jaddr, jlen);
+ progress(0);
+ }
-static int
-formatMedium (ulong jaddr, ulong jlen,
- void (*progress)(int percent))
-{
- int ret;
- int start, end, sect, size;
- uchar *addr;
- struct jffs2_unknown_node cm = {
- .magic = JFFS2_MAGIC,
- .nodetype = (JFFS2_NODETYPE_CLEANMARKER
- | JFFS2_FEATURE_RWCOMPAT_DELETE
- | JFFS2_NODE_ACCURATE),
- .totlen = sizeof(struct jffs2_unknown_node),
- };
-
- if (!jlen) return -1;
-
- cm.hdr_crc = calcHdrCrc(&cm);
-
- if (addrtosector((uchar*)jaddr, &start,
- NULL, NULL)) {
- printf("%s: invalid starting address %x (error, abort)\n",
- __func__, jaddr);
- return -1;
- }
+ while(!gotachar()
+ && jlen
+ && (u = findRawNode(jaddr, jlen, &jaddr, &jlen))) {
+
+ if(progress)
+ progress(((unsigned long long)(jlen_orig - jlen) * 100)
+ / jlen_orig);
+
+ if(is_inode(u)
+ || is_dirent(u)
+ || is_deleted_dirent(u)
+ || is_cleanmarker(u)
+ || is_cleanregion(u)) {
+
+ n = allocListNode(nodetot++, u);
+ if(n != NULL) {
+ insertListNodeAfter(list, n);
+ } else {
+ printf("%s: allocListNode returned NULL (fatal)\n",
+ __func__);
+ return -1;
+ }
+ } else printf("%s: unrecognized nodetype %x (ignored)\n",
+ __func__, u->nodetype & JFFS2_NODETYPE_MASK);
+
+ jlen -= u->totlen;
+ jaddr += u->totlen;
+ }
- if (addrtosector((uchar*)(jaddr + jlen - 1), &end,
- NULL, NULL)) {
- printf("%s: invalid ending address %x (error, abort)\n",
- __func__, jaddr + jlen - 1);
- return -1;
- }
+ return nodetot;
+}
- ret = sectortoaddr(start, NULL, (uchar**)(&addr));
- if (ret || ((ulong)addr != jaddr)) {
- printf("%s: must start at a sector boundary (abort)\n",
- __func__);
- return -1;
- }
+static int
+formatMedium(ulong jaddr, ulong jlen,
+ void (*progress)(int percent))
+{
+ int ret;
+ int start, end, sect, size;
+ uchar *addr;
+ struct jffs2_unknown_node cm = {
+ .magic = JFFS2_MAGIC,
+ .nodetype = (JFFS2_NODETYPE_CLEANMARKER
+ | JFFS2_FEATURE_RWCOMPAT_DELETE
+ | JFFS2_NODE_ACCURATE),
+ .totlen = sizeof(struct jffs2_unknown_node),
+ };
+
+ if(!jlen) {
+ return -1;
+ }
- ret = sectortoaddr(end, &size, (uchar**)(&addr));
- if (ret || ((ulong)(addr + size) != (jaddr + jlen))) {
- printf("%s: must end at a sector boundary (abort)\n",
- __func__);
- return -1;
- }
+ cm.hdr_crc = calcHdrCrc(&cm);
- printf("formatting JFFS2 medium "
- "at 0x%x, %d sectors, %d bytes...\n",
- jaddr, end - start, jlen);
+ if(addrtosector((uchar *)jaddr, &start,
+ NULL, NULL)) {
+ printf("%s: invalid starting address %x (error, abort)\n",
+ __func__, jaddr);
+ return -1;
+ }
- for (sect = start; sect < end; sect++) {
-
- if (progress)
- progress(((sect - start) * 100) / (end - start));
-
- if ((ret = AppFlashErase(sect)) != 1) {
- printf("%s: error %d from AppFlashErase, "
- "sector %d (abort)\n",
- __func__, ret, sect);
- return -1;
+ if(addrtosector((uchar *)(jaddr + jlen - 1), &end,
+ NULL, NULL)) {
+ printf("%s: invalid ending address %x (error, abort)\n",
+ __func__, jaddr + jlen - 1);
+ return -1;
}
-
- if ((ret = sectortoaddr(sect, &size, (uchar**)(&addr))) != 0) {
- printf("%s: error %d from sectortoaddr(%d, NULL, &addr) (abort)\n",
- __func__, ret, sect);
- return -1;
+
+ ret = sectortoaddr(start, NULL, (uchar **)(&addr));
+ if(ret || ((ulong)addr != jaddr)) {
+ printf("%s: must start at a sector boundary (abort)\n",
+ __func__);
+ return -1;
}
-
- if (size < sizeof(cm)) {
- printf("%s: size of sector %d "
- "is smaller than a CLEANMARKER (abort)\n",
- __func__, sect);
- return -1;
+
+ ret = sectortoaddr(end, &size, (uchar **)(&addr));
+ if(ret || ((ulong)(addr + size) != (jaddr + jlen))) {
+ printf("%s: must end at a sector boundary (abort)\n",
+ __func__);
+ return -1;
}
-
- if ((ret = AppFlashWrite(addr, (void*)&cm, cm.totlen)) != 0) {
- printf("%s: error %d from AppFlashWrite, sector %d (abort)\n",
- __func__, ret, sect);
- return -1;
+
+ printf("formatting JFFS2 medium "
+ "at 0x%x, %d sectors, %d bytes...\n",
+ jaddr, end - start, jlen);
+
+ for(sect = start; sect < end; sect++) {
+
+ if(progress) {
+ progress(((sect - start) * 100) / (end - start));
+ }
+
+ if((ret = AppFlashErase(sect)) != 1) {
+ printf("%s: error %d from AppFlashErase, "
+ "sector %d (abort)\n",
+ __func__, ret, sect);
+ return -1;
+ }
+
+ if((ret = sectortoaddr(sect, &size, (uchar **)(&addr))) != 0) {
+ printf("%s: error %d from sectortoaddr(%d, NULL, &addr) (abort)\n",
+ __func__, ret, sect);
+ return -1;
+ }
+
+ if(size < sizeof(cm)) {
+ printf("%s: size of sector %d "
+ "is smaller than a CLEANMARKER (abort)\n",
+ __func__, sect);
+ return -1;
+ }
+
+ if((ret = AppFlashWrite(addr, (void *)&cm, cm.totlen)) != 0) {
+ printf("%s: error %d from AppFlashWrite, sector %d (abort)\n",
+ __func__, ret, sect);
+ return -1;
+ }
}
- }
- return 0;
+ return 0;
}
static int
showNode(ulong nodenum, struct jffs2_unknown_node *u)
{
- if (is_inode(u))
- showInode(nodenum, (struct jffs2_raw_inode*)u);
- else if (is_dirent(u) || is_deleted_dirent(u))
- showDirent(nodenum, (struct jffs2_raw_dirent*)u);
- else if (is_cleanmarker(u))
- showCleanmarker(nodenum, (struct jffs2_raw_inode*)u);
- else if (is_cleanregion(u))
- showCleanregion(nodenum, (struct jffs2_cleanregion_node*)u);
- else if (is_padding(u))
- showPadding(nodenum, (struct jffs2_raw_inode*)u);
- else showUnknown(nodenum, u);
- return 0;
+ if(is_inode(u)) {
+ showInode(nodenum, (struct jffs2_raw_inode *)u);
+ } else if(is_dirent(u) || is_deleted_dirent(u)) {
+ showDirent(nodenum, (struct jffs2_raw_dirent *)u);
+ } else if(is_cleanmarker(u)) {
+ showCleanmarker(nodenum, (struct jffs2_raw_inode *)u);
+ } else if(is_cleanregion(u)) {
+ showCleanregion(nodenum, (struct jffs2_cleanregion_node *)u);
+ } else if(is_padding(u)) {
+ showPadding(nodenum, (struct jffs2_raw_inode *)u);
+ } else {
+ showUnknown(nodenum, u);
+ }
+ return 0;
}
static struct jffs2_unknown_node_list *
findNodeOfType(struct jffs2_unknown_node_list *list,
- jint16 nodetype)
-{
- while (list != NULL && !gotachar()) {
- if (list->u != NULL
- && ((nodetype == JFFS2_NODETYPE_MASK)
- || ((list->u->nodetype & JFFS2_NODETYPE_MASK) == nodetype)))
- return list;
- list = list->next;
- }
-
- return NULL;
+ jint16 nodetype)
+{
+ while(list != NULL && !gotachar()) {
+ if(list->u != NULL
+ && ((nodetype == JFFS2_NODETYPE_MASK)
+ || ((list->u->nodetype & JFFS2_NODETYPE_MASK) == nodetype))) {
+ return list;
+ }
+ list = list->next;
+ }
+
+ return NULL;
}
static struct jffs2_unknown_node_list *
findCleanRegion(struct jffs2_unknown_node_list *list,
- ulong minsize)
+ ulong minsize)
{
- while (list != NULL && !gotachar()) {
- if (list->u != NULL
- && is_cleanregion(list->u)) {
-
- if (list->u->totlen >= minsize)
- return list;
+ while(list != NULL && !gotachar()) {
+ if(list->u != NULL
+ && is_cleanregion(list->u)) {
+
+ if(list->u->totlen >= minsize) {
+ return list;
+ }
+ }
+ list = list->next;
}
- list = list->next;
- }
-
- return NULL;
+
+ return NULL;
}
/*
@@ -938,33 +970,35 @@ findCleanRegion(struct jffs2_unknown_node_list *list,
*/
static struct jffs2_unknown_node_list *
findInode(struct jffs2_unknown_node_list *list,
- jint32 ino, jint32 version)
-{
- struct jffs2_raw_inode *i;
- struct jffs2_unknown_node_list *ulatest = NULL;
-
- while (list != NULL && !gotachar()
- && (list = findNodeOfType(list, JFFS2_NODETYPE_INODE)) != NULL) {
-
- i = (struct jffs2_raw_inode*)list->u;
- if (i->ino == ino) {
- if (version != -1 && version == i->version)
- return list;
- else if (version == -1) {
- if (ulatest == NULL)
- ulatest = list;
- else if (i->version > ((struct jffs2_raw_inode*)(ulatest->u))->version)
- ulatest = list;
- }
+ jint32 ino, jint32 version)
+{
+ struct jffs2_raw_inode *i;
+ struct jffs2_unknown_node_list *ulatest = NULL;
+
+ while(list != NULL && !gotachar()
+ && (list = findNodeOfType(list, JFFS2_NODETYPE_INODE)) != NULL) {
+
+ i = (struct jffs2_raw_inode *)list->u;
+ if(i->ino == ino) {
+ if(version != -1 && version == i->version) {
+ return list;
+ } else if(version == -1) {
+ if(ulatest == NULL) {
+ ulatest = list;
+ } else if(i->version > ((struct jffs2_raw_inode *)(ulatest->u))->version) {
+ ulatest = list;
+ }
+ }
+ }
+
+ list = list->next;
}
- list = list->next;
- }
-
- if (version == -1 && ulatest != NULL)
- return ulatest;
+ if(version == -1 && ulatest != NULL) {
+ return ulatest;
+ }
- return NULL;
+ return NULL;
}
/*
@@ -975,28 +1009,29 @@ findInode(struct jffs2_unknown_node_list *list,
*/
static struct jffs2_unknown_node_list *
findNextMatchingDirent(struct jffs2_unknown_node_list *list,
- jint32 pino, jint32 ino, char *name)
+ jint32 pino, jint32 ino, char *name)
{
- struct jffs2_raw_dirent *d;
+ struct jffs2_raw_dirent *d;
- while (!gotachar()
- && (list = findNodeOfType(list, JFFS2_NODETYPE_DIRENT)) != NULL) {
-
- d = (struct jffs2_raw_dirent*)list->u;
-
- if ((pino == -1 || (pino == d->pino))
- && (ino == -1 || (ino == d->ino))) {
-
- if ((name == NULL)
- || ((strlen(name) == d->nsize)
- && !memcmp((char*)name, (char*)(d->name), d->nsize)))
- return list;
- }
+ while(!gotachar()
+ && (list = findNodeOfType(list, JFFS2_NODETYPE_DIRENT)) != NULL) {
+
+ d = (struct jffs2_raw_dirent *)list->u;
+
+ if((pino == -1 || (pino == d->pino))
+ && (ino == -1 || (ino == d->ino))) {
+
+ if((name == NULL)
+ || ((strlen(name) == d->nsize)
+ && !memcmp((char *)name, (char *)(d->name), d->nsize))) {
+ return list;
+ }
+ }
- list = list->next;
- }
+ list = list->next;
+ }
- return NULL;
+ return NULL;
}
/*
@@ -1006,346 +1041,374 @@ findNextMatchingDirent(struct jffs2_unknown_node_list *list,
*/
static struct jffs2_unknown_node_list *
findMatchingDirent(struct jffs2_unknown_node_list *list,
- jint32 pino, jint32 ino, char *name)
-{
- struct jffs2_unknown_node_list *u, *uret;
- struct jffs2_raw_dirent *d, *dret;
-
- for (uret = NULL, u = list; u != NULL
- && ((u = findNextMatchingDirent(u, pino, ino, name)) != NULL);
- u = u->next) {
-
- if (uret == NULL) {
- uret = u;
- continue;
- }
-
- dret = (struct jffs2_raw_dirent*)uret->u;
- d = (struct jffs2_raw_dirent*)u->u;
-
- if (d->version > dret->version)
- uret = u;
- }
-
- if (uret == NULL)
- return NULL;
+ jint32 pino, jint32 ino, char *name)
+{
+ struct jffs2_unknown_node_list *u, *uret;
+ struct jffs2_raw_dirent *d, *dret;
- if (is_deleted_dirent(uret->u))
- return NULL;
+ for(uret = NULL, u = list; u != NULL
+ && ((u = findNextMatchingDirent(u, pino, ino, name)) != NULL);
+ u = u->next) {
- return uret;
+ if(uret == NULL) {
+ uret = u;
+ continue;
+ }
+
+ dret = (struct jffs2_raw_dirent *)uret->u;
+ d = (struct jffs2_raw_dirent *)u->u;
+
+ if(d->version > dret->version) {
+ uret = u;
+ }
+ }
+
+ if(uret == NULL) {
+ return NULL;
+ }
+
+ if(is_deleted_dirent(uret->u)) {
+ return NULL;
+ }
+
+ return uret;
}
static struct jffs2_unknown_node_list *
findNodeOfTypeRange(struct jffs2_unknown_node_list *list,
- jint16 nodetype,
- char *pino,
- char *ino)
+ jint16 nodetype,
+ char *pino,
+ char *ino)
{
- struct jffs2_raw_dirent *d;
- struct jffs2_raw_inode *i;
-
- while (!gotachar()
- && (list = findNodeOfType(list, nodetype)) != NULL) {
-
- if (is_dirent(list->u)) {
- d = (struct jffs2_raw_dirent*)(list->u);
- if ((pino == NULL || inRange(pino, d->pino))
- && (ino == NULL || inRange(ino, d->ino)))
- return list;
- }
-
- else if (is_inode(list->u)) {
- i = (struct jffs2_raw_inode*)(list->u);
- if (ino == NULL || inRange(ino, i->ino))
- return list;
+ struct jffs2_raw_dirent *d;
+ struct jffs2_raw_inode *i;
+
+ while(!gotachar()
+ && (list = findNodeOfType(list, nodetype)) != NULL) {
+
+ if(is_dirent(list->u)) {
+ d = (struct jffs2_raw_dirent *)(list->u);
+ if((pino == NULL || inRange(pino, d->pino))
+ && (ino == NULL || inRange(ino, d->ino))) {
+ return list;
+ }
+ }
+
+ else if(is_inode(list->u)) {
+ i = (struct jffs2_raw_inode *)(list->u);
+ if(ino == NULL || inRange(ino, i->ino)) {
+ return list;
+ }
+ }
+
+ list = list->next;
}
-
- list = list->next;
- }
-
- return NULL;
+
+ return NULL;
}
static void
showInodeType(int type)
{
- if (is_reg(type)) printf("-");
- else if (is_dir(type)) printf("d");
- else if (is_lnk(type)) printf("l");
- else if (is_blk(type)) printf("b");
- else if (is_chr(type)) printf("c");
- else if (is_fifo(type)) printf("p");
- else printf("?");
+ if(is_reg(type)) {
+ printf("-");
+ } else if(is_dir(type)) {
+ printf("d");
+ } else if(is_lnk(type)) {
+ printf("l");
+ } else if(is_blk(type)) {
+ printf("b");
+ } else if(is_chr(type)) {
+ printf("c");
+ } else if(is_fifo(type)) {
+ printf("p");
+ } else {
+ printf("?");
+ }
}
static void
showInodePerm(int perm)
{
- printf("%s", perm & S_IRUSR ? "r" : "-");
- printf("%s", perm & S_IWUSR ? "w" : "-");
- printf("%s", perm & S_IXUSR ? "x" : "-");
+ printf("%s", perm & S_IRUSR ? "r" : "-");
+ printf("%s", perm & S_IWUSR ? "w" : "-");
+ printf("%s", perm & S_IXUSR ? "x" : "-");
- printf("%s", perm & S_IRGRP ? "r" : "-");
- printf("%s", perm & S_IWGRP ? "w" : "-");
- printf("%s", perm & S_IXGRP ? "x" : "-");
+ printf("%s", perm & S_IRGRP ? "r" : "-");
+ printf("%s", perm & S_IWGRP ? "w" : "-");
+ printf("%s", perm & S_IXGRP ? "x" : "-");
- printf("%s", perm & S_IROTH ? "r" : "-");
- printf("%s", perm & S_IWOTH ? "w" : "-");
- printf("%s", perm & S_IXOTH ? "x" : "-");
+ printf("%s", perm & S_IROTH ? "r" : "-");
+ printf("%s", perm & S_IWOTH ? "w" : "-");
+ printf("%s", perm & S_IXOTH ? "x" : "-");
}
static int
showInodeMeta(struct jffs2_raw_inode *i)
{
- char buf[80];
- struct tm t;
+ char buf[80];
+ struct tm t;
- showInodeType(i->mode);
- showInodePerm(i->mode);
- gmtime_r(i->atime, &t);
- asctime_r(&t, buf);
+ showInodeType(i->mode);
+ showInodePerm(i->mode);
+ gmtime_r(i->atime, &t);
+ asctime_r(&t, buf);
- printf(" %4d %4d %6d %s ",
- i->uid, i->gid, i->isize, buf);
- return 0;
+ printf(" %4d %4d %6d %s ",
+ i->uid, i->gid, i->isize, buf);
+ return 0;
}
static int
showNodesOfType(struct jffs2_unknown_node_list *list,
- jint16 nodetype)
+ jint16 nodetype)
{
- int count = 0;
+ int count = 0;
- while ((list = findNodeOfType(list, nodetype)) != NULL
- && !gotachar()) {
- showNode(list->nodenum, list->u);
- count++;
- list = list->next;
- }
- return count;
+ while((list = findNodeOfType(list, nodetype)) != NULL
+ && !gotachar()) {
+ showNode(list->nodenum, list->u);
+ count++;
+ list = list->next;
+ }
+ return count;
}
static int
showNodesOfTypeRange(struct jffs2_unknown_node_list *list,
- jint16 nodetype,
- char *pino,
- char *ino)
-{
- int count = 0;
-
- while (list && !gotachar()) {
- list = findNodeOfTypeRange(list, nodetype, pino, ino);
- if (list != NULL && list->u != NULL) {
- showNode(list->nodenum, list->u);
- count++;
+ jint16 nodetype,
+ char *pino,
+ char *ino)
+{
+ int count = 0;
+
+ while(list && !gotachar()) {
+ list = findNodeOfTypeRange(list, nodetype, pino, ino);
+ if(list != NULL && list->u != NULL) {
+ showNode(list->nodenum, list->u);
+ count++;
+ }
+ if(list != NULL) {
+ list = list->next;
+ }
}
- if (list != NULL)
- list = list->next;
- }
- return count;
+ return count;
}
static struct jffs2_unknown_node_list *
findNodeOfNumRange(struct jffs2_unknown_node_list *list,
- char *nodenum)
+ char *nodenum)
{
- while (!gotachar() && list) {
-
- if (list->u && inRange(nodenum, list->nodenum))
- return list;
-
- list = list->next;
- }
-
- return NULL;
+ while(!gotachar() && list) {
+
+ if(list->u && inRange(nodenum, list->nodenum)) {
+ return list;
+ }
+
+ list = list->next;
+ }
+
+ return NULL;
}
static int
showNodesOfNumRange(struct jffs2_unknown_node_list *list,
- char *range)
+ char *range)
{
- int nodetot = 0;
+ int nodetot = 0;
- while (list && (list = findNodeOfNumRange(list, range))) {
- nodetot++;
- showNode(list->nodenum, list->u);
- list = list->next;
- }
+ while(list && (list = findNodeOfNumRange(list, range))) {
+ nodetot++;
+ showNode(list->nodenum, list->u);
+ list = list->next;
+ }
- return nodetot;
+ return nodetot;
}
static struct jffs2_unknown_node_list *
findDirentByPath(struct jffs2_unknown_node_list *list,
- char *path)
+ char *path)
{
#define JFFS2_ROOT_PINO 1
#define JFFS2_PATH_SEPARATOR "/"
- char subpath[JFFS2_MAXPATH + 1];
- int pathlen;
- jint32 pino = JFFS2_ROOT_PINO;
- struct jffs2_unknown_node_list *u = NULL;
- struct jffs2_raw_dirent *d;
+ char subpath[JFFS2_MAXPATH + 1];
+ int pathlen;
+ jint32 pino = JFFS2_ROOT_PINO;
+ struct jffs2_unknown_node_list *u = NULL;
+ struct jffs2_raw_dirent *d;
- if (strlen(path) > JFFS2_MAXPATH
- || (path == NULL))
- return NULL;
+ if(strlen(path) > JFFS2_MAXPATH
+ || (path == NULL)) {
+ return NULL;
+ }
- while (*path) {
+ while(*path) {
- path += strspn(path, JFFS2_PATH_SEPARATOR);
- pathlen = strcspn(path, JFFS2_PATH_SEPARATOR);
- strncpy(subpath, path, pathlen);
- subpath[pathlen] = 0;
- path += pathlen;
+ path += strspn(path, JFFS2_PATH_SEPARATOR);
+ pathlen = strcspn(path, JFFS2_PATH_SEPARATOR);
+ strncpy(subpath, path, pathlen);
+ subpath[pathlen] = 0;
+ path += pathlen;
- u = findMatchingDirent(list, pino, -1, subpath);
- if (u == NULL)
- return NULL;
+ u = findMatchingDirent(list, pino, -1, subpath);
+ if(u == NULL) {
+ return NULL;
+ }
- d = (struct jffs2_raw_dirent *)u->u;
- pino = d->ino;
- }
+ d = (struct jffs2_raw_dirent *)u->u;
+ pino = d->ino;
+ }
- if (is_deleted_dirent(u->u))
- return NULL;
- return u;
+ if(is_deleted_dirent(u->u)) {
+ return NULL;
+ }
+ return u;
}
static int
listDirent(struct jffs2_unknown_node_list *list,
- struct jffs2_unknown_node_list *u,
- struct jffs2_umoninfo *umip)
+ struct jffs2_unknown_node_list *u,
+ struct jffs2_umoninfo *umip)
{
- struct jffs2_raw_dirent *d;
- struct jffs2_raw_inode *i;
-
- d = (struct jffs2_raw_dirent*)u->u;
-
- u = findInode(list, d->ino, -1);
- if (u == NULL)
- return 0;
+ struct jffs2_raw_dirent *d;
+ struct jffs2_raw_inode *i;
- i = (struct jffs2_raw_inode*)u->u;
- if (!umip->quiet)
- showInodeMeta(i);
-
- memset(umip->direntname, 0, sizeof(umip->direntname));
- memcpy(umip->direntname, (void*)d->name, d->nsize);
- umip->direntsize = i->isize;
-
- if (is_dir(i->mode))
- umip->direntname[d->nsize] = '/';
+ d = (struct jffs2_raw_dirent *)u->u;
- if (!umip->quiet)
- printf("%s\n", umip->direntname);
+ u = findInode(list, d->ino, -1);
+ if(u == NULL) {
+ return 0;
+ }
- return 1;
-}
+ i = (struct jffs2_raw_inode *)u->u;
+ if(!umip->quiet) {
+ showInodeMeta(i);
+ }
-static int
-listDirentByPath(struct jffs2_unknown_node_list *list,
- char *path, struct jffs2_umoninfo *umip)
-{
- struct jffs2_unknown_node_list *u = NULL;
- struct jffs2_unknown_node_list *n;
- struct jffs2_raw_dirent *d = NULL;
- struct jffs2_raw_inode *i;
- jint32 pino = JFFS2_ROOT_PINO;
- int ret = 0;
-
- /* TODO: wildcards? */
-
- if (path != NULL && strlen(path) != 0
- && strcspn(path, JFFS2_PATH_SEPARATOR) != 0) {
+ memset(umip->direntname, 0, sizeof(umip->direntname));
+ memcpy(umip->direntname, (void *)d->name, d->nsize);
+ umip->direntsize = i->isize;
- u = findDirentByPath(list, path);
- if (u == NULL)
- goto not_found;
+ if(is_dir(i->mode)) {
+ umip->direntname[d->nsize] = '/';
+ }
- d = (struct jffs2_raw_dirent*)u->u;
- n = findInode(list, d->ino, -1);
- if (n == NULL)
- goto not_found;
-
- i = (struct jffs2_raw_inode*)n->u;
- if (!is_dir(i->mode))
- return listDirent(list, u, umip);
- else pino = d->ino;
- }
-
- for (u = list; u != NULL
- && (u = findMatchingDirent(u, pino, -1, NULL)) != NULL;
- u = u->next) {
- ret += listDirent(list, u, umip);
- }
-
- return ret;
-
- not_found:
- if (!umip->quiet)
- printf("%s: no such file or directory\n", path);
- return 0;
+ if(!umip->quiet) {
+ printf("%s\n", umip->direntname);
+ }
+ return 1;
}
-
static int
-readRawInode(struct jffs2_raw_inode *i,
- jint32 offset /* ... into start of inode */,
- jint32 len /* ... of bytes to take from inode */,
- void (*callback)(void *args, int offset, void *buf, int size),
- void *callback_args)
-{
- static void *temp = NULL;
+listDirentByPath(struct jffs2_unknown_node_list *list,
+ char *path, struct jffs2_umoninfo *umip)
+{
+ struct jffs2_unknown_node_list *u = NULL;
+ struct jffs2_unknown_node_list *n;
+ struct jffs2_raw_dirent *d = NULL;
+ struct jffs2_raw_inode *i;
+ jint32 pino = JFFS2_ROOT_PINO;
+ int ret = 0;
+
+ /* TODO: wildcards? */
+
+ if(path != NULL && strlen(path) != 0
+ && strcspn(path, JFFS2_PATH_SEPARATOR) != 0) {
+
+ u = findDirentByPath(list, path);
+ if(u == NULL) {
+ goto not_found;
+ }
+
+ d = (struct jffs2_raw_dirent *)u->u;
+ n = findInode(list, d->ino, -1);
+ if(n == NULL) {
+ goto not_found;
+ }
+
+ i = (struct jffs2_raw_inode *)n->u;
+ if(!is_dir(i->mode)) {
+ return listDirent(list, u, umip);
+ } else {
+ pino = d->ino;
+ }
+ }
- /* TODO: we could allocate a 4K buffer here, read into that, and
- then pass that buffer to the callback (instead of having the
- callback read from flash directly); this would allow us to put
- jffs2 into something other than bulk NOR flash
+ for(u = list; u != NULL
+ && (u = findMatchingDirent(u, pino, -1, NULL)) != NULL;
+ u = u->next) {
+ ret += listDirent(list, u, umip);
+ }
- (is there a uMON flash-reading function that handles
- device-specific i/o details?)
- */
- switch (i->compr) {
+ return ret;
- case JFFS2_COMPR_NONE:
- callback(callback_args, i->offset + offset,
- (void*)(i->data + offset), len);
- break;
+not_found:
+ if(!umip->quiet) {
+ printf("%s: no such file or directory\n", path);
+ }
+ return 0;
- case JFFS2_COMPR_ZERO:
- callback(callback_args, i->offset + offset, 0, len);
- break;
+}
- case JFFS2_COMPR_ZLIB:
- if (temp == NULL && ((temp = malloc(4096)) == NULL)) {
- printf("%s: cannot alloc tempspace (aborted)\n",
- __func__);
- return -1;
- }
- if (i->dsize > 4096) {
- printf("%s: inode dsize > 4K (aborted)\n", __func__);
- return -1;
+static int
+readRawInode(struct jffs2_raw_inode *i,
+ jint32 offset /* ... into start of inode */,
+ jint32 len /* ... of bytes to take from inode */,
+ void (*callback)(void *args, int offset, void *buf, int size),
+ void *callback_args)
+{
+ static void *temp = NULL;
+
+ /* TODO: we could allocate a 4K buffer here, read into that, and
+ then pass that buffer to the callback (instead of having the
+ callback read from flash directly); this would allow us to put
+ jffs2 into something other than bulk NOR flash
+
+ (is there a uMON flash-reading function that handles
+ device-specific i/o details?)
+ */
+ switch(i->compr) {
+
+ case JFFS2_COMPR_NONE:
+ callback(callback_args, i->offset + offset,
+ (void *)(i->data + offset), len);
+ break;
+
+ case JFFS2_COMPR_ZERO:
+ callback(callback_args, i->offset + offset, 0, len);
+ break;
+
+ case JFFS2_COMPR_ZLIB:
+ if(temp == NULL && ((temp = malloc(4096)) == NULL)) {
+ printf("%s: cannot alloc tempspace (aborted)\n",
+ __func__);
+ return -1;
+ }
+
+ if(i->dsize > 4096) {
+ printf("%s: inode dsize > 4K (aborted)\n", __func__);
+ return -1;
+ }
+
+ if(jzlibcpy((void *)(i->data), temp, i->csize, i->dsize) < 0) {
+ return -1;
+ }
+ callback(callback_args, i->offset + offset, temp + offset, len);
+ break;
+
+ case JFFS2_COMPR_RTIME:
+ case JFFS2_COMPR_RUBINMIPS:
+ case JFFS2_COMPR_DYNRUBIN:
+ printf("%s: unsupported compression algorithm (fragment ignored)\n",
+ compr2str(i->compr));
+ break;
}
- if (jzlibcpy((void*)(i->data), temp, i->csize, i->dsize) < 0)
- return -1;
- callback(callback_args, i->offset + offset, temp + offset, len);
- break;
-
- case JFFS2_COMPR_RTIME:
- case JFFS2_COMPR_RUBINMIPS:
- case JFFS2_COMPR_DYNRUBIN:
- printf("%s: unsupported compression algorithm (fragment ignored)\n",
- compr2str(i->compr));
- break;
- }
-
- return len;
+ return len;
}
/*
@@ -1368,388 +1431,408 @@ readRawInode(struct jffs2_raw_inode *i,
*/
static int
readFrag(struct jffs2_unknown_node_list *list,
- struct jffs2_raw_inode *i,
- void (*callback)(void *args, int offset, void *buf, int size),
- void *callback_args)
-{
- jint32 fstart, istart, fend, iend;
- struct jffs2_cleanregion_node *frag;
- struct jffs2_unknown_node *newfrag;
+ struct jffs2_raw_inode *i,
+ void (*callback)(void *args, int offset, void *buf, int size),
+ void *callback_args)
+{
+ jint32 fstart, istart, fend, iend;
+ struct jffs2_cleanregion_node *frag;
+ struct jffs2_unknown_node *newfrag;
+
+ for(; list->next != NULL; list = list->next) {
+
+ /* we "shouldn't" have to do this, but since we're emptying the
+ list entirely the list pointer is always aimed at the sentinel
+ node; skip it if we find it, and use the ->next == NULL case to
+ spot the end of the list (contrary to the rest of the code in
+ this compilation unit) */
+ if(list->u == NULL) {
+ continue;
+ }
+
+ frag = (struct jffs2_cleanregion_node *)list->u;
+
+ fstart = frag->physaddr;
+ istart = i->offset;
+ fend = frag->physaddr + frag->totlen;
+ iend = i->offset + i->dsize;
+
+ if(fend <= istart || iend <= fstart) {
+ continue;
+ }
+
+ if(fstart >= istart && fend <= iend) {
+ delListNode(list);
+ return readRawInode(i, fstart - istart, fend - fstart,
+ callback, callback_args);
+ }
+
+ if(fstart <= istart && fend <= iend) {
+ frag->totlen = istart - fstart;
+ return readRawInode(i, 0, fend - istart,
+ callback, callback_args);
+ }
+
+ if(fstart >= istart && fend >= iend) {
+ frag->physaddr = iend;
+ frag->totlen = fend - iend;
+ return readRawInode(i, fstart - istart, iend - fstart,
+ callback, callback_args);
+ }
+
+ frag->totlen = iend - fend;
+ newfrag = allocCleanRegion(iend, fend - iend);
+ insertListNodeAfter(list, allocListNode(0, newfrag));
+
+ return readRawInode(i, 0, i->dsize, callback, callback_args);
+ }
- for ( ; list->next != NULL; list = list->next) {
-
- /* we "shouldn't" have to do this, but since we're emptying the
- list entirely the list pointer is always aimed at the sentinel
- node; skip it if we find it, and use the ->next == NULL case to
- spot the end of the list (contrary to the rest of the code in
- this compilation unit) */
- if (list->u == NULL) continue;
+ return 0;
+}
- frag = (struct jffs2_cleanregion_node*)list->u;
- fstart = frag->physaddr;
- istart = i->offset;
- fend = frag->physaddr + frag->totlen;
- iend = i->offset + i->dsize;
+static int
+readInode(struct jffs2_unknown_node_list *list,
+ jint32 ino,
+ void (*callback)(void *callback_args,
+ int offset, void *buf, int size),
+ void *callback_args)
+{
+ struct jffs2_unknown_node_list *frags;
+ struct jffs2_unknown_node_list *u;
+ struct jffs2_unknown_node *fr;
+ struct jffs2_unknown_node_list *f;
+ struct jffs2_raw_inode *i;
+ int ret;
+ int len = 0;
+
+ if((u = findInode(list, ino, -1)) == NULL) {
+ printf("%d: no such inode\n", ino);
+ return -1;
+ }
- if (fend <= istart || iend <= fstart)
- continue;
+ i = (struct jffs2_raw_inode *)u->u;
+ if(i->isize == 0) {
+ return 0;
+ }
- if (fstart >= istart && fend <= iend) {
- delListNode(list);
- return readRawInode(i, fstart - istart, fend - fstart,
- callback, callback_args);
+ if(initNodeList(&frags) == NULL) {
+ printf("%s: initNodeList() returned NULL (aborted)\n",
+ __func__);
+ return -1;
}
- if (fstart <= istart && fend <= iend) {
- frag->totlen = istart - fstart;
- return readRawInode(i, 0, fend - istart,
- callback, callback_args);
+ if((fr = allocCleanRegion(0, i->isize)) == NULL) {
+ goto fail_alloc_initial_region;
+ }
+ if((f = allocListNode(0, fr)) == NULL) {
+ goto fail_alloc_initial_node;
}
+ insertListNodeAfter(frags, f);
+
+ /*
+ * Note: The convention in most of this compilation unit is for list
+ * pointers to point to the first valid list member. However, in
+ * the case of the fragment list we know the caller is going to be
+ * removing nodes, including the first valid list member. Thus,
+ * we'll keep the list pointer on the sentinel node since that one
+ * never goes away. (The readFrag() iterator knows about this, and
+ * changes its list walking logic accordingly).
+ */
- if (fstart >= istart && fend >= iend) {
- frag->physaddr = iend;
- frag->totlen = fend - iend;
- return readRawInode(i, fstart - istart, iend - fstart,
- callback, callback_args);
+ do {
+ i = (struct jffs2_raw_inode *)u->u;
+ do {
+ ret = readFrag(frags, i, callback, callback_args);
+ if(ret >= 0) {
+ len += ret;
+ }
+ } while(ret > 0);
+
+ u = findInode(list, ino, i->version - 1);
+ } while(!is_empty_list(frags) && u != NULL);
+
+ if(!is_empty_list(frags))
+ printf("%s: warning, nonempty fragment list "
+ "(missing inode?) (ignored)\n");
+
+ while(frags->next) {
+ delListNode(frags->next);
}
-
- frag->totlen = iend - fend;
- newfrag = allocCleanRegion(iend, fend - iend);
- insertListNodeAfter(list, allocListNode(0, newfrag));
+ delListNode(frags);
- return readRawInode(i, 0, i->dsize, callback, callback_args);
- }
+ return len;
- return 0;
+fail_alloc_initial_node:
+ free(fr);
+ printf("%s: allocListNode() returned NULL (aborted)\n",
+ __func__);
+ return 0;
+fail_alloc_initial_region:
+ printf("%s: allocCleanRegion() returned NULL (aborted)\n",
+ __func__);
+ return 0;
}
-
static int
-readInode(struct jffs2_unknown_node_list *list,
- jint32 ino,
- void (*callback)(void *callback_args,
- int offset, void *buf, int size),
- void *callback_args)
-{
- struct jffs2_unknown_node_list *frags;
- struct jffs2_unknown_node_list *u;
- struct jffs2_unknown_node *fr;
- struct jffs2_unknown_node_list *f;
- struct jffs2_raw_inode *i;
- int ret;
- int len = 0;
-
- if ((u = findInode(list, ino, -1)) == NULL) {
- printf("%d: no such inode\n", ino);
- return -1;
- }
-
- i = (struct jffs2_raw_inode*)u->u;
- if (i->isize == 0)
- return 0;
+readDirent(struct jffs2_unknown_node_list *list, char *path,
+ void (*callback)(void *args,
+ int offset, void *buf, int size),
+ void *callback_args)
+{
+ struct jffs2_unknown_node_list *u;
+ struct jffs2_raw_dirent *d;
+ struct jffs2_raw_inode *i;
- if (initNodeList(&frags) == NULL) {
- printf("%s: initNodeList() returned NULL (aborted)\n",
- __func__);
- return -1;
- }
-
- if ((fr = allocCleanRegion(0, i->isize)) == NULL)
- goto fail_alloc_initial_region;
- if ((f = allocListNode(0, fr)) == NULL)
- goto fail_alloc_initial_node;
- insertListNodeAfter(frags, f);
-
- /*
- * Note: The convention in most of this compilation unit is for list
- * pointers to point to the first valid list member. However, in
- * the case of the fragment list we know the caller is going to be
- * removing nodes, including the first valid list member. Thus,
- * we'll keep the list pointer on the sentinel node since that one
- * never goes away. (The readFrag() iterator knows about this, and
- * changes its list walking logic accordingly).
- */
-
- do {
- i = (struct jffs2_raw_inode*)u->u;
- do {
- ret = readFrag(frags, i, callback, callback_args);
- if (ret >= 0) len += ret;
- } while (ret > 0);
+ u = findDirentByPath(list, path);
+ if(u == NULL) {
+ goto no_such_file;
+ }
- u = findInode(list, ino, i->version - 1);
- } while (!is_empty_list(frags) && u != NULL);
+ d = (struct jffs2_raw_dirent *)u->u;
+ u = findInode(list, d->ino, -1);
+ if(u == NULL) {
+ goto no_such_inode;
+ }
- if (!is_empty_list(frags))
- printf("%s: warning, nonempty fragment list "
- "(missing inode?) (ignored)\n");
+ i = (struct jffs2_raw_inode *)u->u;
+ if(!is_reg(i->mode)) {
+ goto not_a_file;
+ }
- while(frags->next)
- delListNode(frags->next);
- delListNode(frags);
+ return readInode(list, d->ino, callback, callback_args);
- return len;
+no_such_file:
+ printf("%s: no such file or directory\n", path);
+ return -1;
- fail_alloc_initial_node:
- free(fr);
- printf("%s: allocListNode() returned NULL (aborted)\n",
- __func__);
- return 0;
- fail_alloc_initial_region:
- printf("%s: allocCleanRegion() returned NULL (aborted)\n",
- __func__);
- return 0;
-}
+no_such_inode:
+ printf("%d: no such inode\n", d->ino);
+ return -1;
-static int
-readDirent(struct jffs2_unknown_node_list *list, char *path,
- void (*callback)(void *args,
- int offset, void *buf, int size),
- void *callback_args)
-{
- struct jffs2_unknown_node_list *u;
- struct jffs2_raw_dirent *d;
- struct jffs2_raw_inode *i;
-
- u = findDirentByPath(list, path);
- if (u == NULL)
- goto no_such_file;
-
- d = (struct jffs2_raw_dirent *)u->u;
- u = findInode(list, d->ino, -1);
- if (u == NULL)
- goto no_such_inode;
-
- i = (struct jffs2_raw_inode*)u->u;
- if (!is_reg(i->mode))
- goto not_a_file;
-
- return readInode(list, d->ino, callback, callback_args);
-
- no_such_file:
- printf("%s: no such file or directory\n", path);
- return -1;
-
- no_such_inode:
- printf("%d: no such inode\n", d->ino);
- return -1;
-
- not_a_file:
- printf("%s: is %s\n", path,
- is_dir(i->mode) ? "a directory" : "not a file");
- return -1;
+not_a_file:
+ printf("%s: is %s\n", path,
+ is_dir(i->mode) ? "a directory" : "not a file");
+ return -1;
}
static struct jffs2_unknown_node *
commitRawNode(struct jffs2_unknown_node_list *list,
- struct jffs2_unknown_node *u)
+ struct jffs2_unknown_node *u)
{
- struct jffs2_unknown_node_list *c;
- unsigned long adjtotlen;
- int ret;
+ struct jffs2_unknown_node_list *c;
+ unsigned long adjtotlen;
+ int ret;
- /* everything is 32-bit aligned in jffs2-land, so you always need a
- region slightly larger than the data itself to accomodate the
- address and length rounding we may apply later on */
- c = findCleanRegion(list, u->totlen + 4);
- if (c != NULL) {
+ /* everything is 32-bit aligned in jffs2-land, so you always need a
+ region slightly larger than the data itself to accomodate the
+ address and length rounding we may apply later on */
+ c = findCleanRegion(list, u->totlen + 4);
+ if(c != NULL) {
- struct jffs2_cleanregion_node *f = (struct jffs2_cleanregion_node*)c->u;
+ struct jffs2_cleanregion_node *f = (struct jffs2_cleanregion_node *)c->u;
- ret = AppFlashWrite((void*)(f->physaddr), (void*)u, u->totlen);
- if (ret != 0)
- printf("%s: AppFlashWrite returned %d (ignored)\n", __func__, ret);
+ ret = AppFlashWrite((void *)(f->physaddr), (void *)u, u->totlen);
+ if(ret != 0) {
+ printf("%s: AppFlashWrite returned %d (ignored)\n", __func__, ret);
+ }
- ret = f->physaddr;
+ ret = f->physaddr;
- /* cleanregions must always begin on a 32-bit boundary */
- adjtotlen = ulceil(u->totlen, 4);
- f->totlen -= adjtotlen;
- f->physaddr += adjtotlen;
+ /* cleanregions must always begin on a 32-bit boundary */
+ adjtotlen = ulceil(u->totlen, 4);
+ f->totlen -= adjtotlen;
+ f->physaddr += adjtotlen;
- return (struct jffs2_unknown_node*)ret;
- }
+ return (struct jffs2_unknown_node *)ret;
+ }
- return NULL;
+ return NULL;
}
static struct jffs2_raw_dirent *
-allocDirentNode (char *name)
+allocDirentNode(char *name)
{
- struct jffs2_raw_dirent *d;
- int namelen = 0;
+ struct jffs2_raw_dirent *d;
+ int namelen = 0;
- if (name != NULL)
- namelen = strlen(name);
+ if(name != NULL) {
+ namelen = strlen(name);
+ }
- d = (struct jffs2_raw_dirent*)malloc(sizeof(*d) + namelen);
- if (d == NULL) {
- printf("%s: malloc() returned NULL (aborted)\n", __func__);
- return NULL;
- }
+ d = (struct jffs2_raw_dirent *)malloc(sizeof(*d) + namelen);
+ if(d == NULL) {
+ printf("%s: malloc() returned NULL (aborted)\n", __func__);
+ return NULL;
+ }
- memset((void*)d, 0, sizeof(*d));
+ memset((void *)d, 0, sizeof(*d));
- d->magic = JFFS2_MAGIC;
- d->nodetype = JFFS2_NODETYPE_DIRENT
- | JFFS2_NODE_ACCURATE
- | JFFS2_FEATURE_ROCOMPAT
- | JFFS2_FEATURE_RWCOMPAT_COPY;
- memcpy((void*)d->name, name, d->nsize = namelen);
- d->totlen = sizeof(*d) + d->nsize;
+ d->magic = JFFS2_MAGIC;
+ d->nodetype = JFFS2_NODETYPE_DIRENT
+ | JFFS2_NODE_ACCURATE
+ | JFFS2_FEATURE_ROCOMPAT
+ | JFFS2_FEATURE_RWCOMPAT_COPY;
+ memcpy((void *)d->name, name, d->nsize = namelen);
+ d->totlen = sizeof(*d) + d->nsize;
- return d;
+ return d;
}
static void
freeDirentNode(struct jffs2_raw_dirent *d)
{
- free(d);
+ free(d);
}
static jint32
nextPinoVersion(struct jffs2_unknown_node_list *list, jint32 pino)
{
- jint32 version = 0;
+ jint32 version = 0;
- while(list) {
- if (list->u && is_dirent(list->u)) {
- struct jffs2_raw_dirent *d = (struct jffs2_raw_dirent*)list->u;
-
- if (d->pino == pino && d->version > version)
- version = d->version;
+ while(list) {
+ if(list->u && is_dirent(list->u)) {
+ struct jffs2_raw_dirent *d = (struct jffs2_raw_dirent *)list->u;
+
+ if(d->pino == pino && d->version > version) {
+ version = d->version;
+ }
+ }
+ list = list->next;
}
- list = list->next;
- }
- return version + 1;
+ return version + 1;
}
static struct jffs2_unknown_node_list *
-commitDirent(struct jffs2_unknown_node_list *list, ulong nodenum,
- char *name, jint8 type, jint32 pino, jint32 ino,
- jint32 version)
+commitDirent(struct jffs2_unknown_node_list *list, ulong nodenum,
+ char *name, jint8 type, jint32 pino, jint32 ino,
+ jint32 version)
{
- struct jffs2_raw_dirent *d;
- struct jffs2_unknown_node *dc;
- struct jffs2_unknown_node_list *n;
+ struct jffs2_raw_dirent *d;
+ struct jffs2_unknown_node *dc;
+ struct jffs2_unknown_node_list *n;
- d = allocDirentNode(name);
- if (d == NULL)
- return NULL;
+ d = allocDirentNode(name);
+ if(d == NULL) {
+ return NULL;
+ }
- d->type = type;
- d->version = version;
- d->pino = pino;
- d->ino = ino;
+ d->type = type;
+ d->version = version;
+ d->pino = pino;
+ d->ino = ino;
- d->hdr_crc = calcHdrCrc((struct jffs2_unknown_node *)d);
- d->node_crc = calcDirentCrc(d);
- d->name_crc = calcDataCrc(d->name, d->nsize);
+ d->hdr_crc = calcHdrCrc((struct jffs2_unknown_node *)d);
+ d->node_crc = calcDirentCrc(d);
+ d->name_crc = calcDataCrc(d->name, d->nsize);
- dc = commitRawNode(list, (struct jffs2_unknown_node*)d);
- freeDirentNode(d);
+ dc = commitRawNode(list, (struct jffs2_unknown_node *)d);
+ freeDirentNode(d);
- if (dc == NULL) /* TODO: error handling? */
- return NULL;
-
- if ((n = allocListNode(nodenum, dc)) != NULL)
- return insertListNodeAfter(list, n);
+ if(dc == NULL) { /* TODO: error handling? */
+ return NULL;
+ }
+
+ if((n = allocListNode(nodenum, dc)) != NULL) {
+ return insertListNodeAfter(list, n);
+ }
- return NULL;
+ return NULL;
}
static struct jffs2_unknown_node_list *
moveDirent(struct jffs2_unknown_node_list *list,
- int nodetot, char *oldpath, char *newpath)
-{
- struct jffs2_unknown_node_list *u, *ui, *uold, *unew;
- struct jffs2_raw_dirent *d = NULL;
- struct jffs2_raw_inode *i;
- jint32 pino;
- jint32 nextver;
-
- char newname[JFFS2_MAXPATH + 1];
-
- uold = findDirentByPath(list, oldpath);
- if (uold == NULL)
- goto no_such;
- d = (struct jffs2_raw_dirent*)uold->u;
-
- unew = findDirentByPath(list, newpath);
- if (unew != NULL) {
- struct jffs2_raw_dirent *dnew;
-
- dnew = (struct jffs2_raw_dirent*)unew->u;
- ui = findInode(list, dnew->ino, -1);
- i = (struct jffs2_raw_inode*)ui->u;
- if (!is_dir(i->mode))
- goto in_the_way;
-
- pino = dnew->ino;
- strncpy(newname, (void*)d->name, d->nsize);
- newname[d->nsize] = 0;
- }
- else {
- strcpy(newname, newpath);
- pino = JFFS2_ROOT_PINO;
- }
-
- nextver = nextPinoVersion(list, pino);
- u = commitDirent(list, nodetot++, newname,
- d->type, pino, d->ino, nextver++);
- /* TODO: error handling? */
- u = commitDirent(list, nodetot++, oldpath,
- d->type, d->pino, 0, nextver);
- return u;
-
- no_such:
- printf("%s: no such file or directory\n", oldpath);
- return NULL;
-
- in_the_way:
- /* (yes, we could delete this ourselves...) */
- printf("%s already exists\n", newpath);
- return NULL;
+ int nodetot, char *oldpath, char *newpath)
+{
+ struct jffs2_unknown_node_list *u, *ui, *uold, *unew;
+ struct jffs2_raw_dirent *d = NULL;
+ struct jffs2_raw_inode *i;
+ jint32 pino;
+ jint32 nextver;
+
+ char newname[JFFS2_MAXPATH + 1];
+
+ uold = findDirentByPath(list, oldpath);
+ if(uold == NULL) {
+ goto no_such;
+ }
+ d = (struct jffs2_raw_dirent *)uold->u;
+
+ unew = findDirentByPath(list, newpath);
+ if(unew != NULL) {
+ struct jffs2_raw_dirent *dnew;
+
+ dnew = (struct jffs2_raw_dirent *)unew->u;
+ ui = findInode(list, dnew->ino, -1);
+ i = (struct jffs2_raw_inode *)ui->u;
+ if(!is_dir(i->mode)) {
+ goto in_the_way;
+ }
+
+ pino = dnew->ino;
+ strncpy(newname, (void *)d->name, d->nsize);
+ newname[d->nsize] = 0;
+ } else {
+ strcpy(newname, newpath);
+ pino = JFFS2_ROOT_PINO;
+ }
+
+ nextver = nextPinoVersion(list, pino);
+ u = commitDirent(list, nodetot++, newname,
+ d->type, pino, d->ino, nextver++);
+ /* TODO: error handling? */
+ u = commitDirent(list, nodetot++, oldpath,
+ d->type, d->pino, 0, nextver);
+ return u;
+
+no_such:
+ printf("%s: no such file or directory\n", oldpath);
+ return NULL;
+
+in_the_way:
+ /* (yes, we could delete this ourselves...) */
+ printf("%s already exists\n", newpath);
+ return NULL;
}
static struct jffs2_unknown_node_list *
deleteDirent(struct jffs2_unknown_node_list *list,
- int nodetot, char *path)
-{
- struct jffs2_unknown_node_list *u, *ui;
- struct jffs2_raw_dirent *d;
- struct jffs2_raw_inode *i;
- jint32 nextver;
- char name[JFFS2_MAXPATH + 1];
-
- u = findDirentByPath(list, path);
- if (u == NULL)
- goto no_such;
- d = (struct jffs2_raw_dirent*)u->u;
-
- ui = findInode(list, d->ino, -1);
- i = (struct jffs2_raw_inode*)ui->u;
- if (is_dir(i->mode)) {
- /* TODO: make sure directory is empty */
- printf("%s: is a directory (abort)\n", path);
- return NULL;
- }
+ int nodetot, char *path)
+{
+ struct jffs2_unknown_node_list *u, *ui;
+ struct jffs2_raw_dirent *d;
+ struct jffs2_raw_inode *i;
+ jint32 nextver;
+ char name[JFFS2_MAXPATH + 1];
+
+ u = findDirentByPath(list, path);
+ if(u == NULL) {
+ goto no_such;
+ }
+ d = (struct jffs2_raw_dirent *)u->u;
+
+ ui = findInode(list, d->ino, -1);
+ i = (struct jffs2_raw_inode *)ui->u;
+ if(is_dir(i->mode)) {
+ /* TODO: make sure directory is empty */
+ printf("%s: is a directory (abort)\n", path);
+ return NULL;
+ }
+
+ strncpy(name, (void *)d->name, d->nsize);
+ name[d->nsize] = 0;
- strncpy(name, (void*)d->name, d->nsize);
- name[d->nsize] = 0;
+ nextver = nextPinoVersion(list, d->pino);
+ u = commitDirent(list, nodetot++, name,
+ d->type, d->pino, 0, nextver);
- nextver = nextPinoVersion(list, d->pino);
- u = commitDirent(list, nodetot++, name,
- d->type, d->pino, 0, nextver);
+ return u;
- return u;
-
- no_such:
- printf("%s: no such file or directory\n", path);
- return NULL;
+no_such:
+ printf("%s: no such file or directory\n", path);
+ return NULL;
}
#define JFFS2_DEFAULT_UID 0
@@ -1758,52 +1841,54 @@ deleteDirent(struct jffs2_unknown_node_list *list,
static struct jffs2_raw_inode *
allocInode(jint32 ino, jint32 dsize)
{
- struct jffs2_raw_inode *i;
+ struct jffs2_raw_inode *i;
- i = (struct jffs2_raw_inode*)malloc(sizeof(*i) + dsize);
- if (i == NULL) {
- printf("%s: malloc() returned NULL (aborted)\n", __func__);
- return NULL;
- }
+ i = (struct jffs2_raw_inode *)malloc(sizeof(*i) + dsize);
+ if(i == NULL) {
+ printf("%s: malloc() returned NULL (aborted)\n", __func__);
+ return NULL;
+ }
- memset((void*)i, 0, sizeof(*i) + dsize);
+ memset((void *)i, 0, sizeof(*i) + dsize);
- i->magic = JFFS2_MAGIC;
- i->ino = ino;
- i->nodetype = JFFS2_NODETYPE_INODE
- | JFFS2_NODE_ACCURATE
- | JFFS2_FEATURE_ROCOMPAT
- | JFFS2_FEATURE_RWCOMPAT_COPY;
- i->compr = JFFS2_COMPR_NONE;
- i->dsize = i->csize = dsize;
- i->totlen = sizeof(*i) + dsize;
+ i->magic = JFFS2_MAGIC;
+ i->ino = ino;
+ i->nodetype = JFFS2_NODETYPE_INODE
+ | JFFS2_NODE_ACCURATE
+ | JFFS2_FEATURE_ROCOMPAT
+ | JFFS2_FEATURE_RWCOMPAT_COPY;
+ i->compr = JFFS2_COMPR_NONE;
+ i->dsize = i->csize = dsize;
+ i->totlen = sizeof(*i) + dsize;
- return i;
+ return i;
}
static void
freeInode(struct jffs2_raw_inode *i)
{
- free(i);
+ free(i);
}
static jint32
getUnusedIno(struct jffs2_unknown_node_list *list)
{
- /* by definition, the root pino is always taken... */
- jint32 ino = JFFS2_ROOT_PINO + 1;
+ /* by definition, the root pino is always taken... */
+ jint32 ino = JFFS2_ROOT_PINO + 1;
- while (!gotachar()
- && (list = findNodeOfType(list, JFFS2_NODETYPE_INODE)) != NULL) {
- struct jffs2_raw_inode *i = (struct jffs2_raw_inode*)list->u;
- if (i->ino > ino)
- ino = i->ino + 1;
- list = list->next;
- }
+ while(!gotachar()
+ && (list = findNodeOfType(list, JFFS2_NODETYPE_INODE)) != NULL) {
+ struct jffs2_raw_inode *i = (struct jffs2_raw_inode *)list->u;
+ if(i->ino > ino) {
+ ino = i->ino + 1;
+ }
+ list = list->next;
+ }
- if (gotachar())
- return -1;
- return ino;
+ if(gotachar()) {
+ return -1;
+ }
+ return ino;
}
@@ -1812,525 +1897,566 @@ getUnusedIno(struct jffs2_unknown_node_list *list)
static struct jffs2_unknown_node_list *
appendInode(struct jffs2_unknown_node_list *list,
- int nodenum,
- char *path,
- void *data,
- int len)
-{
- struct jffs2_unknown_node_list *n;
- struct jffs2_raw_inode *iprev, *inew;
- struct jffs2_raw_dirent *d;
- struct jffs2_unknown_node *ic;
-
- /* TODO: break append up into smaller nodes, if there isn't a single
- region large enough */
-
- /* TODO: don't deal with large appends yet (nodes are not permitted
- to exceed 4K in size per jffs2) */
- if (len >= 4096) {
- printf("inode extension by >= 4K not supported (yet)\n");
- return NULL;
- }
+ int nodenum,
+ char *path,
+ void *data,
+ int len)
+{
+ struct jffs2_unknown_node_list *n;
+ struct jffs2_raw_inode *iprev, *inew;
+ struct jffs2_raw_dirent *d;
+ struct jffs2_unknown_node *ic;
- n = findDirentByPath(list, path);
- if (n == NULL)
- goto not_found;
- d = (struct jffs2_raw_dirent*)n->u;
+ /* TODO: break append up into smaller nodes, if there isn't a single
+ region large enough */
- n = findInode(list, d->ino, -1);
- if (n == NULL)
- goto not_found;
- iprev = (struct jffs2_raw_inode*)n->u;
+ /* TODO: don't deal with large appends yet (nodes are not permitted
+ to exceed 4K in size per jffs2) */
+ if(len >= 4096) {
+ printf("inode extension by >= 4K not supported (yet)\n");
+ return NULL;
+ }
- inew = allocInode(iprev->ino, len);
- if (inew == NULL)
- return NULL;
+ n = findDirentByPath(list, path);
+ if(n == NULL) {
+ goto not_found;
+ }
+ d = (struct jffs2_raw_dirent *)n->u;
- inew->ino = iprev->ino;
- inew->version = iprev->version + 1;
- inew->mode = iprev->mode;
- inew->uid = iprev->uid;
- inew->gid = iprev->gid;
- inew->atime = iprev->atime;
- inew->mtime = iprev->mtime;
- inew->ctime = iprev->ctime;
-
- inew->offset = inew->isize;
- inew->isize += len;
- inew->compr = JFFS2_COMPR_NONE;
- inew->usercompr = 0;
- memcpy((void*)inew->data, data, len);
-
- inew->hdr_crc = calcHdrCrc((struct jffs2_unknown_node*)inew);
- inew->node_crc = calcInodeCrc(inew);
- inew->data_crc = calcDataCrc(inew->data, inew->dsize);
-
- ic = commitRawNode(list, (struct jffs2_unknown_node*)inew);
- freeInode(inew);
-
- if (ic == NULL) /* TODO: error handling? */
- return NULL;
+ n = findInode(list, d->ino, -1);
+ if(n == NULL) {
+ goto not_found;
+ }
+ iprev = (struct jffs2_raw_inode *)n->u;
+
+ inew = allocInode(iprev->ino, len);
+ if(inew == NULL) {
+ return NULL;
+ }
+
+ inew->ino = iprev->ino;
+ inew->version = iprev->version + 1;
+ inew->mode = iprev->mode;
+ inew->uid = iprev->uid;
+ inew->gid = iprev->gid;
+ inew->atime = iprev->atime;
+ inew->mtime = iprev->mtime;
+ inew->ctime = iprev->ctime;
+
+ inew->offset = inew->isize;
+ inew->isize += len;
+ inew->compr = JFFS2_COMPR_NONE;
+ inew->usercompr = 0;
+ memcpy((void *)inew->data, data, len);
+
+ inew->hdr_crc = calcHdrCrc((struct jffs2_unknown_node *)inew);
+ inew->node_crc = calcInodeCrc(inew);
+ inew->data_crc = calcDataCrc(inew->data, inew->dsize);
+
+ ic = commitRawNode(list, (struct jffs2_unknown_node *)inew);
+ freeInode(inew);
+
+ if(ic == NULL) { /* TODO: error handling? */
+ return NULL;
+ }
- if ((n = allocListNode(nodenum++, ic)) != NULL)
- return insertListNodeAfter(list, n);
+ if((n = allocListNode(nodenum++, ic)) != NULL) {
+ return insertListNodeAfter(list, n);
+ }
- return NULL;
+ return NULL;
- not_found:
- printf("%s: no such file or directory\n", path);
- return NULL;
+not_found:
+ printf("%s: no such file or directory\n", path);
+ return NULL;
}
static struct jffs2_unknown_node_list *
createInode(struct jffs2_unknown_node_list *list,
- int nodenum,
- jint32 mode,
- char *path)
-{
- struct jffs2_unknown_node_list *n;
- struct jffs2_raw_inode *i;
- struct jffs2_unknown_node *ic;
- char *ppath = path;
- jint32 pino = 1;
- jint32 ino;
- jint8 type;
- char name[JFFS2_MAXPATH + 1];
-
- n = findDirentByPath(list, path);
- if (n != NULL)
- goto already_exists;
-
- while (*ppath && strstr(ppath, JFFS2_PATH_SEPARATOR) != NULL)
- ppath++;
-
- if (ppath != path) {
- struct jffs2_raw_dirent *d;
- strncpy(name, path, ppath - path - 1);
- name[ppath - path - 1] = 0;
-
- n = findDirentByPath(list, name);
- if (n == NULL)
- goto not_found;
- d = (struct jffs2_raw_dirent*)n->u;
- pino = d->ino;
- }
-
- ino = getUnusedIno(list);
- if (ino == -1)
- return NULL;
+ int nodenum,
+ jint32 mode,
+ char *path)
+{
+ struct jffs2_unknown_node_list *n;
+ struct jffs2_raw_inode *i;
+ struct jffs2_unknown_node *ic;
+ char *ppath = path;
+ jint32 pino = 1;
+ jint32 ino;
+ jint8 type;
+ char name[JFFS2_MAXPATH + 1];
+
+ n = findDirentByPath(list, path);
+ if(n != NULL) {
+ goto already_exists;
+ }
- i = allocInode(ino, 0);
- if (i == NULL)
- return NULL;
+ while(*ppath && strstr(ppath, JFFS2_PATH_SEPARATOR) != NULL) {
+ ppath++;
+ }
+
+ if(ppath != path) {
+ struct jffs2_raw_dirent *d;
+ strncpy(name, path, ppath - path - 1);
+ name[ppath - path - 1] = 0;
+
+ n = findDirentByPath(list, name);
+ if(n == NULL) {
+ goto not_found;
+ }
+ d = (struct jffs2_raw_dirent *)n->u;
+ pino = d->ino;
+ }
- i->mode = mode;
- i->uid = JFFS2_DEFAULT_UID;
- i->gid = JFFS2_DEFAULT_GID;
- i->version = 1;
+ ino = getUnusedIno(list);
+ if(ino == -1) {
+ return NULL;
+ }
- i->hdr_crc = calcHdrCrc((struct jffs2_unknown_node*)i);
- i->node_crc = calcInodeCrc(i);
- i->data_crc = 0;
+ i = allocInode(ino, 0);
+ if(i == NULL) {
+ return NULL;
+ }
- ic = commitRawNode(list, (struct jffs2_unknown_node*)i);
- freeInode(i);
+ i->mode = mode;
+ i->uid = JFFS2_DEFAULT_UID;
+ i->gid = JFFS2_DEFAULT_GID;
+ i->version = 1;
- if (ic == NULL) /* TODO: error handling? */
- return NULL;
-
- if ((n = allocListNode(nodenum++, ic)) == NULL
- || insertListNodeAfter(list, n) == NULL)
- return NULL;
-
- if (is_lnk(mode)) type = DT_LNK;
- else if (is_blk(mode)) type = DT_BLK;
- else if (is_dir(mode)) type = DT_DIR;
- else if (is_chr(mode)) type = DT_CHR;
- else if (is_fifo(mode)) type = DT_FIFO;
- else type = DT_REG;
+ i->hdr_crc = calcHdrCrc((struct jffs2_unknown_node *)i);
+ i->node_crc = calcInodeCrc(i);
+ i->data_crc = 0;
+
+ ic = commitRawNode(list, (struct jffs2_unknown_node *)i);
+ freeInode(i);
+
+ if(ic == NULL) { /* TODO: error handling? */
+ return NULL;
+ }
+
+ if((n = allocListNode(nodenum++, ic)) == NULL
+ || insertListNodeAfter(list, n) == NULL) {
+ return NULL;
+ }
- i = (struct jffs2_raw_inode*)ic;
-
- return commitDirent(list, nodenum, ppath, type,
- pino, i->ino, nextPinoVersion(list, pino));
+ if(is_lnk(mode)) {
+ type = DT_LNK;
+ } else if(is_blk(mode)) {
+ type = DT_BLK;
+ } else if(is_dir(mode)) {
+ type = DT_DIR;
+ } else if(is_chr(mode)) {
+ type = DT_CHR;
+ } else if(is_fifo(mode)) {
+ type = DT_FIFO;
+ } else {
+ type = DT_REG;
+ }
+
+ i = (struct jffs2_raw_inode *)ic;
- already_exists:
- printf("%s: file exists\n", path);
- return NULL;
+ return commitDirent(list, nodenum, ppath, type,
+ pino, i->ino, nextPinoVersion(list, pino));
- not_found:
- printf("%s: no such file or directory\n", name);
- return NULL;
+already_exists:
+ printf("%s: file exists\n", path);
+ return NULL;
+
+not_found:
+ printf("%s: no such file or directory\n", name);
+ return NULL;
}
struct jffs2_callback_args {
- void *dest;
+ void *dest;
};
static void
-callback_to_memory (void *vargs, int offset,
- void *src, int size)
-{
- struct jffs2_callback_args *args = vargs;
- if (src == NULL)
- memset(args->dest + offset, 0, size);
- else
- memcpy(args->dest + offset, src, size);
+callback_to_memory(void *vargs, int offset,
+ void *src, int size)
+{
+ struct jffs2_callback_args *args = vargs;
+ if(src == NULL) {
+ memset(args->dest + offset, 0, size);
+ } else {
+ memcpy(args->dest + offset, src, size);
+ }
}
static void
-callback_to_console (void *vargs, int offset,
- void *src, int size)
+callback_to_console(void *vargs, int offset,
+ void *src, int size)
{
- char *cp = src;
+ char *cp = src;
- if (src == NULL)
- return;
+ if(src == NULL) {
+ return;
+ }
- for (cp = src; size > 0; size--)
- putchar(*cp++);
+ for(cp = src; size > 0; size--) {
+ putchar(*cp++);
+ }
}
char *Jffs2Help[] = {
- "Read and write JFFS2-formatted flash space",
- "[b:cs:] {operation} [args]...",
+ "Read and write JFFS2-formatted flash space",
+ "[b:cs:] {operation} [args]...",
#if INCLUDE_VERBOSEHELP
- "",
- "Options:",
- " -b {addr} base address of JFFS2 space (note 1)",
- " -c check CRCs of all nodes (note 2)",
- " -s {size} size of JFFS2 space {note 4}",
- " -q quiet operation",
- "",
- "Operations:",
- " add {fname} {address} {bytes}",
- " append {bytes} bytes at {address} to file {fname} (note 3)",
- " cat {fname} dump contents of ASCII file {fname} to console",
- " cp {fname} {to_fname}",
- " copy a file {fname} to {to_fname}",
- " get {fname} {to_addr}",
- " dump contents of file {fname} to {to_addr}",
- " ls [path] list files and/or dirs of the specified [path]",
- " mkdir {path} create a directory named {path}",
- " mv {path} {to_path}",
- " relocate a file/directory from {path} to {to_path}",
- " rm {fname} delete file named {fname}",
- " mkfs [{{addr} {size}}]",
- " build an empty JFFS2 filesystem (notes 1,4)",
- "",
- "Additional operations:",
- " dump display all nodes",
- " dirent display all dirent nodes",
- " inode display all inode nodes",
- " ino [rng] display nodes with specified ino field",
- " node [rng] display nodes of specified numerical range",
- " pino [rng] display nodes with specified pino field",
- " rescan discard current node list, if any, then scan",
- " scan scan filesystem image only",
+ "",
+ "Options:",
+ " -b {addr} base address of JFFS2 space (note 1)",
+ " -c check CRCs of all nodes (note 2)",
+ " -s {size} size of JFFS2 space {note 4}",
+ " -q quiet operation",
+ "",
+ "Operations:",
+ " add {fname} {address} {bytes}",
+ " append {bytes} bytes at {address} to file {fname} (note 3)",
+ " cat {fname} dump contents of ASCII file {fname} to console",
+ " cp {fname} {to_fname}",
+ " copy a file {fname} to {to_fname}",
+ " get {fname} {to_addr}",
+ " dump contents of file {fname} to {to_addr}",
+ " ls [path] list files and/or dirs of the specified [path]",
+ " mkdir {path} create a directory named {path}",
+ " mv {path} {to_path}",
+ " relocate a file/directory from {path} to {to_path}",
+ " rm {fname} delete file named {fname}",
+ " mkfs [{{addr} {size}}]",
+ " build an empty JFFS2 filesystem (notes 1,4)",
+ "",
+ "Additional operations:",
+ " dump display all nodes",
+ " dirent display all dirent nodes",
+ " inode display all inode nodes",
+ " ino [rng] display nodes with specified ino field",
+ " node [rng] display nodes of specified numerical range",
+ " pino [rng] display nodes with specified pino field",
+ " rescan discard current node list, if any, then scan",
+ " scan scan filesystem image only",
#if 0
- " zinf {src} {dest} {srclen} {destlen}",
- " inflate using JFFS2's zlib",
+ " zinf {src} {dest} {srclen} {destlen}",
+ " inflate using JFFS2's zlib",
#endif
- "",
- "Notes:",
- " 1. Base address defaults to $JFFS2BASE or zero, if not specified",
- " 2. Defaults to off",
- " 3. If {fname} does not exist, it is created",
- " 4. Size defaults to $JFFS2SIZE or zero, if not specified",
+ "",
+ "Notes:",
+ " 1. Base address defaults to $JFFS2BASE or zero, if not specified",
+ " 2. Defaults to off",
+ " 3. If {fname} does not exist, it is created",
+ " 4. Size defaults to $JFFS2SIZE or zero, if not specified",
#endif
- 0
+ 0
};
static void
progress_callback(int percent)
{
- static int prev_percent;
+ static int prev_percent;
- if (prev_percent == percent)
- return;
+ if(prev_percent == percent) {
+ return;
+ }
- prev_percent = percent;
- printf("\r%3d%%\r",
- percent > 100 ? 100 : percent);
+ prev_percent = percent;
+ printf("\r%3d%%\r",
+ percent > 100 ? 100 : percent);
}
int
Jffs2Cmd(int argc, char *argv[])
{
- ulong jaddr, jsize;
- struct jffs2_unknown_node *u;
- int opt;
- char *env, *cmd, *fname, *range;
- int bytes, nodes;
- void (*progress)(int percent) = progress_callback;
-
- static int nodetot = 0;
- static struct jffs2_unknown_node_list *nodeList = NULL;
-
- jint32 jffs2_base = JFFS2_DEFAULT_BASE;
- jint32 jffs2_size = 0;
-
- assert(sizeof(jint32) == 4);
- assert(sizeof(jint16) == 2);
- assert(sizeof(jint8) == 1);
-
- jffs2_verify_crc = 0;
-
- if ((env = getenv("JFFS2BASE")))
- jffs2_base = (jint32)strtoul(env,0,0);
-
- if ((env = getenv("JFFS2SIZE")))
- jffs2_size = (jint32)strtoul(env,0,0);
-
- while ((opt=getopt(argc,argv,"b:cs:q")) != -1) {
- switch(opt) {
- case 'b':
- jffs2_base = (jint32)strtoul(optarg,0,0);
- break;
- case 'c':
- jffs2_verify_crc = 1;
- break;
- case 's':
- jffs2_size = (jint32)strtoul(optarg,0,0);
- break;
- case 'q':
- progress = NULL;
- break;
- default:
- return(CMD_PARAM_ERROR);
- }
- }
-
- if (argc < optind + 1)
- return(CMD_PARAM_ERROR);
-
- cmd = argv[optind];
-
- if (strcmp(cmd, "mkfs") == 0) {
- if (argc <= optind + 1)
- jaddr = jffs2_base;
- else
- jaddr = strtoul(argv[optind + 1], 0, 0);
- if (argc <= optind + 2)
- jsize = jffs2_size;
- else
- jsize = strtoul(argv[optind + 2], 0, 0);
-
- nodeList = discardNodeList(nodeList);
-
- /* TODO: progress feedback needs to be optional? */
- return formatMedium(jaddr, jsize, progress) ?
- CMD_FAILURE : CMD_SUCCESS;
- }
-
- if (strcmp(cmd, "rescan") == 0)
- nodeList = discardNodeList(nodeList);
-
- /* commands below this point require a scanMedium() */
-
- if (nodeList == NULL) {
- initNodeList(&nodeList);
- if (nodeList != NULL) {
- nodetot = scanMedium(jffs2_base, jffs2_size, nodeList, progress);
- while (nodeList->prev)
- nodeList = nodeList->prev;
- }
- }
-
- if (strcmp(cmd, "scan") == 0
- || strcmp(cmd, "rescan") == 0)
- return CMD_SUCCESS;
-
- jaddr = jffs2_base;
- u = (struct jffs2_unknown_node *)jaddr;
-
- if (strcmp(cmd,"dump") == 0) {
- printf("JFFS2 base: 0x%lx\n",jffs2_base);
- printf("JFFS2 size: 0x%lx\n",jffs2_size);
- nodes = showNodesOfNumRange(nodeList, "all");
- printf("%d nodes\n", nodes);
- return CMD_SUCCESS;
- }
- else if (strcmp(cmd,"node") == 0) {
- if (argc == optind + 1)
- range = "all";
- else
- range = argv[optind + 1];
- nodes = showNodesOfNumRange(nodeList, range);
- return CMD_SUCCESS;
- }
-
- /* if you want a range of dirents or inodes, you need to specify the
- ino and/or pino; don't use "dirent" or "inode" */
- else if (strcmp(cmd,"dirent") == 0) {
- nodes = showNodesOfType(nodeList, JFFS2_NODETYPE_DIRENT);
- printf("%d nodes\n", nodes);
- }
- else if (strcmp(cmd,"inode") == 0) {
- nodes = showNodesOfType(nodeList, JFFS2_NODETYPE_INODE);
- printf("%d nodes\n", nodes);
- }
-
- /* TODO: this can be reimplemented just like "ino"? */
- else if (strcmp(cmd,"pino") == 0) {
- jint32 pino;
- struct jffs2_unknown_node_list *u = nodeList;
-
- if (argc != optind+2)
- return CMD_PARAM_ERROR;
-
- pino = strtol(argv[optind+1],0,0);
-
- do {
- u = findNextMatchingDirent(u, pino, -1, NULL);
- if (u != NULL && u->u != NULL) {
- showNode(u->nodenum, u->u);
- u = u->next;
- }
- } while (u != NULL && u->u != NULL);
- }
-
- else if (strcmp(cmd,"ino") == 0) {
-
- if (argc == optind+1)
- range = "all";
- else
- range = argv[optind+1];
-
- nodes = showNodesOfTypeRange(nodeList,
- JFFS2_NODETYPE_DIRENT, NULL, range);
- nodes += showNodesOfTypeRange(nodeList,
- JFFS2_NODETYPE_INODE, NULL, range);
- printf("%d nodes\n", nodes);
- return CMD_SUCCESS;
- }
-
- else if (strcmp(cmd,"cp") == 0) {
- printf("TODO: jffs2 cp {fname} {to_fname}\n"
- "(it's harder than it sounds!)\n");
- return CMD_SUCCESS;
- }
-
- else if (strcmp(cmd,"get") == 0) {
- struct jffs2_callback_args args;
-
- if (argc == (optind + 3))
- args.dest = (void*)strtoul(argv[optind + 2], 0, 0);
- else
- return CMD_PARAM_ERROR;
-
- setenv(JFFS2_FSIZE_STR,0);
- fname = argv[optind + 1];
- bytes = readDirent(nodeList, fname, callback_to_memory, &args);
- if (bytes >= 0)
- shell_sprintf(JFFS2_FSIZE_STR,"%d",bytes);
- printf("%d bytes\n", bytes);
- return CMD_SUCCESS;
- }
-
- else if (strcmp(cmd,"cat") == 0) {
- if (argc != optind + 2)
- return CMD_PARAM_ERROR;
-
- setenv(JFFS2_FSIZE_STR,0);
- fname = argv[optind + 1];
- bytes = readDirent(nodeList, fname, callback_to_console, NULL);
- if (bytes >= 0)
- shell_sprintf(JFFS2_FSIZE_STR,"%d",bytes);
- return CMD_SUCCESS;
- }
-
- else if (strcmp(cmd, "mkdir") == 0) {
- if (argc != optind + 2)
- return CMD_PARAM_ERROR;
-
- createInode(nodeList, nodetot++,
- JFFS2_MODE_DIR
- | S_IRUGO | S_IXOTH | S_IXGRP | S_IRWXU,
- argv[optind + 1]);
-
- return CMD_SUCCESS;
- }
-
- else if (strcmp(cmd, "chmod") == 0) {
- printf("TODO: implement chmod\n");
- return CMD_SUCCESS;
- }
-
- else if (strcmp(cmd, "add") == 0) {
- if (argc != (optind + 4))
- return CMD_PARAM_ERROR;
-
- char *path;
- long addr, len;
-
- path = argv[optind + 1];
- addr = strtol(argv[optind + 2], 0, 0);
- len = strtol(argv[optind + 3], 0, 0);
-
- if (findDirentByPath(nodeList, path) == NULL)
- createInode(nodeList, nodetot++,
- JFFS2_MODE_REG | S_IRUGO | S_IWUSR,
- path);
-
- appendInode(nodeList, nodetot++, path, (void*)addr, len);
- return CMD_SUCCESS;
- }
-
- else if (strcmp(cmd, "mv") == 0 && (argc == (optind + 3))) {
- char *oldname, *newname;
-
- oldname = argv[optind + 1];
- newname = argv[optind + 2];
-
- moveDirent(nodeList, nodetot, oldname, newname);
- return CMD_SUCCESS;
- }
-
- else if(strcmp(cmd, "rm") == 0 && (argc == (optind + 2))) {
- deleteDirent(nodeList, nodetot, argv[optind + 1]);
- return CMD_SUCCESS;
- }
-
- else if ((strcmp(cmd, "ls") == 0) || (strcmp(cmd, "qry") == 0)) {
- int ftot;
- char *path;
- struct jffs2_umoninfo ju;
-
- /* If the sub-command is "qry", then we do essentially the same
- * thing as "ls" except quietly (just populate the shell variables).
- */
- if (cmd[0] == 'q')
- ju.quiet = 1;
- else
- ju.quiet = 0;
+ ulong jaddr, jsize;
+ struct jffs2_unknown_node *u;
+ int opt;
+ char *env, *cmd, *fname, *range;
+ int bytes, nodes;
+ void (*progress)(int percent) = progress_callback;
+
+ static int nodetot = 0;
+ static struct jffs2_unknown_node_list *nodeList = NULL;
+
+ jint32 jffs2_base = JFFS2_DEFAULT_BASE;
+ jint32 jffs2_size = 0;
+
+ assert(sizeof(jint32) == 4);
+ assert(sizeof(jint16) == 2);
+ assert(sizeof(jint8) == 1);
+
+ jffs2_verify_crc = 0;
+
+ if((env = getenv("JFFS2BASE"))) {
+ jffs2_base = (jint32)strtoul(env,0,0);
+ }
+
+ if((env = getenv("JFFS2SIZE"))) {
+ jffs2_size = (jint32)strtoul(env,0,0);
+ }
+
+ while((opt=getopt(argc,argv,"b:cs:q")) != -1) {
+ switch(opt) {
+ case 'b':
+ jffs2_base = (jint32)strtoul(optarg,0,0);
+ break;
+ case 'c':
+ jffs2_verify_crc = 1;
+ break;
+ case 's':
+ jffs2_size = (jint32)strtoul(optarg,0,0);
+ break;
+ case 'q':
+ progress = NULL;
+ break;
+ default:
+ return(CMD_PARAM_ERROR);
+ }
+ }
+
+ if(argc < optind + 1) {
+ return(CMD_PARAM_ERROR);
+ }
+
+ cmd = argv[optind];
+
+ if(strcmp(cmd, "mkfs") == 0) {
+ if(argc <= optind + 1) {
+ jaddr = jffs2_base;
+ } else {
+ jaddr = strtoul(argv[optind + 1], 0, 0);
+ }
+ if(argc <= optind + 2) {
+ jsize = jffs2_size;
+ } else {
+ jsize = strtoul(argv[optind + 2], 0, 0);
+ }
+
+ nodeList = discardNodeList(nodeList);
+
+ /* TODO: progress feedback needs to be optional? */
+ return formatMedium(jaddr, jsize, progress) ?
+ CMD_FAILURE : CMD_SUCCESS;
+ }
+
+ if(strcmp(cmd, "rescan") == 0) {
+ nodeList = discardNodeList(nodeList);
+ }
- ju.direntsize = -1;
- ju.direntname[0] = 0;
- setenv(JFFS2_FNAME_STR,0);
- setenv(JFFS2_FSIZE_STR,0);
+ /* commands below this point require a scanMedium() */
- if (argc == optind + 2)
- path = argv[optind + 1];
- else
- path = NULL;
- ftot = listDirentByPath(nodeList, path, &ju);
- if ((ftot > 0) && (!ju.quiet))
- printf(" Total: %d\n",ftot);
+ if(nodeList == NULL) {
+ initNodeList(&nodeList);
+ if(nodeList != NULL) {
+ nodetot = scanMedium(jffs2_base, jffs2_size, nodeList, progress);
+ while(nodeList->prev) {
+ nodeList = nodeList->prev;
+ }
+ }
+ }
+
+ if(strcmp(cmd, "scan") == 0
+ || strcmp(cmd, "rescan") == 0) {
+ return CMD_SUCCESS;
+ }
+
+ jaddr = jffs2_base;
+ u = (struct jffs2_unknown_node *)jaddr;
+
+ if(strcmp(cmd,"dump") == 0) {
+ printf("JFFS2 base: 0x%lx\n",jffs2_base);
+ printf("JFFS2 size: 0x%lx\n",jffs2_size);
+ nodes = showNodesOfNumRange(nodeList, "all");
+ printf("%d nodes\n", nodes);
+ return CMD_SUCCESS;
+ } else if(strcmp(cmd,"node") == 0) {
+ if(argc == optind + 1) {
+ range = "all";
+ } else {
+ range = argv[optind + 1];
+ }
+ nodes = showNodesOfNumRange(nodeList, range);
+ return CMD_SUCCESS;
+ }
+
+ /* if you want a range of dirents or inodes, you need to specify the
+ ino and/or pino; don't use "dirent" or "inode" */
+ else if(strcmp(cmd,"dirent") == 0) {
+ nodes = showNodesOfType(nodeList, JFFS2_NODETYPE_DIRENT);
+ printf("%d nodes\n", nodes);
+ } else if(strcmp(cmd,"inode") == 0) {
+ nodes = showNodesOfType(nodeList, JFFS2_NODETYPE_INODE);
+ printf("%d nodes\n", nodes);
+ }
+
+ /* TODO: this can be reimplemented just like "ino"? */
+ else if(strcmp(cmd,"pino") == 0) {
+ jint32 pino;
+ struct jffs2_unknown_node_list *u = nodeList;
+
+ if(argc != optind+2) {
+ return CMD_PARAM_ERROR;
+ }
+
+ pino = strtol(argv[optind+1],0,0);
+
+ do {
+ u = findNextMatchingDirent(u, pino, -1, NULL);
+ if(u != NULL && u->u != NULL) {
+ showNode(u->nodenum, u->u);
+ u = u->next;
+ }
+ } while(u != NULL && u->u != NULL);
+ }
+
+ else if(strcmp(cmd,"ino") == 0) {
+
+ if(argc == optind+1) {
+ range = "all";
+ } else {
+ range = argv[optind+1];
+ }
+
+ nodes = showNodesOfTypeRange(nodeList,
+ JFFS2_NODETYPE_DIRENT, NULL, range);
+ nodes += showNodesOfTypeRange(nodeList,
+ JFFS2_NODETYPE_INODE, NULL, range);
+ printf("%d nodes\n", nodes);
+ return CMD_SUCCESS;
+ }
+
+ else if(strcmp(cmd,"cp") == 0) {
+ printf("TODO: jffs2 cp {fname} {to_fname}\n"
+ "(it's harder than it sounds!)\n");
+ return CMD_SUCCESS;
+ }
- shell_sprintf(JFFS2_FTOT_STR,"%d",ftot);
+ else if(strcmp(cmd,"get") == 0) {
+ struct jffs2_callback_args args;
+
+ if(argc == (optind + 3)) {
+ args.dest = (void *)strtoul(argv[optind + 2], 0, 0);
+ } else {
+ return CMD_PARAM_ERROR;
+ }
+
+ setenv(JFFS2_FSIZE_STR,0);
+ fname = argv[optind + 1];
+ bytes = readDirent(nodeList, fname, callback_to_memory, &args);
+ if(bytes >= 0) {
+ shell_sprintf(JFFS2_FSIZE_STR,"%d",bytes);
+ }
+ printf("%d bytes\n", bytes);
+ return CMD_SUCCESS;
+ }
+
+ else if(strcmp(cmd,"cat") == 0) {
+ if(argc != optind + 2) {
+ return CMD_PARAM_ERROR;
+ }
+
+ setenv(JFFS2_FSIZE_STR,0);
+ fname = argv[optind + 1];
+ bytes = readDirent(nodeList, fname, callback_to_console, NULL);
+ if(bytes >= 0) {
+ shell_sprintf(JFFS2_FSIZE_STR,"%d",bytes);
+ }
+ return CMD_SUCCESS;
+ }
+
+ else if(strcmp(cmd, "mkdir") == 0) {
+ if(argc != optind + 2) {
+ return CMD_PARAM_ERROR;
+ }
+
+ createInode(nodeList, nodetot++,
+ JFFS2_MODE_DIR
+ | S_IRUGO | S_IXOTH | S_IXGRP | S_IRWXU,
+ argv[optind + 1]);
+
+ return CMD_SUCCESS;
+ }
+
+ else if(strcmp(cmd, "chmod") == 0) {
+ printf("TODO: implement chmod\n");
+ return CMD_SUCCESS;
+ }
+
+ else if(strcmp(cmd, "add") == 0) {
+ if(argc != (optind + 4)) {
+ return CMD_PARAM_ERROR;
+ }
- if (ju.direntsize > 0) {
- shell_sprintf(JFFS2_FSIZE_STR,"%d",ju.direntsize);
- setenv(JFFS2_FNAME_STR,ju.direntname);
+ char *path;
+ long addr, len;
+
+ path = argv[optind + 1];
+ addr = strtol(argv[optind + 2], 0, 0);
+ len = strtol(argv[optind + 3], 0, 0);
+
+ if(findDirentByPath(nodeList, path) == NULL)
+ createInode(nodeList, nodetot++,
+ JFFS2_MODE_REG | S_IRUGO | S_IWUSR,
+ path);
+
+ appendInode(nodeList, nodetot++, path, (void *)addr, len);
+ return CMD_SUCCESS;
+ }
+
+ else if(strcmp(cmd, "mv") == 0 && (argc == (optind + 3))) {
+ char *oldname, *newname;
+
+ oldname = argv[optind + 1];
+ newname = argv[optind + 2];
+
+ moveDirent(nodeList, nodetot, oldname, newname);
+ return CMD_SUCCESS;
}
- return CMD_SUCCESS;
- }
+ else if(strcmp(cmd, "rm") == 0 && (argc == (optind + 2))) {
+ deleteDirent(nodeList, nodetot, argv[optind + 1]);
+ return CMD_SUCCESS;
+ }
+
+ else if((strcmp(cmd, "ls") == 0) || (strcmp(cmd, "qry") == 0)) {
+ int ftot;
+ char *path;
+ struct jffs2_umoninfo ju;
+
+ /* If the sub-command is "qry", then we do essentially the same
+ * thing as "ls" except quietly (just populate the shell variables).
+ */
+ if(cmd[0] == 'q') {
+ ju.quiet = 1;
+ } else {
+ ju.quiet = 0;
+ }
+
+ ju.direntsize = -1;
+ ju.direntname[0] = 0;
+ setenv(JFFS2_FNAME_STR,0);
+ setenv(JFFS2_FSIZE_STR,0);
+
+ if(argc == optind + 2) {
+ path = argv[optind + 1];
+ } else {
+ path = NULL;
+ }
+ ftot = listDirentByPath(nodeList, path, &ju);
+ if((ftot > 0) && (!ju.quiet)) {
+ printf(" Total: %d\n",ftot);
+ }
+
+ shell_sprintf(JFFS2_FTOT_STR,"%d",ftot);
+
+ if(ju.direntsize > 0) {
+ shell_sprintf(JFFS2_FSIZE_STR,"%d",ju.direntsize);
+ setenv(JFFS2_FNAME_STR,ju.direntname);
+ }
+
+ return CMD_SUCCESS;
+ }
- printf("jffs2 cmd <%s> not found\n",cmd);
- return CMD_FAILURE;
+ printf("jffs2 cmd <%s> not found\n",cmd);
+ return CMD_FAILURE;
}
#endif