All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker.
@ 2015-12-21  8:41 Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 01/38] ubifs: pick some common definitions into ubifs_common.h Dongsheng Yang
                   ` (37 more replies)
  0 siblings, 38 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

Hi Brian,
	I picked ubifs_unpacker from David and Richard, and applied them
in my local tree, and rebased against latest mtd-utils. Please consider
taking this patchset.

David Gstir (10):
  ubifs: fix typo in ubifs_read
  Make cli byte parsing from ubi-utils available for all tools
  ubifs: add decompression functions
  ubifs: remove ununsed ubifs context from key helpers
  ubifs: keep scan buffer in ubifs_info
  ubifs: extend master scanning code
  ubifs: add missing include to defs.h
  ubifs: Add more key helper functions
  ubifs: add emubi, a minimal UBI emulation layer
  UBIFS: introduce ubifs_unpacker tool.

Dongsheng Yang (27):
  ubifs: pick some common definitions into ubifs_common.h
  ubifs: move the all io related code into io.[h|c]
  ubifs: remove the including of mkfs.ubifs.h in lpt.c
  ubifs: cut off the dependence from compr.o to mkfs.ubifs
  ubifs: cut off the dependence from devtable to mkfs.ubifs.h
  ubifs: introduce ubifs-utils/include and ubifs-utils/lib
  ubifs: move more functions into io lib
  ubifs: introduce a new tool ubifs_dump
  ubifs: introduce list.h
  ubifs: copy some important data in ubifs.h from kernel to ubifs-utils
  ubifs: copy some important functions in key.h from kernel to
    ubifs-utils
  ubifs: ubifs_dump: add dump_ch and dump_node functions
  ubifs: defs.h: introduce some compatible definition for printk class
  ubifs: io: introduce ubifs_read function to read ubi volume
  ubifs: ubifs_dump: dump super block
  ubifs: introduce scan for ubifs-utils
  ubifs: add some more compatible definitions in defs.h
  ubifs: ubifs_dump: dump master node
  ubifs: ubifs_dump: dump log area
  ubifs: introduce lprops lib
  ubifs: lpt: implement functions to scan lpt
  ubifs: ubifs_dump: dump lpt area
  ubifs: ubifs_dump: dump index area
  ubifs: defs.h: introduce some compatible definitions about integer
    such as __u16
  ubifs: introduce hexdump lib
  ubifs: ubifs_dump: dump data in hex format
  gitignore: add ubifs_dump to gitignore.

Richard Weinberger (1):
  ubifs: add complete version of list.h

 .gitignore                                         |    1 +
 Makefile                                           |   21 +-
 include/common.h                                   |   90 ++
 ubi-utils/include/ubiutils-common.h                |    2 -
 ubi-utils/mtdinfo.c                                |    6 +-
 ubi-utils/ubiattach.c                              |    6 +-
 ubi-utils/ubiformat.c                              |    8 +-
 ubi-utils/ubimkvol.c                               |    6 +-
 ubi-utils/ubinfo.c                                 |   10 +-
 ubi-utils/ubinize.c                                |   10 +-
 ubi-utils/ubirsvol.c                               |    2 +-
 ubi-utils/ubiutils-common.c                        |   93 --
 ubifs-utils/COPYING                                |  340 ++++++
 ubifs-utils/README                                 |    9 +
 ubifs-utils/include/compr.h                        |   46 +
 ubifs-utils/include/crc16.h                        |   27 +
 ubifs-utils/include/defs.h                         |  216 ++++
 ubifs-utils/include/devtable.h                     |   55 +
 ubifs-utils/include/emubi.h                        |   82 ++
 ubifs-utils/include/hashtable.h                    |  199 +++
 ubifs-utils/include/hashtable_itr.h                |  112 ++
 ubifs-utils/include/hashtable_private.h            |   85 ++
 ubifs-utils/include/hexdump.h                      |   21 +
 ubifs-utils/include/io.h                           |   23 +
 ubifs-utils/include/key.h                          |  347 ++++++
 ubifs-utils/include/list.h                         |  605 ++++++++++
 ubifs-utils/include/list_sort.h                    |   11 +
 ubifs-utils/include/lprops.h                       |    6 +
 ubifs-utils/include/lpt.h                          |   32 +
 ubifs-utils/include/master.h                       |    7 +
 ubifs-utils/include/scan.h                         |    8 +
 ubifs-utils/include/ubifs.h                        |  597 +++++++++
 ubifs-utils/include/ubifs_common.h                 |   50 +
 ubifs-utils/lib/compr.c                            |  305 +++++
 ubifs-utils/lib/crc16.c                            |   56 +
 ubifs-utils/lib/devtable.c                         |  525 ++++++++
 ubifs-utils/lib/emubi.c                            |  371 ++++++
 ubifs-utils/lib/hashtable.c                        |  277 +++++
 ubifs-utils/lib/hashtable_itr.c                    |  176 +++
 ubifs-utils/lib/hexdump.c                          |  200 +++
 ubifs-utils/lib/io.c                               |  212 ++++
 ubifs-utils/lib/list_sort.c                        |  157 +++
 ubifs-utils/lib/lprops.c                           |   79 ++
 ubifs-utils/lib/lpt.c                              | 1275 ++++++++++++++++++++
 ubifs-utils/lib/master.c                           |  311 +++++
 ubifs-utils/lib/scan.c                             |  316 +++++
 ubifs-utils/mkfs.ubifs/COPYING                     |  340 ------
 ubifs-utils/mkfs.ubifs/README                      |    9 -
 ubifs-utils/mkfs.ubifs/compr.c                     |  236 ----
 ubifs-utils/mkfs.ubifs/compr.h                     |   46 -
 ubifs-utils/mkfs.ubifs/crc16.c                     |   56 -
 ubifs-utils/mkfs.ubifs/crc16.h                     |   27 -
 ubifs-utils/mkfs.ubifs/defs.h                      |   92 --
 ubifs-utils/mkfs.ubifs/devtable.c                  |  524 --------
 ubifs-utils/mkfs.ubifs/hashtable/hashtable.c       |  277 -----
 ubifs-utils/mkfs.ubifs/hashtable/hashtable.h       |  199 ---
 ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.c   |  176 ---
 ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.h   |  112 --
 .../mkfs.ubifs/hashtable/hashtable_private.h       |   85 --
 ubifs-utils/mkfs.ubifs/key.h                       |  207 ----
 ubifs-utils/mkfs.ubifs/lpt.c                       |  578 ---------
 ubifs-utils/mkfs.ubifs/lpt.h                       |   28 -
 ubifs-utils/mkfs.ubifs/mkfs.ubifs.c                |  210 +---
 ubifs-utils/mkfs.ubifs/mkfs.ubifs.h                |  102 +-
 ubifs-utils/mkfs.ubifs/ubifs.h                     |  450 -------
 ubifs-utils/ubifs_dump/ubifs_dump.c                |  977 +++++++++++++++
 ubifs-utils/ubifs_unpack/index.c                   |  648 ++++++++++
 ubifs-utils/ubifs_unpack/replay.c                  |  865 +++++++++++++
 ubifs-utils/ubifs_unpack/ubifs_unpack.c            |  619 ++++++++++
 ubifs-utils/ubifs_unpack/ubifs_unpack.h            |  107 ++
 70 files changed, 10505 insertions(+), 3858 deletions(-)
 create mode 100644 ubifs-utils/COPYING
 create mode 100644 ubifs-utils/README
 create mode 100644 ubifs-utils/include/compr.h
 create mode 100644 ubifs-utils/include/crc16.h
 create mode 100644 ubifs-utils/include/defs.h
 create mode 100644 ubifs-utils/include/devtable.h
 create mode 100644 ubifs-utils/include/emubi.h
 create mode 100644 ubifs-utils/include/hashtable.h
 create mode 100644 ubifs-utils/include/hashtable_itr.h
 create mode 100644 ubifs-utils/include/hashtable_private.h
 create mode 100644 ubifs-utils/include/hexdump.h
 create mode 100644 ubifs-utils/include/io.h
 create mode 100644 ubifs-utils/include/key.h
 create mode 100644 ubifs-utils/include/list.h
 create mode 100644 ubifs-utils/include/list_sort.h
 create mode 100644 ubifs-utils/include/lprops.h
 create mode 100644 ubifs-utils/include/lpt.h
 create mode 100644 ubifs-utils/include/master.h
 create mode 100644 ubifs-utils/include/scan.h
 create mode 100644 ubifs-utils/include/ubifs.h
 create mode 100644 ubifs-utils/include/ubifs_common.h
 create mode 100644 ubifs-utils/lib/compr.c
 create mode 100644 ubifs-utils/lib/crc16.c
 create mode 100644 ubifs-utils/lib/devtable.c
 create mode 100644 ubifs-utils/lib/emubi.c
 create mode 100644 ubifs-utils/lib/hashtable.c
 create mode 100644 ubifs-utils/lib/hashtable_itr.c
 create mode 100644 ubifs-utils/lib/hexdump.c
 create mode 100644 ubifs-utils/lib/io.c
 create mode 100644 ubifs-utils/lib/list_sort.c
 create mode 100644 ubifs-utils/lib/lprops.c
 create mode 100644 ubifs-utils/lib/lpt.c
 create mode 100644 ubifs-utils/lib/master.c
 create mode 100644 ubifs-utils/lib/scan.c
 delete mode 100644 ubifs-utils/mkfs.ubifs/COPYING
 delete mode 100644 ubifs-utils/mkfs.ubifs/README
 delete mode 100644 ubifs-utils/mkfs.ubifs/compr.c
 delete mode 100644 ubifs-utils/mkfs.ubifs/compr.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/crc16.c
 delete mode 100644 ubifs-utils/mkfs.ubifs/crc16.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/defs.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/devtable.c
 delete mode 100644 ubifs-utils/mkfs.ubifs/hashtable/hashtable.c
 delete mode 100644 ubifs-utils/mkfs.ubifs/hashtable/hashtable.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.c
 delete mode 100644 ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/hashtable/hashtable_private.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/key.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/lpt.c
 delete mode 100644 ubifs-utils/mkfs.ubifs/lpt.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/ubifs.h
 create mode 100644 ubifs-utils/ubifs_dump/ubifs_dump.c
 create mode 100644 ubifs-utils/ubifs_unpack/index.c
 create mode 100644 ubifs-utils/ubifs_unpack/replay.c
 create mode 100644 ubifs-utils/ubifs_unpack/ubifs_unpack.c
 create mode 100644 ubifs-utils/ubifs_unpack/ubifs_unpack.h

-- 
1.8.4.2

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 01/38] ubifs: pick some common definitions into ubifs_common.h
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 02/38] ubifs: move the all io related code into io.[h|c] Dongsheng Yang
                   ` (36 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

Currently, lpt.c is including mkfs.ubifs.h. That make
the lpt depend on mkfs.ubifs. It's not good if we want
to introduce some more tools for ubifs, such as fsck.ubifs.

This patch start to cut off the dependence from libs, such
as lpt, devtable, to mkfs.ubifs.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/mkfs.ubifs/mkfs.ubifs.h   | 46 +-------------------------------
 ubifs-utils/mkfs.ubifs/ubifs_common.h | 50 +++++++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 45 deletions(-)
 create mode 100644 ubifs-utils/mkfs.ubifs/ubifs_common.h

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h
index 944a159..d6d46a2 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h
@@ -23,37 +23,12 @@
 #ifndef __MKFS_UBIFS_H__
 #define __MKFS_UBIFS_H__
 
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <limits.h>
-#include <string.h>
-#include <stdint.h>
-#include <endian.h>
-#include <byteswap.h>
-#include <linux/types.h>
-#include <linux/fs.h>
-
-#include <getopt.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <errno.h>
-#include <libgen.h>
-#include <ctype.h>
-#include <uuid/uuid.h>
-#include <sys/file.h>
-
-#include <mtd/ubifs-media.h>
+#include "ubifs_common.h"
 
 /* common.h requires the PROGRAM_NAME macro */
 #define PROGRAM_NAME "mkfs.ubifs"
 #include "common.h"
 
-#include "libubi.h"
-#include "defs.h"
 #include "crc16.h"
 #include "ubifs.h"
 #include "key.h"
@@ -74,25 +49,6 @@
 #error MKFS_UBIFS_COMPR_ZLIB != UBIFS_COMPR_ZLIB
 #endif
 
-extern int verbose;
-extern int debug_level;
-
-#define dbg_msg(lvl, fmt, ...) do {if (debug_level >= lvl)                \
-	printf("mkfs.ubifs: %s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__); \
-} while(0)
-
-#define err_msg(fmt, ...) ({                                \
-	fprintf(stderr, "Error: " fmt "\n", ##__VA_ARGS__); \
-	-1;                                                 \
-})
-
-#define sys_err_msg(fmt, ...) ({                                         \
-	int err_ = errno;                                                \
-	fprintf(stderr, "Error: " fmt "\n", ##__VA_ARGS__);              \
-	fprintf(stderr, "       %s (error %d)\n", strerror(err_), err_); \
-	-1;                                                              \
-})
-
 /**
  * struct path_htbl_element - an element of the path hash table.
  * @path: the UBIFS path the element describes (the key of the element)
diff --git a/ubifs-utils/mkfs.ubifs/ubifs_common.h b/ubifs-utils/mkfs.ubifs/ubifs_common.h
new file mode 100644
index 0000000..958c20a
--- /dev/null
+++ b/ubifs-utils/mkfs.ubifs/ubifs_common.h
@@ -0,0 +1,50 @@
+#ifndef __UBIFS_COMMON_H__
+#define __UBIFS_COMMON_H__
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <string.h>
+#include <stdint.h>
+#include <endian.h>
+#include <byteswap.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <libgen.h>
+#include <ctype.h>
+#include <uuid/uuid.h>
+#include <sys/file.h>
+
+#include <mtd/ubifs-media.h>
+
+#include "libubi.h"
+#include "defs.h"
+
+extern int verbose;
+extern int debug_level;
+
+#define dbg_msg(lvl, fmt, ...) do {if (debug_level >= lvl)                \
+	printf("ubifs: %s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__); \
+} while(0)
+
+#define err_msg(fmt, ...) ({                                \
+	fprintf(stderr, "Error: " fmt "\n", ##__VA_ARGS__); \
+	-1;                                                 \
+})
+
+#define sys_err_msg(fmt, ...) ({                                         \
+	int err_ = errno;                                                \
+	fprintf(stderr, "Error: " fmt "\n", ##__VA_ARGS__);              \
+	fprintf(stderr, "       %s (error %d)\n", strerror(err_), err_); \
+	-1;                                                              \
+})
+#endif
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 02/38] ubifs: move the all io related code into io.[h|c]
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 01/38] ubifs: pick some common definitions into ubifs_common.h Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 03/38] ubifs: remove the including of mkfs.ubifs.h in lpt.c Dongsheng Yang
                   ` (35 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

To cut off the dependence from common lib to mkfs.ubifs,
this patch refactor the io related functions into a new
lib named as io.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 Makefile                            |  2 +-
 ubifs-utils/mkfs.ubifs/io.c         | 33 +++++++++++++++++++++++++++++++++
 ubifs-utils/mkfs.ubifs/io.h         | 15 +++++++++++++++
 ubifs-utils/mkfs.ubifs/lpt.c        | 10 +++++-----
 ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 34 +++-------------------------------
 ubifs-utils/mkfs.ubifs/mkfs.ubifs.h |  2 +-
 6 files changed, 58 insertions(+), 38 deletions(-)
 create mode 100644 ubifs-utils/mkfs.ubifs/io.c
 create mode 100644 ubifs-utils/mkfs.ubifs/io.h

diff --git a/Makefile b/Makefile
index bd9504a..8864675 100644
--- a/Makefile
+++ b/Makefile
@@ -126,7 +126,7 @@ $(foreach v,$(UBI_BINS),$(eval $(call mkdep,ubi-utils/,$(v),libubi.a ubiutils-co
 #
 # Utils in ubifs-utils subdir
 #
-obj-mkfs.ubifs = crc16.o lpt.o compr.o devtable.o \
+obj-mkfs.ubifs = crc16.o lpt.o compr.o devtable.o io.o\
 	hashtable/hashtable.o hashtable/hashtable_itr.o
 LDFLAGS_mkfs.ubifs = $(ZLIBLDFLAGS) $(LZOLDFLAGS) $(UUIDLDFLAGS)
 LDLIBS_mkfs.ubifs = -lz $(LZOLDLIBS) -lm -luuid
diff --git a/ubifs-utils/mkfs.ubifs/io.c b/ubifs-utils/mkfs.ubifs/io.c
new file mode 100644
index 0000000..7aba0a6
--- /dev/null
+++ b/ubifs-utils/mkfs.ubifs/io.c
@@ -0,0 +1,33 @@
+#include "io.h"
+#define PROGRAM_NAME "ubifs-io"
+#include <common.h>
+
+int out_fd;
+int out_ubi;
+libubi_t ubi;
+
+/**
+ * write_leb - copy the image of a LEB to the output target.
+ * @lnum: LEB number
+ * @len: length of data in the buffer
+ * @buf: buffer (must be at least c->leb_size bytes)
+ */
+int write_leb(struct ubifs_info *c, int lnum, int len, void *buf)
+{
+	off_t pos = (off_t)lnum * c->leb_size;
+
+	dbg_msg(3, "LEB %d len %d", lnum, len);
+	memset(buf + len, 0xff, c->leb_size - len);
+	if (out_ubi)
+		if (ubi_leb_change_start(ubi, out_fd, lnum, c->leb_size))
+			return sys_err_msg("ubi_leb_change_start failed");
+
+	if (lseek(out_fd, pos, SEEK_SET) != pos)
+		return sys_err_msg("lseek failed seeking %"PRIdoff_t, pos);
+
+	if (write(out_fd, buf, c->leb_size) != c->leb_size)
+		return sys_err_msg("write failed writing %d bytes at pos %"PRIdoff_t,
+				   c->leb_size, pos);
+
+	return 0;
+}
diff --git a/ubifs-utils/mkfs.ubifs/io.h b/ubifs-utils/mkfs.ubifs/io.h
new file mode 100644
index 0000000..e24d0c6
--- /dev/null
+++ b/ubifs-utils/mkfs.ubifs/io.h
@@ -0,0 +1,15 @@
+/**
+ * Header file for the io to ubi volume
+ */
+#ifndef __UBIFS_IO_H__
+#define __UBIFS_IO_H__
+
+#include "ubifs_common.h"
+#include "ubifs.h"
+
+extern int out_fd;
+extern int out_ubi;
+extern libubi_t ubi;
+
+int write_leb(struct ubifs_info *c, int lnum, int len, void *buf);
+#endif
diff --git a/ubifs-utils/mkfs.ubifs/lpt.c b/ubifs-utils/mkfs.ubifs/lpt.c
index 6aa0b88..cee221c 100644
--- a/ubifs-utils/mkfs.ubifs/lpt.c
+++ b/ubifs-utils/mkfs.ubifs/lpt.c
@@ -410,7 +410,7 @@ int create_lpt(struct ubifs_info *c)
 			alen = ALIGN(len, c->min_io_size);
 			set_ltab(c, lnum, c->leb_size - alen, alen - len);
 			memset(p, 0xff, alen - len);
-			err = write_leb(lnum++, alen, buf);
+			err = write_leb(c, lnum++, alen, buf);
 			if (err)
 				goto out;
 			p = buf;
@@ -452,7 +452,7 @@ int create_lpt(struct ubifs_info *c)
 				set_ltab(c, lnum, c->leb_size - alen,
 					    alen - len);
 				memset(p, 0xff, alen - len);
-				err = write_leb(lnum++, alen, buf);
+				err = write_leb(c, lnum++, alen, buf);
 				if (err)
 					goto out;
 				p = buf;
@@ -499,7 +499,7 @@ int create_lpt(struct ubifs_info *c)
 			alen = ALIGN(len, c->min_io_size);
 			set_ltab(c, lnum, c->leb_size - alen, alen - len);
 			memset(p, 0xff, alen - len);
-			err = write_leb(lnum++, alen, buf);
+			err = write_leb(c, lnum++, alen, buf);
 			if (err)
 				goto out;
 			p = buf;
@@ -522,7 +522,7 @@ int create_lpt(struct ubifs_info *c)
 		alen = ALIGN(len, c->min_io_size);
 		set_ltab(c, lnum, c->leb_size - alen, alen - len);
 		memset(p, 0xff, alen - len);
-		err = write_leb(lnum++, alen, buf);
+		err = write_leb(c, lnum++, alen, buf);
 		if (err)
 			goto out;
 		p = buf;
@@ -542,7 +542,7 @@ int create_lpt(struct ubifs_info *c)
 
 	/* Write remaining buffer */
 	memset(p, 0xff, alen - len);
-	err = write_leb(lnum, alen, buf);
+	err = write_leb(c, lnum, alen, buf);
 	if (err)
 		goto out;
 
diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 27f8d0a..47f4025 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -101,7 +101,6 @@ struct inum_mapping {
  */
 struct ubifs_info info_;
 static struct ubifs_info *c = &info_;
-static libubi_t ubi;
 
 /* Debug levels are: 0 (none), 1 (statistics), 2 (files) ,3 (more details) */
 int debug_level;
@@ -112,8 +111,6 @@ static char *root;
 static int root_len;
 static struct stat root_st;
 static char *output;
-static int out_fd;
-static int out_ubi;
 static int squash_owner;
 static int do_create_inum_attr;
 
@@ -753,31 +750,6 @@ static void prepare_node(void *node, int len)
 	ch->crc = cpu_to_le32(crc);
 }
 
-/**
- * write_leb - copy the image of a LEB to the output target.
- * @lnum: LEB number
- * @len: length of data in the buffer
- * @buf: buffer (must be at least c->leb_size bytes)
- */
-int write_leb(int lnum, int len, void *buf)
-{
-	off_t pos = (off_t)lnum * c->leb_size;
-
-	dbg_msg(3, "LEB %d len %d", lnum, len);
-	memset(buf + len, 0xff, c->leb_size - len);
-	if (out_ubi)
-		if (ubi_leb_change_start(ubi, out_fd, lnum, c->leb_size))
-			return sys_err_msg("ubi_leb_change_start failed");
-
-	if (lseek(out_fd, pos, SEEK_SET) != pos)
-		return sys_err_msg("lseek failed seeking %"PRIdoff_t, pos);
-
-	if (write(out_fd, buf, c->leb_size) != c->leb_size)
-		return sys_err_msg("write failed writing %d bytes at pos %"PRIdoff_t,
-				   c->leb_size, pos);
-
-	return 0;
-}
 
 /**
  * write_empty_leb - copy the image of an empty LEB to the output target.
@@ -785,7 +757,7 @@ int write_leb(int lnum, int len, void *buf)
  */
 static int write_empty_leb(int lnum)
 {
-	return write_leb(lnum, 0, leb_buf);
+	return write_leb(c, lnum, 0, leb_buf);
 }
 
 /**
@@ -841,7 +813,7 @@ static int write_node(void *node, int len, int lnum)
 
 	len = do_pad(leb_buf, len);
 
-	return write_leb(lnum, len, leb_buf);
+	return write_leb(c, lnum, len, leb_buf);
 }
 
 /**
@@ -951,7 +923,7 @@ static int flush_nodes(void)
 	if (!head_offs)
 		return 0;
 	len = do_pad(leb_buf, head_offs);
-	err = write_leb(head_lnum, len, leb_buf);
+	err = write_leb(c, head_lnum, len, leb_buf);
 	if (err)
 		return err;
 	set_lprops(head_lnum, head_offs, head_flags);
diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h
index d6d46a2..ba646a6 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h
@@ -34,6 +34,7 @@
 #include "key.h"
 #include "lpt.h"
 #include "compr.h"
+#include "io.h"
 
 /*
  * Compression flags are duplicated so that compr.c can compile without ubifs.h.
@@ -88,7 +89,6 @@ extern struct ubifs_info info_;
 
 struct hashtable_itr;
 
-int write_leb(int lnum, int len, void *buf);
 int parse_devtable(const char *tbl_file);
 struct path_htbl_element *devtbl_find_path(const char *path);
 struct name_htbl_element *devtbl_find_name(struct path_htbl_element *ph_elt,
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 03/38] ubifs: remove the including of mkfs.ubifs.h in lpt.c
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 01/38] ubifs: pick some common definitions into ubifs_common.h Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 02/38] ubifs: move the all io related code into io.[h|c] Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 04/38] ubifs: cut off the dependence from compr.o to mkfs.ubifs Dongsheng Yang
                   ` (34 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

As we have a ubifs_common.h and a seperate io lib, then
remove the including of mkfs.ubifs.h in lpt.c

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/mkfs.ubifs/lpt.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/ubifs-utils/mkfs.ubifs/lpt.c b/ubifs-utils/mkfs.ubifs/lpt.c
index cee221c..100d747 100644
--- a/ubifs-utils/mkfs.ubifs/lpt.c
+++ b/ubifs-utils/mkfs.ubifs/lpt.c
@@ -20,7 +20,16 @@
  *          Artem Bityutskiy
  */
 
-#include "mkfs.ubifs.h"
+#include "ubifs_common.h"
+
+/* common.h requires the PROGRAM_NAME macro */
+#define PROGRAM_NAME "ubifs-lpt"
+#include "common.h"
+
+#include "crc16.h"
+#include "ubifs.h"
+#include "lpt.h"
+#include "io.h"
 
 /**
  * do_calc_lpt_geom - calculate sizes for the LPT area.
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 04/38] ubifs: cut off the dependence from compr.o to mkfs.ubifs
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (2 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 03/38] ubifs: remove the including of mkfs.ubifs.h in lpt.c Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 05/38] ubifs: cut off the dependence from devtable to mkfs.ubifs.h Dongsheng Yang
                   ` (33 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

remove the including of mkfs.ubifs.h in compr lib and
drop the reference of globle variable info_ from compr to mkfs.ubifs.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/mkfs.ubifs/compr.c      | 22 +++++++---------------
 ubifs-utils/mkfs.ubifs/compr.h      |  3 +--
 ubifs-utils/mkfs.ubifs/mkfs.ubifs.c |  8 ++++++--
 3 files changed, 14 insertions(+), 19 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/compr.c b/ubifs-utils/mkfs.ubifs/compr.c
index 8eff186..54604d4 100644
--- a/ubifs-utils/mkfs.ubifs/compr.c
+++ b/ubifs-utils/mkfs.ubifs/compr.c
@@ -20,27 +20,19 @@
  *          Zoltan Sogor
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
+#include "ubifs_common.h"
 #ifndef WITHOUT_LZO
 #include <lzo/lzo1x.h>
 #endif
-#include <linux/types.h>
 
 #define crc32 __zlib_crc32
 #include <zlib.h>
 #undef crc32
 
 #include "compr.h"
-#include "mkfs.ubifs.h"
 
 static void *lzo_mem;
 static unsigned long long errcnt = 0;
-#ifndef WITHOUT_LZO
-static struct ubifs_info *c = &info_;
-#endif
 
 #define DEFLATE_DEF_LEVEL     Z_DEFAULT_COMPRESSION
 #define DEFLATE_DEF_WINBITS   11
@@ -121,7 +113,7 @@ static char *zlib_buf;
 
 #ifndef WITHOUT_LZO
 static int favor_lzo_compress(void *in_buf, size_t in_len, void *out_buf,
-			       size_t *out_len, int *type)
+				size_t *out_len, int *type, int lzo_percent)
 {
 	int lzo_ret, zlib_ret;
 	size_t lzo_len, zlib_len;
@@ -143,7 +135,7 @@ static int favor_lzo_compress(void *in_buf, size_t in_len, void *out_buf,
 
 		percent = (double)zlib_len / (double)lzo_len;
 		percent *= 100;
-		if (percent > 100 - c->favor_percent)
+		if (percent > 100 - lzo_percent)
 			goto select_lzo;
 		goto select_zlib;
 	}
@@ -167,8 +159,8 @@ select_zlib:
 }
 #endif
 
-int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len,
-		  int type)
+int compress_data(void *in_buf, size_t in_len, void *out_buf,
+		size_t *out_len, int type, int lzo_percent)
 {
 	int ret;
 
@@ -181,8 +173,8 @@ int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len,
 	{
 		switch (type) {
 #else
-	if (c->favor_lzo)
-		ret = favor_lzo_compress(in_buf, in_len, out_buf, out_len, &type);
+	if (lzo_percent)
+		ret = favor_lzo_compress(in_buf, in_len, out_buf, out_len, &type, lzo_percent);
 	else {
 		switch (type) {
 		case MKFS_UBIFS_COMPR_LZO:
diff --git a/ubifs-utils/mkfs.ubifs/compr.h b/ubifs-utils/mkfs.ubifs/compr.h
index e3dd95c..d44a2ba 100644
--- a/ubifs-utils/mkfs.ubifs/compr.h
+++ b/ubifs-utils/mkfs.ubifs/compr.h
@@ -38,8 +38,7 @@ enum compression_type
 	MKFS_UBIFS_COMPR_ZLIB,
 };
 
-int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len,
-		  int type);
+int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len, int type, int lzo_percent);
 int init_compression(void);
 void destroy_compression(void);
 
diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 47f4025..b2df5b1 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -1455,8 +1455,12 @@ static int add_file(const char *path_name, struct stat *st, ino_t inum,
 #endif
 		else
 			use_compr = c->default_compr;
-		compr_type = compress_data(buf, bytes_read, &dn->data,
-					   &out_len, use_compr);
+		if (c->favor_lzo)
+			compr_type = compress_data(buf, bytes_read, &dn->data,
+					   &out_len, use_compr, c->favor_percent);
+		else
+			compr_type = compress_data(buf, bytes_read, &dn->data,
+					   &out_len, use_compr, 0);
 		dn->compr_type = cpu_to_le16(compr_type);
 		dn_len = UBIFS_DATA_NODE_SZ + out_len;
 		/* Add data node to file system */
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 05/38] ubifs: cut off the dependence from devtable to mkfs.ubifs.h
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (3 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 04/38] ubifs: cut off the dependence from compr.o to mkfs.ubifs Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 06/38] ubifs: introduce ubifs-utils/include and ubifs-utils/lib Dongsheng Yang
                   ` (32 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

Refactor the devtable related definitions in mkfs.ubifs.h
to a new devtable.h

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/mkfs.ubifs/devtable.c   |  3 +-
 ubifs-utils/mkfs.ubifs/devtable.h   | 55 +++++++++++++++++++++++++++++++++++++
 ubifs-utils/mkfs.ubifs/mkfs.ubifs.h | 54 +-----------------------------------
 3 files changed, 58 insertions(+), 54 deletions(-)
 create mode 100644 ubifs-utils/mkfs.ubifs/devtable.h

diff --git a/ubifs-utils/mkfs.ubifs/devtable.c b/ubifs-utils/mkfs.ubifs/devtable.c
index dee035d..1fc0256 100644
--- a/ubifs-utils/mkfs.ubifs/devtable.c
+++ b/ubifs-utils/mkfs.ubifs/devtable.c
@@ -44,7 +44,8 @@
  * for more information about what the device table is.
  */
 
-#include "mkfs.ubifs.h"
+#include "ubifs_common.h"
+#include "devtable.h"
 #include "hashtable/hashtable.h"
 #include "hashtable/hashtable_itr.h"
 
diff --git a/ubifs-utils/mkfs.ubifs/devtable.h b/ubifs-utils/mkfs.ubifs/devtable.h
new file mode 100644
index 0000000..987d4d4
--- /dev/null
+++ b/ubifs-utils/mkfs.ubifs/devtable.h
@@ -0,0 +1,55 @@
+#include "ubifs_common.h"
+
+/**
+ * struct path_htbl_element - an element of the path hash table.
+ * @path: the UBIFS path the element describes (the key of the element)
+ * @name_htbl: one more (nested) hash table containing names of all
+ *             files/directories/device nodes which should be created at this
+ *             path
+ *
+ * See device table handling for more information.
+ */
+struct path_htbl_element {
+	const char *path;
+	struct hashtable *name_htbl;
+};
+
+/**
+ * struct name_htbl_element - an element in the name hash table
+ * @name: name of the file/directory/device node (the key of the element)
+ * @mode: accsess rights and file type
+ * @uid: user ID
+ * @gid: group ID
+ * @major: device node major number
+ * @minor: device node minor number
+ *
+ * This is an element of the name hash table. Name hash table sits in the path
+ * hash table elements and describes file names which should be created/changed
+ * at this path.
+ */
+struct name_htbl_element {
+	const char *name;
+	unsigned int mode;
+	unsigned int uid;
+	unsigned int gid;
+	dev_t dev;
+};
+
+extern struct ubifs_info info_;
+
+struct hashtable_itr;
+
+int parse_devtable(const char *tbl_file);
+struct path_htbl_element *devtbl_find_path(const char *path);
+struct name_htbl_element *devtbl_find_name(struct path_htbl_element *ph_elt,
+					   const char *name);
+int override_attributes(struct stat *st, struct path_htbl_element *ph_elt,
+			struct name_htbl_element *nh_elt);
+struct name_htbl_element *
+first_name_htbl_element(struct path_htbl_element *ph_elt,
+			struct hashtable_itr **itr);
+struct name_htbl_element *
+next_name_htbl_element(struct path_htbl_element *ph_elt,
+			struct hashtable_itr **itr);
+void free_devtable_info(void);
+
diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h
index ba646a6..1963e12 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h
@@ -34,6 +34,7 @@
 #include "key.h"
 #include "lpt.h"
 #include "compr.h"
+#include "devtable.h"
 #include "io.h"
 
 /*
@@ -50,57 +51,4 @@
 #error MKFS_UBIFS_COMPR_ZLIB != UBIFS_COMPR_ZLIB
 #endif
 
-/**
- * struct path_htbl_element - an element of the path hash table.
- * @path: the UBIFS path the element describes (the key of the element)
- * @name_htbl: one more (nested) hash table containing names of all
- *             files/directories/device nodes which should be created at this
- *             path
- *
- * See device table handling for more information.
- */
-struct path_htbl_element {
-	const char *path;
-	struct hashtable *name_htbl;
-};
-
-/**
- * struct name_htbl_element - an element in the name hash table
- * @name: name of the file/directory/device node (the key of the element)
- * @mode: accsess rights and file type
- * @uid: user ID
- * @gid: group ID
- * @major: device node major number
- * @minor: device node minor number
- *
- * This is an element of the name hash table. Name hash table sits in the path
- * hash table elements and describes file names which should be created/changed
- * at this path.
- */
-struct name_htbl_element {
-	const char *name;
-	unsigned int mode;
-	unsigned int uid;
-	unsigned int gid;
-	dev_t dev;
-};
-
-extern struct ubifs_info info_;
-
-struct hashtable_itr;
-
-int parse_devtable(const char *tbl_file);
-struct path_htbl_element *devtbl_find_path(const char *path);
-struct name_htbl_element *devtbl_find_name(struct path_htbl_element *ph_elt,
-					   const char *name);
-int override_attributes(struct stat *st, struct path_htbl_element *ph_elt,
-			struct name_htbl_element *nh_elt);
-struct name_htbl_element *
-first_name_htbl_element(struct path_htbl_element *ph_elt,
-			struct hashtable_itr **itr);
-struct name_htbl_element *
-next_name_htbl_element(struct path_htbl_element *ph_elt,
-		       struct hashtable_itr **itr);
-void free_devtable_info(void);
-
 #endif
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 06/38] ubifs: introduce ubifs-utils/include and ubifs-utils/lib
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (4 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 05/38] ubifs: cut off the dependence from devtable to mkfs.ubifs.h Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 07/38] ubifs: move more functions into io lib Dongsheng Yang
                   ` (31 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

Restructure the ubifs-utils/, introducing ubifs-utils/include
and ubifs-utils/lib to make the ubifs-utils/ better for scalability.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 Makefile                                           |   7 +-
 ubifs-utils/COPYING                                | 340 ++++++++++++
 ubifs-utils/README                                 |   9 +
 ubifs-utils/include/compr.h                        |  45 ++
 ubifs-utils/include/crc16.h                        |  27 +
 ubifs-utils/include/defs.h                         |  92 ++++
 ubifs-utils/include/devtable.h                     |  55 ++
 ubifs-utils/include/hashtable.h                    | 199 +++++++
 ubifs-utils/include/hashtable_itr.h                | 112 ++++
 ubifs-utils/include/hashtable_private.h            |  85 +++
 ubifs-utils/include/io.h                           |  15 +
 ubifs-utils/include/key.h                          | 207 ++++++++
 ubifs-utils/include/lpt.h                          |  28 +
 ubifs-utils/include/ubifs.h                        | 450 ++++++++++++++++
 ubifs-utils/include/ubifs_common.h                 |  50 ++
 ubifs-utils/lib/compr.c                            | 228 ++++++++
 ubifs-utils/lib/crc16.c                            |  56 ++
 ubifs-utils/lib/devtable.c                         | 525 ++++++++++++++++++
 ubifs-utils/lib/hashtable.c                        | 277 ++++++++++
 ubifs-utils/lib/hashtable_itr.c                    | 176 ++++++
 ubifs-utils/lib/io.c                               |  33 ++
 ubifs-utils/lib/lpt.c                              | 587 +++++++++++++++++++++
 ubifs-utils/mkfs.ubifs/COPYING                     | 340 ------------
 ubifs-utils/mkfs.ubifs/README                      |   9 -
 ubifs-utils/mkfs.ubifs/compr.c                     | 228 --------
 ubifs-utils/mkfs.ubifs/compr.h                     |  45 --
 ubifs-utils/mkfs.ubifs/crc16.c                     |  56 --
 ubifs-utils/mkfs.ubifs/crc16.h                     |  27 -
 ubifs-utils/mkfs.ubifs/defs.h                      |  92 ----
 ubifs-utils/mkfs.ubifs/devtable.c                  | 525 ------------------
 ubifs-utils/mkfs.ubifs/devtable.h                  |  55 --
 ubifs-utils/mkfs.ubifs/hashtable/hashtable.c       | 277 ----------
 ubifs-utils/mkfs.ubifs/hashtable/hashtable.h       | 199 -------
 ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.c   | 176 ------
 ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.h   | 112 ----
 .../mkfs.ubifs/hashtable/hashtable_private.h       |  85 ---
 ubifs-utils/mkfs.ubifs/io.c                        |  33 --
 ubifs-utils/mkfs.ubifs/io.h                        |  15 -
 ubifs-utils/mkfs.ubifs/key.h                       | 207 --------
 ubifs-utils/mkfs.ubifs/lpt.c                       | 587 ---------------------
 ubifs-utils/mkfs.ubifs/lpt.h                       |  28 -
 ubifs-utils/mkfs.ubifs/ubifs.h                     | 450 ----------------
 ubifs-utils/mkfs.ubifs/ubifs_common.h              |  50 --
 43 files changed, 3600 insertions(+), 3599 deletions(-)
 create mode 100644 ubifs-utils/COPYING
 create mode 100644 ubifs-utils/README
 create mode 100644 ubifs-utils/include/compr.h
 create mode 100644 ubifs-utils/include/crc16.h
 create mode 100644 ubifs-utils/include/defs.h
 create mode 100644 ubifs-utils/include/devtable.h
 create mode 100644 ubifs-utils/include/hashtable.h
 create mode 100644 ubifs-utils/include/hashtable_itr.h
 create mode 100644 ubifs-utils/include/hashtable_private.h
 create mode 100644 ubifs-utils/include/io.h
 create mode 100644 ubifs-utils/include/key.h
 create mode 100644 ubifs-utils/include/lpt.h
 create mode 100644 ubifs-utils/include/ubifs.h
 create mode 100644 ubifs-utils/include/ubifs_common.h
 create mode 100644 ubifs-utils/lib/compr.c
 create mode 100644 ubifs-utils/lib/crc16.c
 create mode 100644 ubifs-utils/lib/devtable.c
 create mode 100644 ubifs-utils/lib/hashtable.c
 create mode 100644 ubifs-utils/lib/hashtable_itr.c
 create mode 100644 ubifs-utils/lib/io.c
 create mode 100644 ubifs-utils/lib/lpt.c
 delete mode 100644 ubifs-utils/mkfs.ubifs/COPYING
 delete mode 100644 ubifs-utils/mkfs.ubifs/README
 delete mode 100644 ubifs-utils/mkfs.ubifs/compr.c
 delete mode 100644 ubifs-utils/mkfs.ubifs/compr.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/crc16.c
 delete mode 100644 ubifs-utils/mkfs.ubifs/crc16.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/defs.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/devtable.c
 delete mode 100644 ubifs-utils/mkfs.ubifs/devtable.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/hashtable/hashtable.c
 delete mode 100644 ubifs-utils/mkfs.ubifs/hashtable/hashtable.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.c
 delete mode 100644 ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/hashtable/hashtable_private.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/io.c
 delete mode 100644 ubifs-utils/mkfs.ubifs/io.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/key.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/lpt.c
 delete mode 100644 ubifs-utils/mkfs.ubifs/lpt.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/ubifs.h
 delete mode 100644 ubifs-utils/mkfs.ubifs/ubifs_common.h

diff --git a/Makefile b/Makefile
index 8864675..ad0526f 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@
 
 VERSION = 1.5.2
 
-CPPFLAGS += -D_GNU_SOURCE -I./include -I$(BUILDDIR)/include -I./ubi-utils/include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS) $(UUIDCPPFLAGS)
+CPPFLAGS += -D_GNU_SOURCE -I./include -I$(BUILDDIR)/include -I./ubi-utils/include -I./ubifs-utils/include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS) $(UUIDCPPFLAGS)
 
 ifeq ($(WITHOUT_XATTR), 1)
   CPPFLAGS += -DWITHOUT_XATTR
@@ -126,8 +126,9 @@ $(foreach v,$(UBI_BINS),$(eval $(call mkdep,ubi-utils/,$(v),libubi.a ubiutils-co
 #
 # Utils in ubifs-utils subdir
 #
-obj-mkfs.ubifs = crc16.o lpt.o compr.o devtable.o io.o\
-	hashtable/hashtable.o hashtable/hashtable_itr.o
+$(foreach v,crc16.o lpt.o compr.o devtable.o io.o hashtable.o hashtable_itr.o,$(eval UBIFS_LIBS += ../lib/$(v)))
+
+obj-mkfs.ubifs = $(UBIFS_LIBS)
 LDFLAGS_mkfs.ubifs = $(ZLIBLDFLAGS) $(LZOLDFLAGS) $(UUIDLDFLAGS)
 LDLIBS_mkfs.ubifs = -lz $(LZOLDLIBS) -lm -luuid
 $(call mkdep,ubifs-utils/mkfs.ubifs/,mkfs.ubifs,,ubi-utils/libubi.a)
diff --git a/ubifs-utils/COPYING b/ubifs-utils/COPYING
new file mode 100644
index 0000000..60549be
--- /dev/null
+++ b/ubifs-utils/COPYING
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f

+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f

+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f

+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f

+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+\f

+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ubifs-utils/README b/ubifs-utils/README
new file mode 100644
index 0000000..7e19939
--- /dev/null
+++ b/ubifs-utils/README
@@ -0,0 +1,9 @@
+UBIFS File System - Make File System program
+
+* crc16.h and crc16.c were copied from the linux kernel.
+* crc32.h and crc32.c were copied from mtd-utils and amended.
+* ubifs.h is a selection of definitions from fs/ubifs/ubifs.h from the linux kernel.
+* key.h is copied from fs/ubifs/key.h from the linux kernel.
+* defs.h is a bunch of definitions to smooth things over.
+* lpt.c is a selection of functions copied from fs/ubifs/lpt.c from the linux kernel, and amended.
+* hashtable/* was downloaded from http://www.cl.cam.ac.uk/~cwc22/hashtable/
diff --git a/ubifs-utils/include/compr.h b/ubifs-utils/include/compr.h
new file mode 100644
index 0000000..d44a2ba
--- /dev/null
+++ b/ubifs-utils/include/compr.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation.
+ * Copyright (C) 2008 University of Szeged, Hungary
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Artem Bityutskiy
+ *          Adrian Hunter
+ *          Zoltan Sogor
+ */
+
+#ifndef __UBIFS_COMPRESS_H__
+#define __UBIFS_COMPRESS_H__
+
+/*
+ * Compressors may end-up with more data in the output buffer than in the input
+ * buffer. This constant defined the worst case factor, i.e. we assume that the
+ * output buffer may be at max. WORST_COMPR_FACTOR times larger than input
+ * buffer.
+ */
+#define WORST_COMPR_FACTOR 4
+
+enum compression_type
+{
+	MKFS_UBIFS_COMPR_NONE,
+	MKFS_UBIFS_COMPR_LZO,
+	MKFS_UBIFS_COMPR_ZLIB,
+};
+
+int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len, int type, int lzo_percent);
+int init_compression(void);
+void destroy_compression(void);
+
+#endif
diff --git a/ubifs-utils/include/crc16.h b/ubifs-utils/include/crc16.h
new file mode 100644
index 0000000..539d21a
--- /dev/null
+++ b/ubifs-utils/include/crc16.h
@@ -0,0 +1,27 @@
+/*
+ * Implements the standard CRC-16:
+ *   Width 16
+ *   Poly  0x8005 (x^16 + x^15 + x^2 + 1)
+ *   Init  0
+ *
+ * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
+ *
+ * This code was taken from the linux kernel. The license is GPL Version 2.
+ */
+
+#ifndef __CRC16_H__
+#define __CRC16_H__
+
+#include <stdlib.h>
+#include <stdint.h>
+
+extern uint16_t const crc16_table[256];
+
+extern uint16_t crc16(uint16_t crc, const uint8_t *buffer, size_t len);
+
+static inline uint16_t crc16_byte(uint16_t crc, const uint8_t data)
+{
+	return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff];
+}
+
+#endif /* __CRC16_H__ */
diff --git a/ubifs-utils/include/defs.h b/ubifs-utils/include/defs.h
new file mode 100644
index 0000000..1fa3316
--- /dev/null
+++ b/ubifs-utils/include/defs.h
@@ -0,0 +1,92 @@
+/*
+ * Greate deal of the code was taken from the kernel UBIFS implementation, and
+ * this file contains some "glue" definitions.
+ */
+
+#ifndef __UBIFS_DEFS_H__
+#define __UBIFS_DEFS_H__
+
+#define t16(x) ({ \
+	uint16_t __b = (x); \
+	(__LITTLE_ENDIAN==__BYTE_ORDER) ? __b : bswap_16(__b); \
+})
+
+#define t32(x) ({ \
+	uint32_t __b = (x); \
+	(__LITTLE_ENDIAN==__BYTE_ORDER) ? __b : bswap_32(__b); \
+})
+
+#define t64(x) ({ \
+	uint64_t __b = (x); \
+	(__LITTLE_ENDIAN==__BYTE_ORDER) ? __b : bswap_64(__b); \
+})
+
+#define cpu_to_le16(x) ((__le16){t16(x)})
+#define cpu_to_le32(x) ((__le32){t32(x)})
+#define cpu_to_le64(x) ((__le64){t64(x)})
+
+#define le16_to_cpu(x) (t16((x)))
+#define le32_to_cpu(x) (t32((x)))
+#define le64_to_cpu(x) (t64((x)))
+
+#define unlikely(x) (x)
+
+#define ubifs_assert(x) ({})
+
+struct qstr
+{
+	char *name;
+	size_t len;
+};
+
+/**
+ * fls - find last (most-significant) bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as ffs.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
+ */
+static inline int fls(int x)
+{
+	int r = 32;
+
+	if (!x)
+		return 0;
+	if (!(x & 0xffff0000u)) {
+		x <<= 16;
+		r -= 16;
+	}
+	if (!(x & 0xff000000u)) {
+		x <<= 8;
+		r -= 8;
+	}
+	if (!(x & 0xf0000000u)) {
+		x <<= 4;
+		r -= 4;
+	}
+	if (!(x & 0xc0000000u)) {
+		x <<= 2;
+		r -= 2;
+	}
+	if (!(x & 0x80000000u)) {
+		x <<= 1;
+		r -= 1;
+	}
+	return r;
+}
+
+#define do_div(n,base) ({ \
+int __res; \
+__res = ((unsigned long) n) % (unsigned) base; \
+n = ((unsigned long) n) / (unsigned) base; \
+__res; })
+
+#if INT_MAX != 0x7fffffff
+#error : sizeof(int) must be 4 for this program
+#endif
+
+#if (~0ULL) != 0xffffffffffffffffULL
+#error : sizeof(long long) must be 8 for this program
+#endif
+
+#endif
diff --git a/ubifs-utils/include/devtable.h b/ubifs-utils/include/devtable.h
new file mode 100644
index 0000000..987d4d4
--- /dev/null
+++ b/ubifs-utils/include/devtable.h
@@ -0,0 +1,55 @@
+#include "ubifs_common.h"
+
+/**
+ * struct path_htbl_element - an element of the path hash table.
+ * @path: the UBIFS path the element describes (the key of the element)
+ * @name_htbl: one more (nested) hash table containing names of all
+ *             files/directories/device nodes which should be created at this
+ *             path
+ *
+ * See device table handling for more information.
+ */
+struct path_htbl_element {
+	const char *path;
+	struct hashtable *name_htbl;
+};
+
+/**
+ * struct name_htbl_element - an element in the name hash table
+ * @name: name of the file/directory/device node (the key of the element)
+ * @mode: accsess rights and file type
+ * @uid: user ID
+ * @gid: group ID
+ * @major: device node major number
+ * @minor: device node minor number
+ *
+ * This is an element of the name hash table. Name hash table sits in the path
+ * hash table elements and describes file names which should be created/changed
+ * at this path.
+ */
+struct name_htbl_element {
+	const char *name;
+	unsigned int mode;
+	unsigned int uid;
+	unsigned int gid;
+	dev_t dev;
+};
+
+extern struct ubifs_info info_;
+
+struct hashtable_itr;
+
+int parse_devtable(const char *tbl_file);
+struct path_htbl_element *devtbl_find_path(const char *path);
+struct name_htbl_element *devtbl_find_name(struct path_htbl_element *ph_elt,
+					   const char *name);
+int override_attributes(struct stat *st, struct path_htbl_element *ph_elt,
+			struct name_htbl_element *nh_elt);
+struct name_htbl_element *
+first_name_htbl_element(struct path_htbl_element *ph_elt,
+			struct hashtable_itr **itr);
+struct name_htbl_element *
+next_name_htbl_element(struct path_htbl_element *ph_elt,
+			struct hashtable_itr **itr);
+void free_devtable_info(void);
+
diff --git a/ubifs-utils/include/hashtable.h b/ubifs-utils/include/hashtable.h
new file mode 100644
index 0000000..c0b0acd
--- /dev/null
+++ b/ubifs-utils/include/hashtable.h
@@ -0,0 +1,199 @@
+/* Copyright (C) 2002 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
+
+#ifndef __HASHTABLE_CWC22_H__
+#define __HASHTABLE_CWC22_H__
+
+struct hashtable;
+
+/* Example of use:
+ *
+ *      struct hashtable  *h;
+ *      struct some_key   *k;
+ *      struct some_value *v;
+ *
+ *      static unsigned int         hash_from_key_fn( void *k );
+ *      static int                  keys_equal_fn ( void *key1, void *key2 );
+ *
+ *      h = create_hashtable(16, hash_from_key_fn, keys_equal_fn);
+ *      k = (struct some_key *)     malloc(sizeof(struct some_key));
+ *      v = (struct some_value *)   malloc(sizeof(struct some_value));
+ *
+ *      (initialise k and v to suitable values)
+ *
+ *      if (! hashtable_insert(h,k,v) )
+ *      {     exit(-1);               }
+ *
+ *      if (NULL == (found = hashtable_search(h,k) ))
+ *      {    printf("not found!");                  }
+ *
+ *      if (NULL == (found = hashtable_remove(h,k) ))
+ *      {    printf("Not found\n");                 }
+ *
+ */
+
+/* Macros may be used to define type-safe(r) hashtable access functions, with
+ * methods specialized to take known key and value types as parameters.
+ *
+ * Example:
+ *
+ * Insert this at the start of your file:
+ *
+ * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value);
+ * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value);
+ * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value);
+ *
+ * This defines the functions 'insert_some', 'search_some' and 'remove_some'.
+ * These operate just like hashtable_insert etc., with the same parameters,
+ * but their function signatures have 'struct some_key *' rather than
+ * 'void *', and hence can generate compile time errors if your program is
+ * supplying incorrect data as a key (and similarly for value).
+ *
+ * Note that the hash and key equality functions passed to create_hashtable
+ * still take 'void *' parameters instead of 'some key *'. This shouldn't be
+ * a difficult issue as they're only defined and passed once, and the other
+ * functions will ensure that only valid keys are supplied to them.
+ *
+ * The cost for this checking is increased code size and runtime overhead
+ * - if performance is important, it may be worth switching back to the
+ * unsafe methods once your program has been debugged with the safe methods.
+ * This just requires switching to some simple alternative defines - eg:
+ * #define insert_some hashtable_insert
+ *
+ */
+
+/*****************************************************************************
+ * create_hashtable
+
+ * @name                    create_hashtable
+ * @param   minsize         minimum initial size of hashtable
+ * @param   hashfunction    function for hashing keys
+ * @param   key_eq_fn       function for determining key equality
+ * @return                  newly created hashtable or NULL on failure
+ */
+
+struct hashtable *
+create_hashtable(unsigned int minsize,
+                 unsigned int (*hashfunction) (void*),
+                 int (*key_eq_fn) (void*,void*));
+
+/*****************************************************************************
+ * hashtable_insert
+
+ * @name        hashtable_insert
+ * @param   h   the hashtable to insert into
+ * @param   k   the key - hashtable claims ownership and will free on removal
+ * @param   v   the value - does not claim ownership
+ * @return      non-zero for successful insertion
+ *
+ * This function will cause the table to expand if the insertion would take
+ * the ratio of entries to table size over the maximum load factor.
+ *
+ * This function does not check for repeated insertions with a duplicate key.
+ * The value returned when using a duplicate key is undefined -- when
+ * the hashtable changes size, the order of retrieval of duplicate key
+ * entries is reversed.
+ * If in doubt, remove before insert.
+ */
+
+int
+hashtable_insert(struct hashtable *h, void *k, void *v);
+
+#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \
+int fnname (struct hashtable *h, keytype *k, valuetype *v) \
+{ \
+    return hashtable_insert(h,k,v); \
+}
+
+/*****************************************************************************
+ * hashtable_search
+
+ * @name        hashtable_search
+ * @param   h   the hashtable to search
+ * @param   k   the key to search for  - does not claim ownership
+ * @return      the value associated with the key, or NULL if none found
+ */
+
+void *
+hashtable_search(struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \
+valuetype * fnname (struct hashtable *h, keytype *k) \
+{ \
+    return (valuetype *) (hashtable_search(h,k)); \
+}
+
+/*****************************************************************************
+ * hashtable_remove
+
+ * @name        hashtable_remove
+ * @param   h   the hashtable to remove the item from
+ * @param   k   the key to search for  - does not claim ownership
+ * @return      the value associated with the key, or NULL if none found
+ */
+
+void * /* returns value */
+hashtable_remove(struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \
+valuetype * fnname (struct hashtable *h, keytype *k) \
+{ \
+    return (valuetype *) (hashtable_remove(h,k)); \
+}
+
+
+/*****************************************************************************
+ * hashtable_count
+
+ * @name        hashtable_count
+ * @param   h   the hashtable
+ * @return      the number of items stored in the hashtable
+ */
+unsigned int
+hashtable_count(struct hashtable *h);
+
+
+/*****************************************************************************
+ * hashtable_destroy
+
+ * @name        hashtable_destroy
+ * @param   h   the hashtable
+ * @param       free_values     whether to call 'free' on the remaining values
+ */
+
+void
+hashtable_destroy(struct hashtable *h, int free_values);
+
+#endif /* __HASHTABLE_CWC22_H__ */
+
+/*
+ * Copyright (c) 2002, Christopher Clark
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
diff --git a/ubifs-utils/include/hashtable_itr.h b/ubifs-utils/include/hashtable_itr.h
new file mode 100644
index 0000000..5c94a04
--- /dev/null
+++ b/ubifs-utils/include/hashtable_itr.h
@@ -0,0 +1,112 @@
+/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
+
+#ifndef __HASHTABLE_ITR_CWC22__
+#define __HASHTABLE_ITR_CWC22__
+#include "hashtable.h"
+#include "hashtable_private.h" /* needed to enable inlining */
+
+/*****************************************************************************/
+/* This struct is only concrete here to allow the inlining of two of the
+ * accessor functions. */
+struct hashtable_itr
+{
+    struct hashtable *h;
+    struct entry *e;
+    struct entry *parent;
+    unsigned int index;
+};
+
+
+/*****************************************************************************/
+/* hashtable_iterator
+ */
+
+struct hashtable_itr *
+hashtable_iterator(struct hashtable *h);
+
+/*****************************************************************************/
+/* hashtable_iterator_key
+ * - return the value of the (key,value) pair at the current position */
+
+static inline void *
+hashtable_iterator_key(struct hashtable_itr *i)
+{
+    return i->e->k;
+}
+
+/*****************************************************************************/
+/* value - return the value of the (key,value) pair at the current position */
+
+static inline void *
+hashtable_iterator_value(struct hashtable_itr *i)
+{
+    return i->e->v;
+}
+
+/*****************************************************************************/
+/* advance - advance the iterator to the next element
+ *           returns zero if advanced to end of table */
+
+int
+hashtable_iterator_advance(struct hashtable_itr *itr);
+
+/*****************************************************************************/
+/* remove - remove current element and advance the iterator to the next element
+ *          NB: if you need the value to free it, read it before
+ *          removing. ie: beware memory leaks!
+ *          returns zero if advanced to end of table */
+
+int
+hashtable_iterator_remove(struct hashtable_itr *itr);
+
+/*****************************************************************************/
+/* search - overwrite the supplied iterator, to point to the entry
+ *          matching the supplied key.
+            h points to the hashtable to be searched.
+ *          returns zero if not found. */
+int
+hashtable_iterator_search(struct hashtable_itr *itr,
+                          struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \
+int fnname (struct hashtable_itr *i, struct hashtable *h, keytype *k) \
+{ \
+    return (hashtable_iterator_search(i,h,k)); \
+}
+
+
+
+#endif /* __HASHTABLE_ITR_CWC22__*/
+
+/*
+ * Copyright (c) 2002, 2004, Christopher Clark
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
diff --git a/ubifs-utils/include/hashtable_private.h b/ubifs-utils/include/hashtable_private.h
new file mode 100644
index 0000000..3a558e6
--- /dev/null
+++ b/ubifs-utils/include/hashtable_private.h
@@ -0,0 +1,85 @@
+/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
+
+#ifndef __HASHTABLE_PRIVATE_CWC22_H__
+#define __HASHTABLE_PRIVATE_CWC22_H__
+
+#include "hashtable.h"
+
+/*****************************************************************************/
+struct entry
+{
+    void *k, *v;
+    unsigned int h;
+    struct entry *next;
+};
+
+struct hashtable {
+    unsigned int tablelength;
+    struct entry **table;
+    unsigned int entrycount;
+    unsigned int loadlimit;
+    unsigned int primeindex;
+    unsigned int (*hashfn) (void *k);
+    int (*eqfn) (void *k1, void *k2);
+};
+
+/*****************************************************************************/
+unsigned int
+hash(struct hashtable *h, void *k);
+
+/*****************************************************************************/
+/* indexFor */
+static inline unsigned int
+indexFor(unsigned int tablelength, unsigned int hashvalue) {
+    return (hashvalue % tablelength);
+};
+
+/* Only works if tablelength == 2^N */
+/*static inline unsigned int
+indexFor(unsigned int tablelength, unsigned int hashvalue)
+{
+    return (hashvalue & (tablelength - 1u));
+}
+*/
+
+/*****************************************************************************/
+#define freekey(X) free(X)
+/*define freekey(X) ; */
+
+
+/*****************************************************************************/
+
+#endif /* __HASHTABLE_PRIVATE_CWC22_H__*/
+
+/*
+ * Copyright (c) 2002, Christopher Clark
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
diff --git a/ubifs-utils/include/io.h b/ubifs-utils/include/io.h
new file mode 100644
index 0000000..e24d0c6
--- /dev/null
+++ b/ubifs-utils/include/io.h
@@ -0,0 +1,15 @@
+/**
+ * Header file for the io to ubi volume
+ */
+#ifndef __UBIFS_IO_H__
+#define __UBIFS_IO_H__
+
+#include "ubifs_common.h"
+#include "ubifs.h"
+
+extern int out_fd;
+extern int out_ubi;
+extern libubi_t ubi;
+
+int write_leb(struct ubifs_info *c, int lnum, int len, void *buf);
+#endif
diff --git a/ubifs-utils/include/key.h b/ubifs-utils/include/key.h
new file mode 100644
index 0000000..39379fd
--- /dev/null
+++ b/ubifs-utils/include/key.h
@@ -0,0 +1,207 @@
+/*
+ * This file is part of UBIFS.
+ *
+ * Copyright (C) 2006-2008 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Artem Bityutskiy (Битюцкий Артём)
+ *          Adrian Hunter
+ */
+
+/*
+ * This header contains various key-related definitions and helper function.
+ * UBIFS allows several key schemes, so we access key fields only via these
+ * helpers. At the moment only one key scheme is supported.
+ *
+ * Simple key scheme
+ * ~~~~~~~~~~~~~~~~~
+ *
+ * Keys are 64-bits long. First 32-bits are inode number (parent inode number
+ * in case of direntry key). Next 3 bits are node type. The last 29 bits are
+ * 4KiB offset in case of inode node, and direntry hash in case of a direntry
+ * node. We use "r5" hash borrowed from reiserfs.
+ */
+
+#ifndef __UBIFS_KEY_H__
+#define __UBIFS_KEY_H__
+
+/**
+ * key_mask_hash - mask a valid hash value.
+ * @val: value to be masked
+ *
+ * We use hash values as offset in directories, so values %0 and %1 are
+ * reserved for "." and "..". %2 is reserved for "end of readdir" marker. This
+ * function makes sure the reserved values are not used.
+ */
+static inline uint32_t key_mask_hash(uint32_t hash)
+{
+	hash &= UBIFS_S_KEY_HASH_MASK;
+	if (unlikely(hash <= 2))
+		hash += 3;
+	return hash;
+}
+
+/**
+ * key_r5_hash - R5 hash function (borrowed from reiserfs).
+ * @s: direntry name
+ * @len: name length
+ */
+static inline uint32_t key_r5_hash(const char *s, int len)
+{
+	uint32_t a = 0;
+	const signed char *str = (const signed char *)s;
+
+	len = len;
+	while (*str) {
+		a += *str << 4;
+		a += *str >> 4;
+		a *= 11;
+		str++;
+	}
+
+	return key_mask_hash(a);
+}
+
+/**
+ * key_test_hash - testing hash function.
+ * @str: direntry name
+ * @len: name length
+ */
+static inline uint32_t key_test_hash(const char *str, int len)
+{
+	uint32_t a = 0;
+
+	len = min_t(uint32_t, len, 4);
+	memcpy(&a, str, len);
+	return key_mask_hash(a);
+}
+
+/**
+ * ino_key_init - initialize inode key.
+ * @c: UBIFS file-system description object
+ * @key: key to initialize
+ * @inum: inode number
+ */
+static inline void ino_key_init(union ubifs_key *key, ino_t inum)
+{
+	key->u32[0] = inum;
+	key->u32[1] = UBIFS_INO_KEY << UBIFS_S_KEY_BLOCK_BITS;
+}
+
+/**
+ * dent_key_init - initialize directory entry key.
+ * @c: UBIFS file-system description object
+ * @key: key to initialize
+ * @inum: parent inode number
+ * @nm: direntry name and length
+ */
+static inline void dent_key_init(const struct ubifs_info *c,
+				 union ubifs_key *key, ino_t inum,
+				 const struct qstr *nm)
+{
+	uint32_t hash = c->key_hash(nm->name, nm->len);
+
+	ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
+	key->u32[0] = inum;
+	key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS);
+}
+
+/**
+ * xent_key_init - initialize extended attribute entry key.
+ * @c: UBIFS file-system description object
+ * @key: key to initialize
+ * @inum: host inode number
+ * @nm: extended attribute entry name and length
+ */
+static inline void xent_key_init(const struct ubifs_info *c,
+				 union ubifs_key *key, ino_t inum,
+				 const struct qstr *nm)
+{
+	uint32_t hash = c->key_hash(nm->name, nm->len);
+
+	ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
+	key->u32[0] = inum;
+	key->u32[1] = hash | (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS);
+}
+
+/**
+ * data_key_init - initialize data key.
+ * @c: UBIFS file-system description object
+ * @key: key to initialize
+ * @inum: inode number
+ * @block: block number
+ */
+static inline void data_key_init(union ubifs_key *key, ino_t inum,
+				 unsigned int block)
+{
+	ubifs_assert(!(block & ~UBIFS_S_KEY_BLOCK_MASK));
+	key->u32[0] = inum;
+	key->u32[1] = block | (UBIFS_DATA_KEY << UBIFS_S_KEY_BLOCK_BITS);
+}
+
+/**
+ * key_write - transform a key from in-memory format.
+ * @c: UBIFS file-system description object
+ * @from: the key to transform
+ * @to: the key to store the result
+ */
+static inline void key_write(const union ubifs_key *from, void *to)
+{
+	union ubifs_key *t = to;
+
+	t->j32[0] = cpu_to_le32(from->u32[0]);
+	t->j32[1] = cpu_to_le32(from->u32[1]);
+	memset(to + 8, 0, UBIFS_MAX_KEY_LEN - 8);
+}
+
+/**
+ * key_write_idx - transform a key from in-memory format for the index.
+ * @c: UBIFS file-system description object
+ * @from: the key to transform
+ * @to: the key to store the result
+ */
+static inline void key_write_idx(const union ubifs_key *from, void *to)
+{
+	union ubifs_key *t = to;
+
+	t->j32[0] = cpu_to_le32(from->u32[0]);
+	t->j32[1] = cpu_to_le32(from->u32[1]);
+}
+
+/**
+ * keys_cmp - compare keys.
+ * @c: UBIFS file-system description object
+ * @key1: the first key to compare
+ * @key2: the second key to compare
+ *
+ * This function compares 2 keys and returns %-1 if @key1 is less than
+ * @key2, 0 if the keys are equivalent and %1 if @key1 is greater than @key2.
+ */
+static inline int keys_cmp(const union ubifs_key *key1,
+			   const union ubifs_key *key2)
+{
+	if (key1->u32[0] < key2->u32[0])
+		return -1;
+	if (key1->u32[0] > key2->u32[0])
+		return 1;
+	if (key1->u32[1] < key2->u32[1])
+		return -1;
+	if (key1->u32[1] > key2->u32[1])
+		return 1;
+
+	return 0;
+}
+
+#endif /* !__UBIFS_KEY_H__ */
diff --git a/ubifs-utils/include/lpt.h b/ubifs-utils/include/lpt.h
new file mode 100644
index 0000000..4cde59d
--- /dev/null
+++ b/ubifs-utils/include/lpt.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation.
+ * Copyright (C) 2008 University of Szeged, Hungary
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Artem Bityutskiy
+ *          Adrian Hunter
+ */
+
+#ifndef __UBIFS_LPT_H__
+#define __UBIFS_LPT_H__
+
+int calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs, int *big_lpt);
+int create_lpt(struct ubifs_info *c);
+
+#endif
diff --git a/ubifs-utils/include/ubifs.h b/ubifs-utils/include/ubifs.h
new file mode 100644
index 0000000..2f080a8
--- /dev/null
+++ b/ubifs-utils/include/ubifs.h
@@ -0,0 +1,450 @@
+/*
+ * This file is part of UBIFS.
+ *
+ * Copyright (C) 2008 Nokia Corporation.
+ * Copyright (C) 2008 University of Szeged, Hungary
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Artem Bityutskiy
+ *          Adrian Hunter
+ *          Zoltan Sogor
+ */
+
+#ifndef __UBIFS_H__
+#define __UBIFS_H__
+
+/* Maximum logical eraseblock size in bytes */
+#define UBIFS_MAX_LEB_SZ (2*1024*1024)
+
+/* Minimum amount of data UBIFS writes to the flash */
+#define MIN_WRITE_SZ (UBIFS_DATA_NODE_SZ + 8)
+
+/* Largest key size supported in this implementation */
+#define CUR_MAX_KEY_LEN UBIFS_SK_LEN
+
+/*
+ * There is no notion of truncation key because truncation nodes do not exist
+ * in TNC. However, when replaying, it is handy to introduce fake "truncation"
+ * keys for truncation nodes because the code becomes simpler. So we define
+ * %UBIFS_TRUN_KEY type.
+ */
+#define UBIFS_TRUN_KEY UBIFS_KEY_TYPES_CNT
+
+/*
+ * How much a directory entry/extended attribute entry adds to the parent/host
+ * inode.
+ */
+#define CALC_DENT_SIZE(name_len) ALIGN(UBIFS_DENT_NODE_SZ + (name_len) + 1, 8)
+
+/* How much an extended attribute adds to the host inode */
+#define CALC_XATTR_BYTES(data_len) ALIGN(UBIFS_INO_NODE_SZ + (data_len) + 1, 8)
+
+/* The below union makes it easier to deal with keys */
+union ubifs_key
+{
+	uint8_t u8[CUR_MAX_KEY_LEN];
+	uint32_t u32[CUR_MAX_KEY_LEN/4];
+	uint64_t u64[CUR_MAX_KEY_LEN/8];
+	__le32 j32[CUR_MAX_KEY_LEN/4];
+};
+
+/*
+ * LEB properties flags.
+ *
+ * LPROPS_UNCAT: not categorized
+ * LPROPS_DIRTY: dirty > 0, not index
+ * LPROPS_DIRTY_IDX: dirty + free > UBIFS_CH_SZ and index
+ * LPROPS_FREE: free > 0, not empty, not index
+ * LPROPS_HEAP_CNT: number of heaps used for storing categorized LEBs
+ * LPROPS_EMPTY: LEB is empty, not taken
+ * LPROPS_FREEABLE: free + dirty == leb_size, not index, not taken
+ * LPROPS_FRDI_IDX: free + dirty == leb_size and index, may be taken
+ * LPROPS_CAT_MASK: mask for the LEB categories above
+ * LPROPS_TAKEN: LEB was taken (this flag is not saved on the media)
+ * LPROPS_INDEX: LEB contains indexing nodes (this flag also exists on flash)
+ */
+enum {
+	LPROPS_UNCAT     =  0,
+	LPROPS_DIRTY     =  1,
+	LPROPS_DIRTY_IDX =  2,
+	LPROPS_FREE      =  3,
+	LPROPS_HEAP_CNT  =  3,
+	LPROPS_EMPTY     =  4,
+	LPROPS_FREEABLE  =  5,
+	LPROPS_FRDI_IDX  =  6,
+	LPROPS_CAT_MASK  = 15,
+	LPROPS_TAKEN     = 16,
+	LPROPS_INDEX     = 32,
+};
+
+/**
+ * struct ubifs_lprops - logical eraseblock properties.
+ * @free: amount of free space in bytes
+ * @dirty: amount of dirty space in bytes
+ * @flags: LEB properties flags (see above)
+ */
+struct ubifs_lprops
+{
+	int free;
+	int dirty;
+	int flags;
+};
+
+/**
+ * struct ubifs_lpt_lprops - LPT logical eraseblock properties.
+ * @free: amount of free space in bytes
+ * @dirty: amount of dirty space in bytes
+ */
+struct ubifs_lpt_lprops
+{
+	int free;
+	int dirty;
+};
+
+struct ubifs_nnode;
+
+/**
+ * struct ubifs_cnode - LEB Properties Tree common node.
+ * @parent: parent nnode
+ * @cnext: next cnode to commit
+ * @flags: flags (%DIRTY_LPT_NODE or %OBSOLETE_LPT_NODE)
+ * @iip: index in parent
+ * @level: level in the tree (zero for pnodes, greater than zero for nnodes)
+ * @num: node number
+ */
+struct ubifs_cnode
+{
+	struct ubifs_nnode *parent;
+	struct ubifs_cnode *cnext;
+	unsigned long flags;
+	int iip;
+	int level;
+	int num;
+};
+
+/**
+ * struct ubifs_pnode - LEB Properties Tree leaf node.
+ * @parent: parent nnode
+ * @cnext: next cnode to commit
+ * @flags: flags (%DIRTY_LPT_NODE or %OBSOLETE_LPT_NODE)
+ * @iip: index in parent
+ * @level: level in the tree (always zero for pnodes)
+ * @num: node number
+ * @lprops: LEB properties array
+ */
+struct ubifs_pnode
+{
+	struct ubifs_nnode *parent;
+	struct ubifs_cnode *cnext;
+	unsigned long flags;
+	int iip;
+	int level;
+	int num;
+	struct ubifs_lprops lprops[UBIFS_LPT_FANOUT];
+};
+
+/**
+ * struct ubifs_nbranch - LEB Properties Tree internal node branch.
+ * @lnum: LEB number of child
+ * @offs: offset of child
+ * @nnode: nnode child
+ * @pnode: pnode child
+ * @cnode: cnode child
+ */
+struct ubifs_nbranch
+{
+	int lnum;
+	int offs;
+	union
+	{
+		struct ubifs_nnode *nnode;
+		struct ubifs_pnode *pnode;
+		struct ubifs_cnode *cnode;
+	};
+};
+
+/**
+ * struct ubifs_nnode - LEB Properties Tree internal node.
+ * @parent: parent nnode
+ * @cnext: next cnode to commit
+ * @flags: flags (%DIRTY_LPT_NODE or %OBSOLETE_LPT_NODE)
+ * @iip: index in parent
+ * @level: level in the tree (always greater than zero for nnodes)
+ * @num: node number
+ * @nbranch: branches to child nodes
+ */
+struct ubifs_nnode
+{
+	struct ubifs_nnode *parent;
+	struct ubifs_cnode *cnext;
+	unsigned long flags;
+	int iip;
+	int level;
+	int num;
+	struct ubifs_nbranch nbranch[UBIFS_LPT_FANOUT];
+};
+
+/**
+ * struct ubifs_lp_stats - statistics of eraseblocks in the main area.
+ * @empty_lebs: number of empty LEBs
+ * @taken_empty_lebs: number of taken LEBs
+ * @idx_lebs: number of indexing LEBs
+ * @total_free: total free space in bytes
+ * @total_dirty: total dirty space in bytes
+ * @total_used: total used space in bytes (includes only data LEBs)
+ * @total_dead: total dead space in bytes (includes only data LEBs)
+ * @total_dark: total dark space in bytes (includes only data LEBs)
+ */
+struct ubifs_lp_stats {
+	int empty_lebs;
+	int taken_empty_lebs;
+	int idx_lebs;
+	long long total_free;
+	long long total_dirty;
+	long long total_used;
+	long long total_dead;
+	long long total_dark;
+};
+
+/**
+ * struct ubifs_zbranch - key/coordinate/length branch stored in znodes.
+ * @key: key
+ * @znode: znode address in memory
+ * @lnum: LEB number of the indexing node
+ * @offs: offset of the indexing node within @lnum
+ * @len: target node length
+ */
+struct ubifs_zbranch
+{
+	union ubifs_key key;
+	struct ubifs_znode *znode;
+	int lnum;
+	int offs;
+	int len;
+};
+
+/**
+ * struct ubifs_znode - in-memory representation of an indexing node.
+ * @parent: parent znode or NULL if it is the root
+ * @cnext: next znode to commit
+ * @flags: flags
+ * @time: last access time (seconds)
+ * @level: level of the entry in the TNC tree
+ * @child_cnt: count of child znodes
+ * @iip: index in parent's zbranch array
+ * @alt: lower bound of key range has altered i.e. child inserted at slot 0
+ * @zbranch: array of znode branches (@c->fanout elements)
+ */
+struct ubifs_znode
+{
+	struct ubifs_znode *parent;
+	struct ubifs_znode *cnext;
+	unsigned long flags;
+	unsigned long time;
+	int level;
+	int child_cnt;
+	int iip;
+	int alt;
+#ifdef CONFIG_UBIFS_FS_DEBUG
+	int lnum, offs, len;
+#endif
+	struct ubifs_zbranch zbranch[];
+};
+
+/**
+ * struct ubifs_info - UBIFS file-system description data structure
+ * (per-superblock).
+ *
+ * @highest_inum: highest used inode number
+ * @max_sqnum: current global sequence number
+ *
+ * @jhead_cnt: count of journal heads
+ * @max_bud_bytes: maximum number of bytes allowed in buds
+ *
+ * @zroot: zbranch which points to the root index node and znode
+ * @ihead_lnum: LEB number of index head
+ * @ihead_offs: offset of index head
+ *
+ * @log_lebs: number of logical eraseblocks in the log
+ * @lpt_lebs: number of LEBs used for lprops table
+ * @lpt_first: first LEB of the lprops table area
+ * @lpt_last: last LEB of the lprops table area
+ * @main_lebs: count of LEBs in the main area
+ * @main_first: first LEB of the main area
+ * @default_compr: default compression type
+ * @favor_lzo: favor LZO compression method
+ * @favor_percent: lzo vs. zlib threshold used in case favor LZO
+ *
+ * @key_hash_type: type of the key hash
+ * @key_hash: direntry key hash function
+ * @key_fmt: key format
+ * @key_len: key length
+ * @fanout: fanout of the index tree (number of links per indexing node)
+ *
+ * @min_io_size: minimal input/output unit size
+ * @leb_size: logical eraseblock size in bytes
+ * @leb_cnt: count of logical eraseblocks
+ * @max_leb_cnt: maximum count of logical eraseblocks
+ *
+ * @old_idx_sz: size of index on flash
+ * @lst: lprops statistics
+ *
+ * @dead_wm: LEB dead space watermark
+ * @dark_wm: LEB dark space watermark
+ *
+ * @di: UBI device information
+ * @vi: UBI volume information
+ *
+ * @gc_lnum: LEB number used for garbage collection
+ * @rp_size: reserved pool size
+ *
+ * @space_bits: number of bits needed to record free or dirty space
+ * @lpt_lnum_bits: number of bits needed to record a LEB number in the LPT
+ * @lpt_offs_bits: number of bits needed to record an offset in the LPT
+ * @lpt_spc_bits: number of bits needed to space in the LPT
+ * @pcnt_bits: number of bits needed to record pnode or nnode number
+ * @lnum_bits: number of bits needed to record LEB number
+ * @nnode_sz: size of on-flash nnode
+ * @pnode_sz: size of on-flash pnode
+ * @ltab_sz: size of on-flash LPT lprops table
+ * @lsave_sz: size of on-flash LPT save table
+ * @pnode_cnt: number of pnodes
+ * @nnode_cnt: number of nnodes
+ * @lpt_hght: height of the LPT
+ *
+ * @lpt_lnum: LEB number of the root nnode of the LPT
+ * @lpt_offs: offset of the root nnode of the LPT
+ * @nhead_lnum: LEB number of LPT head
+ * @nhead_offs: offset of LPT head
+ * @big_lpt: flag that LPT is too big to write whole during commit
+ * @space_fixup: flag indicating that free space in LEBs needs to be cleaned up
+ * @lpt_sz: LPT size
+ *
+ * @ltab_lnum: LEB number of LPT's own lprops table
+ * @ltab_offs: offset of LPT's own lprops table
+ * @lpt: lprops table
+ * @ltab: LPT's own lprops table
+ * @lsave_cnt: number of LEB numbers in LPT's save table
+ * @lsave_lnum: LEB number of LPT's save table
+ * @lsave_offs: offset of LPT's save table
+ * @lsave: LPT's save table
+ * @lscan_lnum: LEB number of last LPT scan
+ */
+struct ubifs_info
+{
+	ino_t highest_inum;
+	unsigned long long max_sqnum;
+
+	int jhead_cnt;
+	long long max_bud_bytes;
+
+	struct ubifs_zbranch zroot;
+	int ihead_lnum;
+	int ihead_offs;
+
+	int log_lebs;
+	int lpt_lebs;
+	int lpt_first;
+	int lpt_last;
+	int orph_lebs;
+	int main_lebs;
+	int main_first;
+	int default_compr;
+	int favor_lzo;
+	int favor_percent;
+
+	uint8_t key_hash_type;
+	uint32_t (*key_hash)(const char *str, int len);
+	int key_fmt;
+	int key_len;
+	int fanout;
+
+	int min_io_size;
+	int leb_size;
+	int leb_cnt;
+	int max_leb_cnt;
+
+	unsigned long long old_idx_sz;
+	struct ubifs_lp_stats lst;
+
+	int dead_wm;
+	int dark_wm;
+
+	struct ubi_dev_info di;
+	struct ubi_vol_info vi;
+
+	int gc_lnum;
+	long long rp_size;
+
+	int space_bits;
+	int lpt_lnum_bits;
+	int lpt_offs_bits;
+	int lpt_spc_bits;
+	int pcnt_bits;
+	int lnum_bits;
+	int nnode_sz;
+	int pnode_sz;
+	int ltab_sz;
+	int lsave_sz;
+	int pnode_cnt;
+	int nnode_cnt;
+	int lpt_hght;
+
+	int lpt_lnum;
+	int lpt_offs;
+	int nhead_lnum;
+	int nhead_offs;
+	int big_lpt;
+	int space_fixup;
+	long long lpt_sz;
+
+	int ltab_lnum;
+	int ltab_offs;
+	struct ubifs_lprops *lpt;
+	struct ubifs_lpt_lprops *ltab;
+	int lsave_cnt;
+	int lsave_lnum;
+	int lsave_offs;
+	int *lsave;
+	int lscan_lnum;
+
+};
+
+/**
+ * ubifs_idx_node_sz - return index node size.
+ * @c: the UBIFS file-system description object
+ * @child_cnt: number of children of this index node
+ */
+static inline int ubifs_idx_node_sz(const struct ubifs_info *c, int child_cnt)
+{
+	return UBIFS_IDX_NODE_SZ + (UBIFS_BRANCH_SZ + c->key_len) * child_cnt;
+}
+
+/**
+ * ubifs_idx_branch - return pointer to an index branch.
+ * @c: the UBIFS file-system description object
+ * @idx: index node
+ * @bnum: branch number
+ */
+static inline
+struct ubifs_branch *ubifs_idx_branch(const struct ubifs_info *c,
+				      const struct ubifs_idx_node *idx,
+				      int bnum)
+{
+	return (struct ubifs_branch *)((void *)idx->branches +
+				       (UBIFS_BRANCH_SZ + c->key_len) * bnum);
+}
+
+#endif /* __UBIFS_H__ */
diff --git a/ubifs-utils/include/ubifs_common.h b/ubifs-utils/include/ubifs_common.h
new file mode 100644
index 0000000..958c20a
--- /dev/null
+++ b/ubifs-utils/include/ubifs_common.h
@@ -0,0 +1,50 @@
+#ifndef __UBIFS_COMMON_H__
+#define __UBIFS_COMMON_H__
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <string.h>
+#include <stdint.h>
+#include <endian.h>
+#include <byteswap.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <libgen.h>
+#include <ctype.h>
+#include <uuid/uuid.h>
+#include <sys/file.h>
+
+#include <mtd/ubifs-media.h>
+
+#include "libubi.h"
+#include "defs.h"
+
+extern int verbose;
+extern int debug_level;
+
+#define dbg_msg(lvl, fmt, ...) do {if (debug_level >= lvl)                \
+	printf("ubifs: %s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__); \
+} while(0)
+
+#define err_msg(fmt, ...) ({                                \
+	fprintf(stderr, "Error: " fmt "\n", ##__VA_ARGS__); \
+	-1;                                                 \
+})
+
+#define sys_err_msg(fmt, ...) ({                                         \
+	int err_ = errno;                                                \
+	fprintf(stderr, "Error: " fmt "\n", ##__VA_ARGS__);              \
+	fprintf(stderr, "       %s (error %d)\n", strerror(err_), err_); \
+	-1;                                                              \
+})
+#endif
diff --git a/ubifs-utils/lib/compr.c b/ubifs-utils/lib/compr.c
new file mode 100644
index 0000000..54604d4
--- /dev/null
+++ b/ubifs-utils/lib/compr.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation.
+ * Copyright (C) 2008 University of Szeged, Hungary
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Artem Bityutskiy
+ *          Adrian Hunter
+ *          Zoltan Sogor
+ */
+
+#include "ubifs_common.h"
+#ifndef WITHOUT_LZO
+#include <lzo/lzo1x.h>
+#endif
+
+#define crc32 __zlib_crc32
+#include <zlib.h>
+#undef crc32
+
+#include "compr.h"
+
+static void *lzo_mem;
+static unsigned long long errcnt = 0;
+
+#define DEFLATE_DEF_LEVEL     Z_DEFAULT_COMPRESSION
+#define DEFLATE_DEF_WINBITS   11
+#define DEFLATE_DEF_MEMLEVEL  8
+
+static int zlib_deflate(void *in_buf, size_t in_len, void *out_buf,
+			size_t *out_len)
+{
+	z_stream strm;
+
+	strm.zalloc = NULL;
+	strm.zfree = NULL;
+
+	/*
+	 * Match exactly the zlib parameters used by the Linux kernel crypto
+	 * API.
+	 */
+        if (deflateInit2(&strm, DEFLATE_DEF_LEVEL, Z_DEFLATED,
+			 -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
+			 Z_DEFAULT_STRATEGY)) {
+		errcnt += 1;
+		return -1;
+	}
+
+	strm.next_in = in_buf;
+	strm.avail_in = in_len;
+	strm.total_in = 0;
+
+	strm.next_out = out_buf;
+	strm.avail_out = *out_len;
+	strm.total_out = 0;
+
+	if (deflate(&strm, Z_FINISH) != Z_STREAM_END) {
+		deflateEnd(&strm);
+		errcnt += 1;
+		return -1;
+	}
+
+	if (deflateEnd(&strm) != Z_OK) {
+		errcnt += 1;
+		return -1;
+	}
+
+	*out_len = strm.total_out;
+
+	return 0;
+}
+
+#ifndef WITHOUT_LZO
+static int lzo_compress(void *in_buf, size_t in_len, void *out_buf,
+			size_t *out_len)
+{
+	lzo_uint len;
+	int ret;
+
+	len = *out_len;
+	ret = lzo1x_999_compress(in_buf, in_len, out_buf, &len, lzo_mem);
+	*out_len = len;
+
+	if (ret != LZO_E_OK) {
+		errcnt += 1;
+		return -1;
+	}
+
+	return 0;
+}
+#endif
+
+static int no_compress(void *in_buf, size_t in_len, void *out_buf,
+		       size_t *out_len)
+{
+	memcpy(out_buf, in_buf, in_len);
+	*out_len = in_len;
+	return 0;
+}
+
+static char *zlib_buf;
+
+#ifndef WITHOUT_LZO
+static int favor_lzo_compress(void *in_buf, size_t in_len, void *out_buf,
+				size_t *out_len, int *type, int lzo_percent)
+{
+	int lzo_ret, zlib_ret;
+	size_t lzo_len, zlib_len;
+
+	lzo_len = zlib_len = *out_len;
+	lzo_ret = lzo_compress(in_buf, in_len, out_buf, &lzo_len);
+	zlib_ret = zlib_deflate(in_buf, in_len, zlib_buf, &zlib_len);
+
+	if (lzo_ret && zlib_ret)
+		/* Both compressors failed */
+		return -1;
+
+	if (!lzo_ret && !zlib_ret) {
+		double percent;
+
+		/* Both compressors succeeded */
+		if (lzo_len <= zlib_len )
+			goto select_lzo;
+
+		percent = (double)zlib_len / (double)lzo_len;
+		percent *= 100;
+		if (percent > 100 - lzo_percent)
+			goto select_lzo;
+		goto select_zlib;
+	}
+
+	if (lzo_ret)
+		/* Only zlib compressor succeeded */
+		goto select_zlib;
+
+	/* Only LZO compressor succeeded */
+
+select_lzo:
+	*out_len = lzo_len;
+	*type = MKFS_UBIFS_COMPR_LZO;
+	return 0;
+
+select_zlib:
+	*out_len = zlib_len;
+	*type = MKFS_UBIFS_COMPR_ZLIB;
+	memcpy(out_buf, zlib_buf, zlib_len);
+	return 0;
+}
+#endif
+
+int compress_data(void *in_buf, size_t in_len, void *out_buf,
+		size_t *out_len, int type, int lzo_percent)
+{
+	int ret;
+
+	if (in_len < UBIFS_MIN_COMPR_LEN) {
+		no_compress(in_buf, in_len, out_buf, out_len);
+		return MKFS_UBIFS_COMPR_NONE;
+	}
+
+#ifdef WITHOUT_LZO
+	{
+		switch (type) {
+#else
+	if (lzo_percent)
+		ret = favor_lzo_compress(in_buf, in_len, out_buf, out_len, &type, lzo_percent);
+	else {
+		switch (type) {
+		case MKFS_UBIFS_COMPR_LZO:
+			ret = lzo_compress(in_buf, in_len, out_buf, out_len);
+			break;
+#endif
+		case MKFS_UBIFS_COMPR_ZLIB:
+			ret = zlib_deflate(in_buf, in_len, out_buf, out_len);
+			break;
+		case MKFS_UBIFS_COMPR_NONE:
+			ret = 1;
+			break;
+		default:
+			errcnt += 1;
+			ret = 1;
+			break;
+		}
+	}
+	if (ret || *out_len >= in_len) {
+		no_compress(in_buf, in_len, out_buf, out_len);
+		return MKFS_UBIFS_COMPR_NONE;
+	}
+	return type;
+}
+
+int init_compression(void)
+{
+#ifdef WITHOUT_LZO
+	lzo_mem = NULL;
+#else
+	lzo_mem = malloc(LZO1X_999_MEM_COMPRESS);
+	if (!lzo_mem)
+		return -1;
+#endif
+
+	zlib_buf = malloc(UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR);
+	if (!zlib_buf) {
+		free(lzo_mem);
+		return -1;
+	}
+
+	return 0;
+}
+
+void destroy_compression(void)
+{
+	free(zlib_buf);
+	free(lzo_mem);
+	if (errcnt)
+		fprintf(stderr, "%llu compression errors occurred\n", errcnt);
+}
diff --git a/ubifs-utils/lib/crc16.c b/ubifs-utils/lib/crc16.c
new file mode 100644
index 0000000..a19512e
--- /dev/null
+++ b/ubifs-utils/lib/crc16.c
@@ -0,0 +1,56 @@
+/*
+ * This code was taken from the linux kernel. The license is GPL Version 2.
+ */
+
+#include "crc16.h"
+
+/** CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */
+uint16_t const crc16_table[256] = {
+	0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
+	0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
+	0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
+	0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
+	0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
+	0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
+	0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
+	0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
+	0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
+	0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
+	0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
+	0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
+	0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
+	0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
+	0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
+	0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
+	0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
+	0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
+	0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
+	0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
+	0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
+	0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
+	0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
+	0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
+	0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
+	0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
+	0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
+	0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
+	0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
+	0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
+	0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
+	0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
+};
+
+/**
+ * crc16 - compute the CRC-16 for the data buffer
+ * @crc:	previous CRC value
+ * @buffer:	data pointer
+ * @len:	number of bytes in the buffer
+ *
+ * Returns the updated CRC value.
+ */
+uint16_t crc16(uint16_t crc, uint8_t const *buffer, size_t len)
+{
+	while (len--)
+		crc = crc16_byte(crc, *buffer++);
+	return crc;
+}
diff --git a/ubifs-utils/lib/devtable.c b/ubifs-utils/lib/devtable.c
new file mode 100644
index 0000000..e6ec319
--- /dev/null
+++ b/ubifs-utils/lib/devtable.c
@@ -0,0 +1,525 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Artem Bityutskiy
+ *
+ * Part of the device table parsing code was taken from the mkfs.jffs2 utility.
+ * The original author of that code is Erik Andersen, hence:
+ *	Copyright (C) 2001, 2002 Erik Andersen <andersen@codepoet.org>
+ */
+
+/*
+ * This file implemented device table support. Device table entries take the
+ * form of:
+ * <path>    <type> <mode> <uid> <gid> <major> <minor> <start>	<inc> <count>
+ * /dev/mem  c       640   0     0     1       1       0        0     -
+ *
+ * Type can be one of:
+ * f  A regular file
+ * d  Directory
+ * c  Character special device file
+ * b  Block special device file
+ * p  Fifo (named pipe)
+ *
+ * Don't bother with symlinks (permissions are irrelevant), hard links (special
+ * cases of regular files), or sockets (why bother).
+ *
+ * Regular files must exist in the target root directory. If a char, block,
+ * fifo, or directory does not exist, it will be created.
+ *
+ * Please, refer the device_table.txt file which can be found at MTD utilities
+ * for more information about what the device table is.
+ */
+
+#include "ubifs_common.h"
+#include "devtable.h"
+#include "hashtable.h"
+#include "hashtable_itr.h"
+
+/*
+ * The hash table which contains paths to files/directories/device nodes
+ * referred to in the device table. For example, if the device table refers
+ * "/dev/loop0", the @path_htbl will contain "/dev" element.
+ */
+static struct hashtable *path_htbl;
+
+/* Hash function used for hash tables */
+static unsigned int r5_hash(void *s)
+{
+	unsigned int a = 0;
+	const signed char *str = s;
+
+	while (*str) {
+		a += *str << 4;
+		a += *str >> 4;
+		a *= 11;
+		str++;
+	}
+
+	return a;
+}
+
+/*
+ * Check whether 2 keys of a hash table are equivalent. The keys are path/file
+ * names, so we simply use 'strcmp()'.
+ */
+static int is_equivalent(void *k1, void *k2)
+{
+	return !strcmp(k1, k2);
+}
+
+/**
+ * separate_last - separate out the last path component
+ * @buf: the path to split
+ * @len: length of the @buf string
+ * @path: the beginning of path is returned here
+ * @name: the last path component is returned here
+ *
+ * This helper function separates out the the last component of the full path
+ * string. For example, "/dev/loop" would be split on "/dev" and "loop". This
+ * function allocates memory for @path and @name and return the result there.
+ * Returns zero in case of success and a negative error code in case of
+ * failure.
+ */
+static int separate_last(const char *buf, int len, char **path, char **name)
+{
+	int path_len = len, name_len;
+	const char *p = buf + len, *n;
+
+	while (*--p != '/')
+		path_len -= 1;
+
+	/* Drop the final '/' unless this is the root directory */
+	name_len = len - path_len;
+	n = buf + path_len;
+	if (path_len > 1)
+		path_len -= 1;
+
+	*path = malloc(path_len + 1);
+	if (!*path)
+		return err_msg("cannot allocate %d bytes of memory",
+			       path_len + 1);
+	memcpy(*path, buf, path_len);
+	(*path)[path_len] = '\0';
+
+	*name = malloc(name_len + 1);
+	if (!*name) {
+		free(*path);
+		return err_msg("cannot allocate %d bytes of memory",
+			       name_len + 1);
+	}
+	memcpy(*name, n, name_len + 1);
+
+	return 0;
+}
+
+static int interpret_table_entry(const char *line)
+{
+	char buf[1024], type, *path = NULL, *name = NULL;
+	int len;
+	struct path_htbl_element *ph_elt = NULL;
+	struct name_htbl_element *nh_elt = NULL;
+	unsigned int mode = 0755, uid = 0, gid = 0, major = 0, minor = 0;
+	unsigned int start = 0, increment = 0, count = 0;
+
+	if (sscanf(line, "%1023s %c %o %u %u %u %u %u %u %u",
+		   buf, &type, &mode, &uid, &gid, &major, &minor,
+		   &start, &increment, &count) < 0)
+		return sys_err_msg("sscanf failed");
+
+	dbg_msg(3, "name %s, type %c, mode %o, uid %u, gid %u, major %u, "
+		"minor %u, start %u, inc %u, cnt %u",
+		buf, type, mode, uid, gid, major, minor, start,
+		increment, count);
+
+	len = strnlen(buf, 1024);
+	if (len == 1024)
+		return err_msg("too long path");
+
+	if (!strcmp(buf, "/"))
+		return err_msg("device table entries require absolute paths");
+	if (buf[1] == '\0')
+		return err_msg("root directory cannot be created");
+	if (strstr(buf, "//"))
+		return err_msg("'//' cannot be used in the path");
+	if (buf[len - 1] == '/')
+		return err_msg("do not put '/' at the end");
+
+	if (strstr(buf, "/./") || strstr(buf, "/../") ||
+	    !strcmp(buf + len - 2, "/.") || !strcmp(buf + len - 3, "/.."))
+		return err_msg("'.' and '..' cannot be used in the path");
+
+	switch (type) {
+		case 'd':
+			mode |= S_IFDIR;
+			break;
+		case 'f':
+			mode |= S_IFREG;
+			break;
+		case 'p':
+			mode |= S_IFIFO;
+			break;
+		case 'c':
+			mode |= S_IFCHR;
+			break;
+		case 'b':
+			mode |= S_IFBLK;
+			break;
+		default:
+			return err_msg("unsupported file type '%c'", type);
+	}
+
+	if (separate_last(buf, len, &path, &name))
+		return -1;
+
+	/*
+	 * Check if this path already exist in the path hash table and add it
+	 * if it is not.
+	 */
+	ph_elt = hashtable_search(path_htbl, path);
+	if (!ph_elt) {
+		dbg_msg(3, "inserting '%s' into path hash table", path);
+		ph_elt = malloc(sizeof(struct path_htbl_element));
+		if (!ph_elt) {
+			err_msg("cannot allocate %zd bytes of memory",
+				sizeof(struct path_htbl_element));
+			goto out_free;
+		}
+
+		if (!hashtable_insert(path_htbl, path, ph_elt)) {
+			err_msg("cannot insert into path hash table");
+			goto out_free;
+		}
+
+		ph_elt->path = path;
+		path = NULL;
+		ph_elt->name_htbl = create_hashtable(128, &r5_hash,
+						     &is_equivalent);
+		if (!ph_elt->name_htbl) {
+			err_msg("cannot create name hash table");
+			goto out_free;
+		}
+	}
+
+	if (increment != 0 && count == 0)
+		return err_msg("count cannot be zero if increment is non-zero");
+
+	/*
+	 * Add the file/directory/device node (last component of the path) to
+	 * the name hashtable. The name hashtable resides in the corresponding
+	 * path hashtable element.
+	 */
+
+	if (count == 0) {
+		/* This entry does not require any iterating */
+		nh_elt = malloc(sizeof(struct name_htbl_element));
+		if (!nh_elt) {
+			err_msg("cannot allocate %zd bytes of memory",
+				sizeof(struct name_htbl_element));
+			goto out_free;
+		}
+
+		nh_elt->mode = mode;
+		nh_elt->uid = uid;
+		nh_elt->gid = gid;
+		nh_elt->dev = makedev(major, minor);
+
+		dbg_msg(3, "inserting '%s' into name hash table (major %d, minor %d)",
+			name, major(nh_elt->dev), minor(nh_elt->dev));
+
+		if (hashtable_search(ph_elt->name_htbl, name))
+			return err_msg("'%s' is referred twice", buf);
+
+		nh_elt->name = name;
+		if (!hashtable_insert(ph_elt->name_htbl, name, nh_elt)) {
+			err_msg("cannot insert into name hash table");
+			goto out_free;
+		}
+	} else {
+		int i, num = start + count, len = strlen(name) + 20;
+		char *nm;
+
+		for (i = start; i < num; i++) {
+			nh_elt = malloc(sizeof(struct name_htbl_element));
+			if (!nh_elt) {
+				err_msg("cannot allocate %zd bytes of memory",
+					sizeof(struct name_htbl_element));
+				goto out_free;
+			}
+
+			nh_elt->mode = mode;
+			nh_elt->uid = uid;
+			nh_elt->gid = gid;
+			nh_elt->dev = makedev(major, minor + (i - start) * increment);
+
+			nm = malloc(len);
+			if (!nm) {
+				err_msg("cannot allocate %d bytes of memory", len);
+				goto out_free;
+			}
+
+			sprintf(nm, "%s%d", name, i);
+			nh_elt->name = nm;
+
+			dbg_msg(3, "inserting '%s' into name hash table (major %d, minor %d)",
+			        nm, major(nh_elt->dev), minor(nh_elt->dev));
+
+			if (hashtable_search(ph_elt->name_htbl, nm)) {
+				err_msg("'%s' is referred twice", buf);
+				free (nm);
+				goto out_free;
+			}
+
+			if (!hashtable_insert(ph_elt->name_htbl, nm, nh_elt)) {
+				err_msg("cannot insert into name hash table");
+				free (nm);
+				goto out_free;
+			}
+		}
+		free(name);
+		name = NULL;
+	}
+
+	return 0;
+
+out_free:
+	free(ph_elt);
+	free(nh_elt);
+	free(path);
+	free(name);
+	return -1;
+}
+
+/**
+ * parse_devtable - parse the device table.
+ * @tbl_file: device table file name
+ *
+ * This function parses the device table and prepare the hash table which will
+ * later be used by mkfs.ubifs to create the specified files/device nodes.
+ * Returns zero in case of success and a negative error code in case of
+ * failure.
+ */
+int parse_devtable(const char *tbl_file)
+{
+	FILE *f;
+	char *line = NULL;
+	struct stat st;
+	size_t len;
+
+	dbg_msg(1, "parsing device table file '%s'", tbl_file);
+
+	path_htbl = create_hashtable(128, &r5_hash, &is_equivalent);
+	if (!path_htbl)
+		return err_msg("cannot create path hash table");
+
+	f = fopen(tbl_file, "r");
+	if (!f)
+		return sys_err_msg("cannot open '%s'", tbl_file);
+
+	if (fstat(fileno(f), &st) < 0) {
+		sys_err_msg("cannot stat '%s'", tbl_file);
+		goto out_close;
+	}
+
+	if (st.st_size < 10) {
+		sys_err_msg("'%s' is too short", tbl_file);
+		goto out_close;
+	}
+
+	/*
+	 * The general plan now is to read in one line at a time, check for
+	 * leading comment delimiters ('#'), then try and parse the line as a
+	 * device table
+	 */
+	while (getline(&line, &len, f) != -1) {
+		/* First trim off any white-space */
+		len = strlen(line);
+
+		/* Trim trailing white-space */
+		while (len > 0 && isspace(line[len - 1]))
+			line[--len] = '\0';
+		/* Trim leading white-space */
+		memmove(line, &line[strspn(line, " \n\r\t\v")], len);
+
+		/* How long are we after trimming? */
+		len = strlen(line);
+
+		/* If this is not a comment line, try to interpret it */
+		if (len && *line != '#') {
+			if (interpret_table_entry(line)) {
+				err_msg("cannot parse '%s'", line);
+				goto out_close;
+			}
+		}
+
+		free(line);
+		line = NULL;
+	}
+
+	dbg_msg(1, "finished parsing");
+	fclose(f);
+	return 0;
+
+out_close:
+	fclose(f);
+	free_devtable_info();
+	return -1;
+}
+
+/**
+ * devtbl_find_path - find a path in the path hash table.
+ * @path: UBIFS path to find.
+ *
+ * This looks up the path hash table. Returns the path hash table element
+ * reference if @path was found and %NULL if not.
+ */
+struct path_htbl_element *devtbl_find_path(const char *path)
+{
+	if (!path_htbl)
+		return NULL;
+
+	return hashtable_search(path_htbl, (void *)path);
+}
+
+/**
+ * devtbl_find_name - find a name in the name hash table.
+ * @ph_etl: path hash table element to find at
+ * @name: name to find
+ *
+ * This looks up the name hash table. Returns the name hash table element
+ * reference if @name found and %NULL if not.
+ */
+struct name_htbl_element *devtbl_find_name(struct path_htbl_element *ph_elt,
+					   const char *name)
+{
+	if (!path_htbl)
+		return NULL;
+
+	return hashtable_search(ph_elt->name_htbl, (void *)name);
+}
+
+/**
+ * override_attributes - override inode attributes.
+ * @st: struct stat object to containing the attributes to override
+ * @ph_elt: path hash table element object
+ * @nh_elt: name hash table element object containing the new values
+ *
+ * The device table file may override attributes like UID of files. For
+ * example, the device table may contain a "/dev" entry, and the UBIFS FS on
+ * the host may contain "/dev" directory. In this case the attributes of the
+ * "/dev" directory inode has to be as the device table specifies.
+ *
+ * Note, the hash element is removed by this function as well.
+ */
+int override_attributes(struct stat *st, struct path_htbl_element *ph_elt,
+			struct name_htbl_element *nh_elt)
+{
+	if (!path_htbl)
+		return 0;
+
+	if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode) ||
+	    S_ISFIFO(st->st_mode))
+		return err_msg("%s/%s both exists at UBIFS root at host, "
+			       "and is referred from the device table",
+			       strcmp(ph_elt->path, "/") ? ph_elt->path : "",
+			       nh_elt->name);
+
+	if ((st->st_mode & S_IFMT) != (nh_elt->mode & S_IFMT))
+		return err_msg("%s/%s is referred from the device table also exists in "
+			       "the UBIFS root directory at host, but the file type is "
+			       "different", strcmp(ph_elt->path, "/") ? ph_elt->path : "",
+			       nh_elt->name);
+
+	dbg_msg(3, "set UID %d, GID %d, mode %o for %s/%s as device table says",
+		nh_elt->uid, nh_elt->gid, nh_elt->mode, ph_elt->path, nh_elt->name);
+
+	st->st_uid = nh_elt->uid;
+	st->st_gid = nh_elt->gid;
+	st->st_mode = nh_elt->mode;
+
+	hashtable_remove(ph_elt->name_htbl, (void *)nh_elt->name);
+	return 0;
+}
+
+/**
+ * first_name_htbl_element - return first element of the name hash table.
+ * @ph_elt: the path hash table the name hash table belongs to
+ * @itr: double pointer to a 'struct hashtable_itr' object where the
+ *       information about further iterations is stored
+ *
+ * This function implements name hash table iteration together with
+ * 'next_name_htbl_element()'. Returns the first name hash table element or
+ * %NULL if the hash table is empty.
+ */
+struct name_htbl_element *
+first_name_htbl_element(struct path_htbl_element *ph_elt,
+			struct hashtable_itr **itr)
+{
+	if (!path_htbl || !ph_elt || hashtable_count(ph_elt->name_htbl) == 0)
+		return NULL;
+
+	*itr = hashtable_iterator(ph_elt->name_htbl);
+	return hashtable_iterator_value(*itr);
+}
+
+/**
+ * first_name_htbl_element - return next element of the name hash table.
+ * @ph_elt: the path hash table the name hash table belongs to
+ * @itr: double pointer to a 'struct hashtable_itr' object where the
+ *       information about further iterations is stored
+ *
+ * This function implements name hash table iteration together with
+ * 'first_name_htbl_element()'. Returns the next name hash table element or
+ * %NULL if there are no more elements.
+ */
+struct name_htbl_element *
+next_name_htbl_element(struct path_htbl_element *ph_elt,
+		       struct hashtable_itr **itr)
+{
+	if (!path_htbl || !ph_elt || !hashtable_iterator_advance(*itr))
+		return NULL;
+
+	return hashtable_iterator_value(*itr);
+}
+
+/**
+ * free_devtable_info - free device table information.
+ *
+ * This function frees the path hash table and the name hash tables.
+ */
+void free_devtable_info(void)
+{
+	struct hashtable_itr *ph_itr;
+	struct path_htbl_element *ph_elt;
+
+	if (!path_htbl)
+		return;
+
+	if (hashtable_count(path_htbl) > 0) {
+		ph_itr = hashtable_iterator(path_htbl);
+		do {
+			ph_elt = hashtable_iterator_value(ph_itr);
+			/*
+			 * Note, since we use the same string for the key and
+			 * @name in the name hash table elements, we do not
+			 * have to iterate name hash table because @name memory
+			 * will be freed when freeing the key.
+			 */
+			hashtable_destroy(ph_elt->name_htbl, 1);
+		} while (hashtable_iterator_advance(ph_itr));
+	}
+	hashtable_destroy(path_htbl, 1);
+}
diff --git a/ubifs-utils/lib/hashtable.c b/ubifs-utils/lib/hashtable.c
new file mode 100644
index 0000000..c1f99ed
--- /dev/null
+++ b/ubifs-utils/lib/hashtable.c
@@ -0,0 +1,277 @@
+/* Copyright (C) 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
+
+#define PROGRAM_NAME "hashtable"
+
+#include "common.h"
+#include "hashtable.h"
+#include "hashtable_private.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+/*
+Credit for primes table: Aaron Krowne
+ http://br.endernet.org/~akrowne/
+ http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
+*/
+static const unsigned int primes[] = {
+53, 97, 193, 389,
+769, 1543, 3079, 6151,
+12289, 24593, 49157, 98317,
+196613, 393241, 786433, 1572869,
+3145739, 6291469, 12582917, 25165843,
+50331653, 100663319, 201326611, 402653189,
+805306457, 1610612741
+};
+const unsigned int prime_table_length = ARRAY_SIZE(primes);
+const float max_load_factor = 0.65;
+
+/*****************************************************************************/
+struct hashtable *
+create_hashtable(unsigned int minsize,
+                 unsigned int (*hashf) (void*),
+                 int (*eqf) (void*,void*))
+{
+    struct hashtable *h;
+    unsigned int pindex, size = primes[0];
+    /* Check requested hashtable isn't too large */
+    if (minsize > (1u << 30)) return NULL;
+    /* Enforce size as prime */
+    for (pindex=0; pindex < prime_table_length; pindex++) {
+        if (primes[pindex] > minsize) { size = primes[pindex]; break; }
+    }
+    h = (struct hashtable *)malloc(sizeof(struct hashtable));
+    if (NULL == h) return NULL; /*oom*/
+    h->table = (struct entry **)malloc(sizeof(struct entry*) * size);
+    if (NULL == h->table) { free(h); return NULL; } /*oom*/
+    memset(h->table, 0, size * sizeof(struct entry *));
+    h->tablelength  = size;
+    h->primeindex   = pindex;
+    h->entrycount   = 0;
+    h->hashfn       = hashf;
+    h->eqfn         = eqf;
+    h->loadlimit    = (unsigned int) ceil(size * max_load_factor);
+    return h;
+}
+
+/*****************************************************************************/
+unsigned int
+hash(struct hashtable *h, void *k)
+{
+    /* Aim to protect against poor hash functions by adding logic here
+     * - logic taken from java 1.4 hashtable source */
+    unsigned int i = h->hashfn(k);
+    i += ~(i << 9);
+    i ^=  ((i >> 14) | (i << 18)); /* >>> */
+    i +=  (i << 4);
+    i ^=  ((i >> 10) | (i << 22)); /* >>> */
+    return i;
+}
+
+/*****************************************************************************/
+static int
+hashtable_expand(struct hashtable *h)
+{
+    /* Double the size of the table to accomodate more entries */
+    struct entry **newtable;
+    struct entry *e;
+    struct entry **pE;
+    unsigned int newsize, i, index;
+    /* Check we're not hitting max capacity */
+    if (h->primeindex == (prime_table_length - 1)) return 0;
+    newsize = primes[++(h->primeindex)];
+
+    newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize);
+    if (NULL != newtable)
+    {
+        memset(newtable, 0, newsize * sizeof(struct entry *));
+        /* This algorithm is not 'stable'. ie. it reverses the list
+         * when it transfers entries between the tables */
+        for (i = 0; i < h->tablelength; i++) {
+            while (NULL != (e = h->table[i])) {
+                h->table[i] = e->next;
+                index = indexFor(newsize,e->h);
+                e->next = newtable[index];
+                newtable[index] = e;
+            }
+        }
+        free(h->table);
+        h->table = newtable;
+    }
+    /* Plan B: realloc instead */
+    else
+    {
+        newtable = (struct entry **)
+                   realloc(h->table, newsize * sizeof(struct entry *));
+        if (NULL == newtable) { (h->primeindex)--; return 0; }
+        h->table = newtable;
+        memset(newtable[h->tablelength], 0, newsize - h->tablelength);
+        for (i = 0; i < h->tablelength; i++) {
+            for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
+                index = indexFor(newsize,e->h);
+                if (index == i)
+                {
+                    pE = &(e->next);
+                }
+                else
+                {
+                    *pE = e->next;
+                    e->next = newtable[index];
+                    newtable[index] = e;
+                }
+            }
+        }
+    }
+    h->tablelength = newsize;
+    h->loadlimit   = (unsigned int) ceil(newsize * max_load_factor);
+    return -1;
+}
+
+/*****************************************************************************/
+unsigned int
+hashtable_count(struct hashtable *h)
+{
+    return h->entrycount;
+}
+
+/*****************************************************************************/
+int
+hashtable_insert(struct hashtable *h, void *k, void *v)
+{
+    /* This method allows duplicate keys - but they shouldn't be used */
+    unsigned int index;
+    struct entry *e;
+    if (++(h->entrycount) > h->loadlimit)
+    {
+        /* Ignore the return value. If expand fails, we should
+         * still try cramming just this value into the existing table
+         * -- we may not have memory for a larger table, but one more
+         * element may be ok. Next time we insert, we'll try expanding again.*/
+        hashtable_expand(h);
+    }
+    e = (struct entry *)malloc(sizeof(struct entry));
+    if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
+    e->h = hash(h,k);
+    index = indexFor(h->tablelength,e->h);
+    e->k = k;
+    e->v = v;
+    e->next = h->table[index];
+    h->table[index] = e;
+    return -1;
+}
+
+/*****************************************************************************/
+void * /* returns value associated with key */
+hashtable_search(struct hashtable *h, void *k)
+{
+    struct entry *e;
+    unsigned int hashvalue, index;
+    hashvalue = hash(h,k);
+    index = indexFor(h->tablelength,hashvalue);
+    e = h->table[index];
+    while (NULL != e)
+    {
+        /* Check hash value to short circuit heavier comparison */
+        if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v;
+        e = e->next;
+    }
+    return NULL;
+}
+
+/*****************************************************************************/
+void * /* returns value associated with key */
+hashtable_remove(struct hashtable *h, void *k)
+{
+    /* TODO: consider compacting the table when the load factor drops enough,
+     *       or provide a 'compact' method. */
+
+    struct entry *e;
+    struct entry **pE;
+    void *v;
+    unsigned int hashvalue, index;
+
+    hashvalue = hash(h,k);
+    index = indexFor(h->tablelength,hash(h,k));
+    pE = &(h->table[index]);
+    e = *pE;
+    while (NULL != e)
+    {
+        /* Check hash value to short circuit heavier comparison */
+        if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
+        {
+            *pE = e->next;
+            h->entrycount--;
+            v = e->v;
+            freekey(e->k);
+            free(e);
+            return v;
+        }
+        pE = &(e->next);
+        e = e->next;
+    }
+    return NULL;
+}
+
+/*****************************************************************************/
+/* destroy */
+void
+hashtable_destroy(struct hashtable *h, int free_values)
+{
+    unsigned int i;
+    struct entry *e, *f;
+    struct entry **table = h->table;
+    if (free_values)
+    {
+        for (i = 0; i < h->tablelength; i++)
+        {
+            e = table[i];
+            while (NULL != e)
+            { f = e; e = e->next; freekey(f->k); free(f->v); free(f); }
+        }
+    }
+    else
+    {
+        for (i = 0; i < h->tablelength; i++)
+        {
+            e = table[i];
+            while (NULL != e)
+            { f = e; e = e->next; freekey(f->k); free(f); }
+        }
+    }
+    free(h->table);
+    free(h);
+}
+
+/*
+ * Copyright (c) 2002, Christopher Clark
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
diff --git a/ubifs-utils/lib/hashtable_itr.c b/ubifs-utils/lib/hashtable_itr.c
new file mode 100644
index 0000000..d102453
--- /dev/null
+++ b/ubifs-utils/lib/hashtable_itr.c
@@ -0,0 +1,176 @@
+/* Copyright (C) 2002, 2004 Christopher Clark  <firstname.lastname@cl.cam.ac.uk> */
+
+#include "hashtable.h"
+#include "hashtable_private.h"
+#include "hashtable_itr.h"
+#include <stdlib.h> /* defines NULL */
+
+/*****************************************************************************/
+/* hashtable_iterator    - iterator constructor */
+
+struct hashtable_itr *
+hashtable_iterator(struct hashtable *h)
+{
+    unsigned int i, tablelength;
+    struct hashtable_itr *itr = (struct hashtable_itr *)
+        malloc(sizeof(struct hashtable_itr));
+    if (NULL == itr) return NULL;
+    itr->h = h;
+    itr->e = NULL;
+    itr->parent = NULL;
+    tablelength = h->tablelength;
+    itr->index = tablelength;
+    if (0 == h->entrycount) return itr;
+
+    for (i = 0; i < tablelength; i++)
+    {
+        if (NULL != h->table[i])
+        {
+            itr->e = h->table[i];
+            itr->index = i;
+            break;
+        }
+    }
+    return itr;
+}
+
+/*****************************************************************************/
+/* advance - advance the iterator to the next element
+ *           returns zero if advanced to end of table */
+
+int
+hashtable_iterator_advance(struct hashtable_itr *itr)
+{
+    unsigned int j,tablelength;
+    struct entry **table;
+    struct entry *next;
+    if (NULL == itr->e) return 0; /* stupidity check */
+
+    next = itr->e->next;
+    if (NULL != next)
+    {
+        itr->parent = itr->e;
+        itr->e = next;
+        return -1;
+    }
+    tablelength = itr->h->tablelength;
+    itr->parent = NULL;
+    if (tablelength <= (j = ++(itr->index)))
+    {
+        itr->e = NULL;
+        return 0;
+    }
+    table = itr->h->table;
+    while (NULL == (next = table[j]))
+    {
+        if (++j >= tablelength)
+        {
+            itr->index = tablelength;
+            itr->e = NULL;
+            return 0;
+        }
+    }
+    itr->index = j;
+    itr->e = next;
+    return -1;
+}
+
+/*****************************************************************************/
+/* remove - remove the entry at the current iterator position
+ *          and advance the iterator, if there is a successive
+ *          element.
+ *          If you want the value, read it before you remove:
+ *          beware memory leaks if you don't.
+ *          Returns zero if end of iteration. */
+
+int
+hashtable_iterator_remove(struct hashtable_itr *itr)
+{
+    struct entry *remember_e, *remember_parent;
+    int ret;
+
+    /* Do the removal */
+    if (NULL == (itr->parent))
+    {
+        /* element is head of a chain */
+        itr->h->table[itr->index] = itr->e->next;
+    } else {
+        /* element is mid-chain */
+        itr->parent->next = itr->e->next;
+    }
+    /* itr->e is now outside the hashtable */
+    remember_e = itr->e;
+    itr->h->entrycount--;
+    freekey(remember_e->k);
+
+    /* Advance the iterator, correcting the parent */
+    remember_parent = itr->parent;
+    ret = hashtable_iterator_advance(itr);
+    if (itr->parent == remember_e) { itr->parent = remember_parent; }
+    free(remember_e);
+    return ret;
+}
+
+/*****************************************************************************/
+int /* returns zero if not found */
+hashtable_iterator_search(struct hashtable_itr *itr,
+                          struct hashtable *h, void *k)
+{
+    struct entry *e, *parent;
+    unsigned int hashvalue, index;
+
+    hashvalue = hash(h,k);
+    index = indexFor(h->tablelength,hashvalue);
+
+    e = h->table[index];
+    parent = NULL;
+    while (NULL != e)
+    {
+        /* Check hash value to short circuit heavier comparison */
+        if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
+        {
+            itr->index = index;
+            itr->e = e;
+            itr->parent = parent;
+            itr->h = h;
+            return -1;
+        }
+        parent = e;
+        e = e->next;
+    }
+    return 0;
+}
+
+
+/*
+ * Copyright (c) 2002, 2004, Christopher Clark
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
diff --git a/ubifs-utils/lib/io.c b/ubifs-utils/lib/io.c
new file mode 100644
index 0000000..7aba0a6
--- /dev/null
+++ b/ubifs-utils/lib/io.c
@@ -0,0 +1,33 @@
+#include "io.h"
+#define PROGRAM_NAME "ubifs-io"
+#include <common.h>
+
+int out_fd;
+int out_ubi;
+libubi_t ubi;
+
+/**
+ * write_leb - copy the image of a LEB to the output target.
+ * @lnum: LEB number
+ * @len: length of data in the buffer
+ * @buf: buffer (must be at least c->leb_size bytes)
+ */
+int write_leb(struct ubifs_info *c, int lnum, int len, void *buf)
+{
+	off_t pos = (off_t)lnum * c->leb_size;
+
+	dbg_msg(3, "LEB %d len %d", lnum, len);
+	memset(buf + len, 0xff, c->leb_size - len);
+	if (out_ubi)
+		if (ubi_leb_change_start(ubi, out_fd, lnum, c->leb_size))
+			return sys_err_msg("ubi_leb_change_start failed");
+
+	if (lseek(out_fd, pos, SEEK_SET) != pos)
+		return sys_err_msg("lseek failed seeking %"PRIdoff_t, pos);
+
+	if (write(out_fd, buf, c->leb_size) != c->leb_size)
+		return sys_err_msg("write failed writing %d bytes at pos %"PRIdoff_t,
+				   c->leb_size, pos);
+
+	return 0;
+}
diff --git a/ubifs-utils/lib/lpt.c b/ubifs-utils/lib/lpt.c
new file mode 100644
index 0000000..100d747
--- /dev/null
+++ b/ubifs-utils/lib/lpt.c
@@ -0,0 +1,587 @@
+/*
+ * This file is part of UBIFS.
+ *
+ * Copyright (C) 2006, 2007 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Adrian Hunter
+ *          Artem Bityutskiy
+ */
+
+#include "ubifs_common.h"
+
+/* common.h requires the PROGRAM_NAME macro */
+#define PROGRAM_NAME "ubifs-lpt"
+#include "common.h"
+
+#include "crc16.h"
+#include "ubifs.h"
+#include "lpt.h"
+#include "io.h"
+
+/**
+ * do_calc_lpt_geom - calculate sizes for the LPT area.
+ * @c: the UBIFS file-system description object
+ *
+ * Calculate the sizes of LPT bit fields, nodes, and tree, based on the
+ * properties of the flash and whether LPT is "big" (c->big_lpt).
+ */
+static void do_calc_lpt_geom(struct ubifs_info *c)
+{
+	int n, bits, per_leb_wastage;
+	long long sz, tot_wastage;
+
+	c->pnode_cnt = (c->main_lebs + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT;
+
+	n = (c->pnode_cnt + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT;
+	c->nnode_cnt = n;
+	while (n > 1) {
+		n = (n + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT;
+		c->nnode_cnt += n;
+	}
+
+	c->lpt_hght = 1;
+	n = UBIFS_LPT_FANOUT;
+	while (n < c->pnode_cnt) {
+		c->lpt_hght += 1;
+		n <<= UBIFS_LPT_FANOUT_SHIFT;
+	}
+
+	c->space_bits = fls(c->leb_size) - 3;
+	c->lpt_lnum_bits = fls(c->lpt_lebs);
+	c->lpt_offs_bits = fls(c->leb_size - 1);
+	c->lpt_spc_bits = fls(c->leb_size);
+
+	n = (c->max_leb_cnt + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT;
+	c->pcnt_bits = fls(n - 1);
+
+	c->lnum_bits = fls(c->max_leb_cnt - 1);
+
+	bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
+	       (c->big_lpt ? c->pcnt_bits : 0) +
+	       (c->space_bits * 2 + 1) * UBIFS_LPT_FANOUT;
+	c->pnode_sz = (bits + 7) / 8;
+
+	bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
+	       (c->big_lpt ? c->pcnt_bits : 0) +
+	       (c->lpt_lnum_bits + c->lpt_offs_bits) * UBIFS_LPT_FANOUT;
+	c->nnode_sz = (bits + 7) / 8;
+
+	bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
+	       c->lpt_lebs * c->lpt_spc_bits * 2;
+	c->ltab_sz = (bits + 7) / 8;
+
+	bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
+	       c->lnum_bits * c->lsave_cnt;
+	c->lsave_sz = (bits + 7) / 8;
+
+	/* Calculate the minimum LPT size */
+	c->lpt_sz = (long long)c->pnode_cnt * c->pnode_sz;
+	c->lpt_sz += (long long)c->nnode_cnt * c->nnode_sz;
+	c->lpt_sz += c->ltab_sz;
+	c->lpt_sz += c->lsave_sz;
+
+	/* Add wastage */
+	sz = c->lpt_sz;
+	per_leb_wastage = max_t(int, c->pnode_sz, c->nnode_sz);
+	sz += per_leb_wastage;
+	tot_wastage = per_leb_wastage;
+	while (sz > c->leb_size) {
+		sz += per_leb_wastage;
+		sz -= c->leb_size;
+		tot_wastage += per_leb_wastage;
+	}
+	tot_wastage += ALIGN(sz, c->min_io_size) - sz;
+	c->lpt_sz += tot_wastage;
+}
+
+/**
+ * calc_dflt_lpt_geom - calculate default LPT geometry.
+ * @c: the UBIFS file-system description object
+ * @main_lebs: number of main area LEBs is passed and returned here
+ * @big_lpt: whether the LPT area is "big" is returned here
+ *
+ * The size of the LPT area depends on parameters that themselves are dependent
+ * on the size of the LPT area. This function, successively recalculates the LPT
+ * area geometry until the parameters and resultant geometry are consistent.
+ *
+ * This function returns %0 on success and a negative error code on failure.
+ */
+int calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs, int *big_lpt)
+{
+	int i, lebs_needed;
+	long long sz;
+
+	/* Start by assuming the minimum number of LPT LEBs */
+	c->lpt_lebs = UBIFS_MIN_LPT_LEBS;
+	c->main_lebs = *main_lebs - c->lpt_lebs;
+	if (c->main_lebs <= 0)
+		return -EINVAL;
+
+	/* And assume we will use the small LPT model */
+	c->big_lpt = 0;
+
+	/*
+	 * Calculate the geometry based on assumptions above and then see if it
+	 * makes sense
+	 */
+	do_calc_lpt_geom(c);
+
+	/* Small LPT model must have lpt_sz < leb_size */
+	if (c->lpt_sz > c->leb_size) {
+		/* Nope, so try again using big LPT model */
+		c->big_lpt = 1;
+		do_calc_lpt_geom(c);
+	}
+
+	/* Now check there are enough LPT LEBs */
+	for (i = 0; i < 64 ; i++) {
+		sz = c->lpt_sz * 4; /* Allow 4 times the size */
+		sz += c->leb_size - 1;
+		do_div(sz, c->leb_size);
+		lebs_needed = sz;
+		if (lebs_needed > c->lpt_lebs) {
+			/* Not enough LPT LEBs so try again with more */
+			c->lpt_lebs = lebs_needed;
+			c->main_lebs = *main_lebs - c->lpt_lebs;
+			if (c->main_lebs <= 0)
+				return -EINVAL;
+			do_calc_lpt_geom(c);
+			continue;
+		}
+		if (c->ltab_sz > c->leb_size) {
+			err_msg("LPT ltab too big");
+			return -EINVAL;
+		}
+		*main_lebs = c->main_lebs;
+		*big_lpt = c->big_lpt;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+/**
+ * pack_bits - pack bit fields end-to-end.
+ * @addr: address at which to pack (passed and next address returned)
+ * @pos: bit position at which to pack (passed and next position returned)
+ * @val: value to pack
+ * @nrbits: number of bits of value to pack (1-32)
+ */
+static void pack_bits(uint8_t **addr, int *pos, uint32_t val, int nrbits)
+{
+	uint8_t *p = *addr;
+	int b = *pos;
+
+	if (b) {
+		*p |= ((uint8_t)val) << b;
+		nrbits += b;
+		if (nrbits > 8) {
+			*++p = (uint8_t)(val >>= (8 - b));
+			if (nrbits > 16) {
+				*++p = (uint8_t)(val >>= 8);
+				if (nrbits > 24) {
+					*++p = (uint8_t)(val >>= 8);
+					if (nrbits > 32)
+						*++p = (uint8_t)(val >>= 8);
+				}
+			}
+		}
+	} else {
+		*p = (uint8_t)val;
+		if (nrbits > 8) {
+			*++p = (uint8_t)(val >>= 8);
+			if (nrbits > 16) {
+				*++p = (uint8_t)(val >>= 8);
+				if (nrbits > 24)
+					*++p = (uint8_t)(val >>= 8);
+			}
+		}
+	}
+	b = nrbits & 7;
+	if (b == 0)
+		p++;
+	*addr = p;
+	*pos = b;
+}
+
+/**
+ * pack_pnode - pack all the bit fields of a pnode.
+ * @c: UBIFS file-system description object
+ * @buf: buffer into which to pack
+ * @pnode: pnode to pack
+ */
+static void pack_pnode(struct ubifs_info *c, void *buf,
+		       struct ubifs_pnode *pnode)
+{
+	uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
+	int i, pos = 0;
+	uint16_t crc;
+
+	pack_bits(&addr, &pos, UBIFS_LPT_PNODE, UBIFS_LPT_TYPE_BITS);
+	if (c->big_lpt)
+		pack_bits(&addr, &pos, pnode->num, c->pcnt_bits);
+	for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
+		pack_bits(&addr, &pos, pnode->lprops[i].free >> 3,
+			  c->space_bits);
+		pack_bits(&addr, &pos, pnode->lprops[i].dirty >> 3,
+			  c->space_bits);
+		if (pnode->lprops[i].flags & LPROPS_INDEX)
+			pack_bits(&addr, &pos, 1, 1);
+		else
+			pack_bits(&addr, &pos, 0, 1);
+	}
+	crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
+		    c->pnode_sz - UBIFS_LPT_CRC_BYTES);
+	addr = buf;
+	pos = 0;
+	pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
+}
+
+/**
+ * pack_nnode - pack all the bit fields of a nnode.
+ * @c: UBIFS file-system description object
+ * @buf: buffer into which to pack
+ * @nnode: nnode to pack
+ */
+static void pack_nnode(struct ubifs_info *c, void *buf,
+		       struct ubifs_nnode *nnode)
+{
+	uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
+	int i, pos = 0;
+	uint16_t crc;
+
+	pack_bits(&addr, &pos, UBIFS_LPT_NNODE, UBIFS_LPT_TYPE_BITS);
+	if (c->big_lpt)
+		pack_bits(&addr, &pos, nnode->num, c->pcnt_bits);
+	for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
+		int lnum = nnode->nbranch[i].lnum;
+
+		if (lnum == 0)
+			lnum = c->lpt_last + 1;
+		pack_bits(&addr, &pos, lnum - c->lpt_first, c->lpt_lnum_bits);
+		pack_bits(&addr, &pos, nnode->nbranch[i].offs,
+			  c->lpt_offs_bits);
+	}
+	crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
+		    c->nnode_sz - UBIFS_LPT_CRC_BYTES);
+	addr = buf;
+	pos = 0;
+	pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
+}
+
+/**
+ * pack_ltab - pack the LPT's own lprops table.
+ * @c: UBIFS file-system description object
+ * @buf: buffer into which to pack
+ * @ltab: LPT's own lprops table to pack
+ */
+static void pack_ltab(struct ubifs_info *c, void *buf,
+			 struct ubifs_lpt_lprops *ltab)
+{
+	uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
+	int i, pos = 0;
+	uint16_t crc;
+
+	pack_bits(&addr, &pos, UBIFS_LPT_LTAB, UBIFS_LPT_TYPE_BITS);
+	for (i = 0; i < c->lpt_lebs; i++) {
+		pack_bits(&addr, &pos, ltab[i].free, c->lpt_spc_bits);
+		pack_bits(&addr, &pos, ltab[i].dirty, c->lpt_spc_bits);
+	}
+	crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
+		    c->ltab_sz - UBIFS_LPT_CRC_BYTES);
+	addr = buf;
+	pos = 0;
+	pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
+}
+
+/**
+ * pack_lsave - pack the LPT's save table.
+ * @c: UBIFS file-system description object
+ * @buf: buffer into which to pack
+ * @lsave: LPT's save table to pack
+ */
+static void pack_lsave(struct ubifs_info *c, void *buf, int *lsave)
+{
+	uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
+	int i, pos = 0;
+	uint16_t crc;
+
+	pack_bits(&addr, &pos, UBIFS_LPT_LSAVE, UBIFS_LPT_TYPE_BITS);
+	for (i = 0; i < c->lsave_cnt; i++)
+		pack_bits(&addr, &pos, lsave[i], c->lnum_bits);
+	crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
+		    c->lsave_sz - UBIFS_LPT_CRC_BYTES);
+	addr = buf;
+	pos = 0;
+	pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
+}
+
+/**
+ * set_ltab - set LPT LEB properties.
+ * @c: UBIFS file-system description object
+ * @lnum: LEB number
+ * @free: amount of free space
+ * @dirty: amount of dirty space
+ */
+static void set_ltab(struct ubifs_info *c, int lnum, int free, int dirty)
+{
+	dbg_msg(3, "LEB %d free %d dirty %d to %d %d",
+		lnum, c->ltab[lnum - c->lpt_first].free,
+		c->ltab[lnum - c->lpt_first].dirty, free, dirty);
+	c->ltab[lnum - c->lpt_first].free = free;
+	c->ltab[lnum - c->lpt_first].dirty = dirty;
+}
+
+/**
+ * calc_nnode_num - calculate nnode number.
+ * @row: the row in the tree (root is zero)
+ * @col: the column in the row (leftmost is zero)
+ *
+ * The nnode number is a number that uniquely identifies a nnode and can be used
+ * easily to traverse the tree from the root to that nnode.
+ *
+ * This function calculates and returns the nnode number for the nnode at @row
+ * and @col.
+ */
+static int calc_nnode_num(int row, int col)
+{
+	int num, bits;
+
+	num = 1;
+	while (row--) {
+		bits = (col & (UBIFS_LPT_FANOUT - 1));
+		col >>= UBIFS_LPT_FANOUT_SHIFT;
+		num <<= UBIFS_LPT_FANOUT_SHIFT;
+		num |= bits;
+	}
+	return num;
+}
+
+/**
+ * create_lpt - create LPT.
+ * @c: UBIFS file-system description object
+ *
+ * This function returns %0 on success and a negative error code on failure.
+ */
+int create_lpt(struct ubifs_info *c)
+{
+	int lnum, err = 0, i, j, cnt, len, alen, row;
+	int blnum, boffs, bsz, bcnt;
+	struct ubifs_pnode *pnode = NULL;
+	struct ubifs_nnode *nnode = NULL;
+	void *buf = NULL, *p;
+	int *lsave = NULL;
+
+	pnode = malloc(sizeof(struct ubifs_pnode));
+	nnode = malloc(sizeof(struct ubifs_nnode));
+	buf = malloc(c->leb_size);
+	lsave = malloc(sizeof(int) * c->lsave_cnt);
+	if (!pnode || !nnode || !buf || !lsave) {
+		err = -ENOMEM;
+		goto out;
+	}
+	memset(pnode, 0 , sizeof(struct ubifs_pnode));
+	memset(nnode, 0 , sizeof(struct ubifs_nnode));
+
+	c->lscan_lnum = c->main_first;
+
+	lnum = c->lpt_first;
+	p = buf;
+	len = 0;
+	/* Number of leaf nodes (pnodes) */
+	cnt = (c->main_lebs + UBIFS_LPT_FANOUT - 1) >> UBIFS_LPT_FANOUT_SHIFT;
+	//printf("pnode_cnt=%d\n",cnt);
+
+	/*
+	 * To calculate the internal node branches, we keep information about
+	 * the level below.
+	 */
+	blnum = lnum; /* LEB number of level below */
+	boffs = 0; /* Offset of level below */
+	bcnt = cnt; /* Number of nodes in level below */
+	bsz = c->pnode_sz; /* Size of nodes in level below */
+
+	/* Add pnodes */
+	for (i = 0; i < cnt; i++) {
+		if (len + c->pnode_sz > c->leb_size) {
+			alen = ALIGN(len, c->min_io_size);
+			set_ltab(c, lnum, c->leb_size - alen, alen - len);
+			memset(p, 0xff, alen - len);
+			err = write_leb(c, lnum++, alen, buf);
+			if (err)
+				goto out;
+			p = buf;
+			len = 0;
+		}
+		/* Fill in the pnode */
+		for (j = 0; j < UBIFS_LPT_FANOUT; j++) {
+			int k = (i << UBIFS_LPT_FANOUT_SHIFT) + j;
+
+			if (k < c->main_lebs)
+				pnode->lprops[j] = c->lpt[k];
+			else {
+				pnode->lprops[j].free = c->leb_size;
+				pnode->lprops[j].dirty = 0;
+				pnode->lprops[j].flags = 0;
+			}
+		}
+		pack_pnode(c, p, pnode);
+		p += c->pnode_sz;
+		len += c->pnode_sz;
+		/*
+		 * pnodes are simply numbered left to right starting at zero,
+		 * which means the pnode number can be used easily to traverse
+		 * down the tree to the corresponding pnode.
+		 */
+		pnode->num += 1;
+	}
+
+	row = c->lpt_hght - 1;
+	/* Add all nnodes, one level at a time */
+	while (1) {
+		/* Number of internal nodes (nnodes) at next level */
+		cnt = (cnt + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT;
+		if (cnt == 0)
+			cnt = 1;
+		for (i = 0; i < cnt; i++) {
+			if (len + c->nnode_sz > c->leb_size) {
+				alen = ALIGN(len, c->min_io_size);
+				set_ltab(c, lnum, c->leb_size - alen,
+					    alen - len);
+				memset(p, 0xff, alen - len);
+				err = write_leb(c, lnum++, alen, buf);
+				if (err)
+					goto out;
+				p = buf;
+				len = 0;
+			}
+			/* The root is on row zero */
+			if (row == 0) {
+				c->lpt_lnum = lnum;
+				c->lpt_offs = len;
+			}
+			/* Set branches to the level below */
+			for (j = 0; j < UBIFS_LPT_FANOUT; j++) {
+				if (bcnt) {
+					if (boffs + bsz > c->leb_size) {
+						blnum += 1;
+						boffs = 0;
+					}
+					nnode->nbranch[j].lnum = blnum;
+					nnode->nbranch[j].offs = boffs;
+					boffs += bsz;
+					bcnt--;
+				} else {
+					nnode->nbranch[j].lnum = 0;
+					nnode->nbranch[j].offs = 0;
+				}
+			}
+			nnode->num = calc_nnode_num(row, i);
+			pack_nnode(c, p, nnode);
+			p += c->nnode_sz;
+			len += c->nnode_sz;
+		}
+		/* Row zero  is the top row */
+		if (row == 0)
+			break;
+		/* Update the information about the level below */
+		bcnt = cnt;
+		bsz = c->nnode_sz;
+		row -= 1;
+	}
+
+	if (c->big_lpt) {
+		/* Need to add LPT's save table */
+		if (len + c->lsave_sz > c->leb_size) {
+			alen = ALIGN(len, c->min_io_size);
+			set_ltab(c, lnum, c->leb_size - alen, alen - len);
+			memset(p, 0xff, alen - len);
+			err = write_leb(c, lnum++, alen, buf);
+			if (err)
+				goto out;
+			p = buf;
+			len = 0;
+		}
+
+		c->lsave_lnum = lnum;
+		c->lsave_offs = len;
+
+		for (i = 0; i < c->lsave_cnt; i++)
+			lsave[i] = c->main_first + i;
+
+		pack_lsave(c, p, lsave);
+		p += c->lsave_sz;
+		len += c->lsave_sz;
+	}
+
+	/* Need to add LPT's own LEB properties table */
+	if (len + c->ltab_sz > c->leb_size) {
+		alen = ALIGN(len, c->min_io_size);
+		set_ltab(c, lnum, c->leb_size - alen, alen - len);
+		memset(p, 0xff, alen - len);
+		err = write_leb(c, lnum++, alen, buf);
+		if (err)
+			goto out;
+		p = buf;
+		len = 0;
+	}
+
+	c->ltab_lnum = lnum;
+	c->ltab_offs = len;
+
+	/* Update ltab before packing it */
+	len += c->ltab_sz;
+	alen = ALIGN(len, c->min_io_size);
+	set_ltab(c, lnum, c->leb_size - alen, alen - len);
+
+	pack_ltab(c, p, c->ltab);
+	p += c->ltab_sz;
+
+	/* Write remaining buffer */
+	memset(p, 0xff, alen - len);
+	err = write_leb(c, lnum, alen, buf);
+	if (err)
+		goto out;
+
+	c->nhead_lnum = lnum;
+	c->nhead_offs = ALIGN(len, c->min_io_size);
+
+	dbg_msg(1, "lpt_sz:         %lld", c->lpt_sz);
+	dbg_msg(1, "space_bits:     %d", c->space_bits);
+	dbg_msg(1, "lpt_lnum_bits:  %d", c->lpt_lnum_bits);
+	dbg_msg(1, "lpt_offs_bits:  %d", c->lpt_offs_bits);
+	dbg_msg(1, "lpt_spc_bits:   %d", c->lpt_spc_bits);
+	dbg_msg(1, "pcnt_bits:      %d", c->pcnt_bits);
+	dbg_msg(1, "lnum_bits:      %d", c->lnum_bits);
+	dbg_msg(1, "pnode_sz:       %d", c->pnode_sz);
+	dbg_msg(1, "nnode_sz:       %d", c->nnode_sz);
+	dbg_msg(1, "ltab_sz:        %d", c->ltab_sz);
+	dbg_msg(1, "lsave_sz:       %d", c->lsave_sz);
+	dbg_msg(1, "lsave_cnt:      %d", c->lsave_cnt);
+	dbg_msg(1, "lpt_hght:       %d", c->lpt_hght);
+	dbg_msg(1, "big_lpt:        %d", c->big_lpt);
+	dbg_msg(1, "LPT root is at  %d:%d", c->lpt_lnum, c->lpt_offs);
+	dbg_msg(1, "LPT head is at  %d:%d", c->nhead_lnum, c->nhead_offs);
+	dbg_msg(1, "LPT ltab is at  %d:%d", c->ltab_lnum, c->ltab_offs);
+	if (c->big_lpt)
+		dbg_msg(1, "LPT lsave is at %d:%d",
+		        c->lsave_lnum, c->lsave_offs);
+out:
+	free(lsave);
+	free(buf);
+	free(nnode);
+	free(pnode);
+	return err;
+}
diff --git a/ubifs-utils/mkfs.ubifs/COPYING b/ubifs-utils/mkfs.ubifs/COPYING
deleted file mode 100644
index 60549be..0000000
--- a/ubifs-utils/mkfs.ubifs/COPYING
+++ /dev/null
@@ -1,340 +0,0 @@
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-\f

-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-\f

-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-\f

-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-\f

-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-\f

-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) 19yy  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) 19yy name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/ubifs-utils/mkfs.ubifs/README b/ubifs-utils/mkfs.ubifs/README
deleted file mode 100644
index 7e19939..0000000
--- a/ubifs-utils/mkfs.ubifs/README
+++ /dev/null
@@ -1,9 +0,0 @@
-UBIFS File System - Make File System program
-
-* crc16.h and crc16.c were copied from the linux kernel.
-* crc32.h and crc32.c were copied from mtd-utils and amended.
-* ubifs.h is a selection of definitions from fs/ubifs/ubifs.h from the linux kernel.
-* key.h is copied from fs/ubifs/key.h from the linux kernel.
-* defs.h is a bunch of definitions to smooth things over.
-* lpt.c is a selection of functions copied from fs/ubifs/lpt.c from the linux kernel, and amended.
-* hashtable/* was downloaded from http://www.cl.cam.ac.uk/~cwc22/hashtable/
diff --git a/ubifs-utils/mkfs.ubifs/compr.c b/ubifs-utils/mkfs.ubifs/compr.c
deleted file mode 100644
index 54604d4..0000000
--- a/ubifs-utils/mkfs.ubifs/compr.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2008 Nokia Corporation.
- * Copyright (C) 2008 University of Szeged, Hungary
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Authors: Artem Bityutskiy
- *          Adrian Hunter
- *          Zoltan Sogor
- */
-
-#include "ubifs_common.h"
-#ifndef WITHOUT_LZO
-#include <lzo/lzo1x.h>
-#endif
-
-#define crc32 __zlib_crc32
-#include <zlib.h>
-#undef crc32
-
-#include "compr.h"
-
-static void *lzo_mem;
-static unsigned long long errcnt = 0;
-
-#define DEFLATE_DEF_LEVEL     Z_DEFAULT_COMPRESSION
-#define DEFLATE_DEF_WINBITS   11
-#define DEFLATE_DEF_MEMLEVEL  8
-
-static int zlib_deflate(void *in_buf, size_t in_len, void *out_buf,
-			size_t *out_len)
-{
-	z_stream strm;
-
-	strm.zalloc = NULL;
-	strm.zfree = NULL;
-
-	/*
-	 * Match exactly the zlib parameters used by the Linux kernel crypto
-	 * API.
-	 */
-        if (deflateInit2(&strm, DEFLATE_DEF_LEVEL, Z_DEFLATED,
-			 -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
-			 Z_DEFAULT_STRATEGY)) {
-		errcnt += 1;
-		return -1;
-	}
-
-	strm.next_in = in_buf;
-	strm.avail_in = in_len;
-	strm.total_in = 0;
-
-	strm.next_out = out_buf;
-	strm.avail_out = *out_len;
-	strm.total_out = 0;
-
-	if (deflate(&strm, Z_FINISH) != Z_STREAM_END) {
-		deflateEnd(&strm);
-		errcnt += 1;
-		return -1;
-	}
-
-	if (deflateEnd(&strm) != Z_OK) {
-		errcnt += 1;
-		return -1;
-	}
-
-	*out_len = strm.total_out;
-
-	return 0;
-}
-
-#ifndef WITHOUT_LZO
-static int lzo_compress(void *in_buf, size_t in_len, void *out_buf,
-			size_t *out_len)
-{
-	lzo_uint len;
-	int ret;
-
-	len = *out_len;
-	ret = lzo1x_999_compress(in_buf, in_len, out_buf, &len, lzo_mem);
-	*out_len = len;
-
-	if (ret != LZO_E_OK) {
-		errcnt += 1;
-		return -1;
-	}
-
-	return 0;
-}
-#endif
-
-static int no_compress(void *in_buf, size_t in_len, void *out_buf,
-		       size_t *out_len)
-{
-	memcpy(out_buf, in_buf, in_len);
-	*out_len = in_len;
-	return 0;
-}
-
-static char *zlib_buf;
-
-#ifndef WITHOUT_LZO
-static int favor_lzo_compress(void *in_buf, size_t in_len, void *out_buf,
-				size_t *out_len, int *type, int lzo_percent)
-{
-	int lzo_ret, zlib_ret;
-	size_t lzo_len, zlib_len;
-
-	lzo_len = zlib_len = *out_len;
-	lzo_ret = lzo_compress(in_buf, in_len, out_buf, &lzo_len);
-	zlib_ret = zlib_deflate(in_buf, in_len, zlib_buf, &zlib_len);
-
-	if (lzo_ret && zlib_ret)
-		/* Both compressors failed */
-		return -1;
-
-	if (!lzo_ret && !zlib_ret) {
-		double percent;
-
-		/* Both compressors succeeded */
-		if (lzo_len <= zlib_len )
-			goto select_lzo;
-
-		percent = (double)zlib_len / (double)lzo_len;
-		percent *= 100;
-		if (percent > 100 - lzo_percent)
-			goto select_lzo;
-		goto select_zlib;
-	}
-
-	if (lzo_ret)
-		/* Only zlib compressor succeeded */
-		goto select_zlib;
-
-	/* Only LZO compressor succeeded */
-
-select_lzo:
-	*out_len = lzo_len;
-	*type = MKFS_UBIFS_COMPR_LZO;
-	return 0;
-
-select_zlib:
-	*out_len = zlib_len;
-	*type = MKFS_UBIFS_COMPR_ZLIB;
-	memcpy(out_buf, zlib_buf, zlib_len);
-	return 0;
-}
-#endif
-
-int compress_data(void *in_buf, size_t in_len, void *out_buf,
-		size_t *out_len, int type, int lzo_percent)
-{
-	int ret;
-
-	if (in_len < UBIFS_MIN_COMPR_LEN) {
-		no_compress(in_buf, in_len, out_buf, out_len);
-		return MKFS_UBIFS_COMPR_NONE;
-	}
-
-#ifdef WITHOUT_LZO
-	{
-		switch (type) {
-#else
-	if (lzo_percent)
-		ret = favor_lzo_compress(in_buf, in_len, out_buf, out_len, &type, lzo_percent);
-	else {
-		switch (type) {
-		case MKFS_UBIFS_COMPR_LZO:
-			ret = lzo_compress(in_buf, in_len, out_buf, out_len);
-			break;
-#endif
-		case MKFS_UBIFS_COMPR_ZLIB:
-			ret = zlib_deflate(in_buf, in_len, out_buf, out_len);
-			break;
-		case MKFS_UBIFS_COMPR_NONE:
-			ret = 1;
-			break;
-		default:
-			errcnt += 1;
-			ret = 1;
-			break;
-		}
-	}
-	if (ret || *out_len >= in_len) {
-		no_compress(in_buf, in_len, out_buf, out_len);
-		return MKFS_UBIFS_COMPR_NONE;
-	}
-	return type;
-}
-
-int init_compression(void)
-{
-#ifdef WITHOUT_LZO
-	lzo_mem = NULL;
-#else
-	lzo_mem = malloc(LZO1X_999_MEM_COMPRESS);
-	if (!lzo_mem)
-		return -1;
-#endif
-
-	zlib_buf = malloc(UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR);
-	if (!zlib_buf) {
-		free(lzo_mem);
-		return -1;
-	}
-
-	return 0;
-}
-
-void destroy_compression(void)
-{
-	free(zlib_buf);
-	free(lzo_mem);
-	if (errcnt)
-		fprintf(stderr, "%llu compression errors occurred\n", errcnt);
-}
diff --git a/ubifs-utils/mkfs.ubifs/compr.h b/ubifs-utils/mkfs.ubifs/compr.h
deleted file mode 100644
index d44a2ba..0000000
--- a/ubifs-utils/mkfs.ubifs/compr.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2008 Nokia Corporation.
- * Copyright (C) 2008 University of Szeged, Hungary
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Authors: Artem Bityutskiy
- *          Adrian Hunter
- *          Zoltan Sogor
- */
-
-#ifndef __UBIFS_COMPRESS_H__
-#define __UBIFS_COMPRESS_H__
-
-/*
- * Compressors may end-up with more data in the output buffer than in the input
- * buffer. This constant defined the worst case factor, i.e. we assume that the
- * output buffer may be at max. WORST_COMPR_FACTOR times larger than input
- * buffer.
- */
-#define WORST_COMPR_FACTOR 4
-
-enum compression_type
-{
-	MKFS_UBIFS_COMPR_NONE,
-	MKFS_UBIFS_COMPR_LZO,
-	MKFS_UBIFS_COMPR_ZLIB,
-};
-
-int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len, int type, int lzo_percent);
-int init_compression(void);
-void destroy_compression(void);
-
-#endif
diff --git a/ubifs-utils/mkfs.ubifs/crc16.c b/ubifs-utils/mkfs.ubifs/crc16.c
deleted file mode 100644
index a19512e..0000000
--- a/ubifs-utils/mkfs.ubifs/crc16.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * This code was taken from the linux kernel. The license is GPL Version 2.
- */
-
-#include "crc16.h"
-
-/** CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */
-uint16_t const crc16_table[256] = {
-	0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
-	0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
-	0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
-	0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
-	0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
-	0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
-	0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
-	0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
-	0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
-	0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
-	0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
-	0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
-	0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
-	0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
-	0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
-	0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
-	0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
-	0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
-	0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
-	0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
-	0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
-	0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
-	0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
-	0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
-	0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
-	0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
-	0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
-	0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
-	0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
-	0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
-	0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
-	0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
-};
-
-/**
- * crc16 - compute the CRC-16 for the data buffer
- * @crc:	previous CRC value
- * @buffer:	data pointer
- * @len:	number of bytes in the buffer
- *
- * Returns the updated CRC value.
- */
-uint16_t crc16(uint16_t crc, uint8_t const *buffer, size_t len)
-{
-	while (len--)
-		crc = crc16_byte(crc, *buffer++);
-	return crc;
-}
diff --git a/ubifs-utils/mkfs.ubifs/crc16.h b/ubifs-utils/mkfs.ubifs/crc16.h
deleted file mode 100644
index 539d21a..0000000
--- a/ubifs-utils/mkfs.ubifs/crc16.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Implements the standard CRC-16:
- *   Width 16
- *   Poly  0x8005 (x^16 + x^15 + x^2 + 1)
- *   Init  0
- *
- * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
- *
- * This code was taken from the linux kernel. The license is GPL Version 2.
- */
-
-#ifndef __CRC16_H__
-#define __CRC16_H__
-
-#include <stdlib.h>
-#include <stdint.h>
-
-extern uint16_t const crc16_table[256];
-
-extern uint16_t crc16(uint16_t crc, const uint8_t *buffer, size_t len);
-
-static inline uint16_t crc16_byte(uint16_t crc, const uint8_t data)
-{
-	return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff];
-}
-
-#endif /* __CRC16_H__ */
diff --git a/ubifs-utils/mkfs.ubifs/defs.h b/ubifs-utils/mkfs.ubifs/defs.h
deleted file mode 100644
index 1fa3316..0000000
--- a/ubifs-utils/mkfs.ubifs/defs.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Greate deal of the code was taken from the kernel UBIFS implementation, and
- * this file contains some "glue" definitions.
- */
-
-#ifndef __UBIFS_DEFS_H__
-#define __UBIFS_DEFS_H__
-
-#define t16(x) ({ \
-	uint16_t __b = (x); \
-	(__LITTLE_ENDIAN==__BYTE_ORDER) ? __b : bswap_16(__b); \
-})
-
-#define t32(x) ({ \
-	uint32_t __b = (x); \
-	(__LITTLE_ENDIAN==__BYTE_ORDER) ? __b : bswap_32(__b); \
-})
-
-#define t64(x) ({ \
-	uint64_t __b = (x); \
-	(__LITTLE_ENDIAN==__BYTE_ORDER) ? __b : bswap_64(__b); \
-})
-
-#define cpu_to_le16(x) ((__le16){t16(x)})
-#define cpu_to_le32(x) ((__le32){t32(x)})
-#define cpu_to_le64(x) ((__le64){t64(x)})
-
-#define le16_to_cpu(x) (t16((x)))
-#define le32_to_cpu(x) (t32((x)))
-#define le64_to_cpu(x) (t64((x)))
-
-#define unlikely(x) (x)
-
-#define ubifs_assert(x) ({})
-
-struct qstr
-{
-	char *name;
-	size_t len;
-};
-
-/**
- * fls - find last (most-significant) bit set
- * @x: the word to search
- *
- * This is defined the same way as ffs.
- * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
- */
-static inline int fls(int x)
-{
-	int r = 32;
-
-	if (!x)
-		return 0;
-	if (!(x & 0xffff0000u)) {
-		x <<= 16;
-		r -= 16;
-	}
-	if (!(x & 0xff000000u)) {
-		x <<= 8;
-		r -= 8;
-	}
-	if (!(x & 0xf0000000u)) {
-		x <<= 4;
-		r -= 4;
-	}
-	if (!(x & 0xc0000000u)) {
-		x <<= 2;
-		r -= 2;
-	}
-	if (!(x & 0x80000000u)) {
-		x <<= 1;
-		r -= 1;
-	}
-	return r;
-}
-
-#define do_div(n,base) ({ \
-int __res; \
-__res = ((unsigned long) n) % (unsigned) base; \
-n = ((unsigned long) n) / (unsigned) base; \
-__res; })
-
-#if INT_MAX != 0x7fffffff
-#error : sizeof(int) must be 4 for this program
-#endif
-
-#if (~0ULL) != 0xffffffffffffffffULL
-#error : sizeof(long long) must be 8 for this program
-#endif
-
-#endif
diff --git a/ubifs-utils/mkfs.ubifs/devtable.c b/ubifs-utils/mkfs.ubifs/devtable.c
deleted file mode 100644
index 1fc0256..0000000
--- a/ubifs-utils/mkfs.ubifs/devtable.c
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
- * Copyright (C) 2008 Nokia Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: Artem Bityutskiy
- *
- * Part of the device table parsing code was taken from the mkfs.jffs2 utility.
- * The original author of that code is Erik Andersen, hence:
- *	Copyright (C) 2001, 2002 Erik Andersen <andersen@codepoet.org>
- */
-
-/*
- * This file implemented device table support. Device table entries take the
- * form of:
- * <path>    <type> <mode> <uid> <gid> <major> <minor> <start>	<inc> <count>
- * /dev/mem  c       640   0     0     1       1       0        0     -
- *
- * Type can be one of:
- * f  A regular file
- * d  Directory
- * c  Character special device file
- * b  Block special device file
- * p  Fifo (named pipe)
- *
- * Don't bother with symlinks (permissions are irrelevant), hard links (special
- * cases of regular files), or sockets (why bother).
- *
- * Regular files must exist in the target root directory. If a char, block,
- * fifo, or directory does not exist, it will be created.
- *
- * Please, refer the device_table.txt file which can be found at MTD utilities
- * for more information about what the device table is.
- */
-
-#include "ubifs_common.h"
-#include "devtable.h"
-#include "hashtable/hashtable.h"
-#include "hashtable/hashtable_itr.h"
-
-/*
- * The hash table which contains paths to files/directories/device nodes
- * referred to in the device table. For example, if the device table refers
- * "/dev/loop0", the @path_htbl will contain "/dev" element.
- */
-static struct hashtable *path_htbl;
-
-/* Hash function used for hash tables */
-static unsigned int r5_hash(void *s)
-{
-	unsigned int a = 0;
-	const signed char *str = s;
-
-	while (*str) {
-		a += *str << 4;
-		a += *str >> 4;
-		a *= 11;
-		str++;
-	}
-
-	return a;
-}
-
-/*
- * Check whether 2 keys of a hash table are equivalent. The keys are path/file
- * names, so we simply use 'strcmp()'.
- */
-static int is_equivalent(void *k1, void *k2)
-{
-	return !strcmp(k1, k2);
-}
-
-/**
- * separate_last - separate out the last path component
- * @buf: the path to split
- * @len: length of the @buf string
- * @path: the beginning of path is returned here
- * @name: the last path component is returned here
- *
- * This helper function separates out the the last component of the full path
- * string. For example, "/dev/loop" would be split on "/dev" and "loop". This
- * function allocates memory for @path and @name and return the result there.
- * Returns zero in case of success and a negative error code in case of
- * failure.
- */
-static int separate_last(const char *buf, int len, char **path, char **name)
-{
-	int path_len = len, name_len;
-	const char *p = buf + len, *n;
-
-	while (*--p != '/')
-		path_len -= 1;
-
-	/* Drop the final '/' unless this is the root directory */
-	name_len = len - path_len;
-	n = buf + path_len;
-	if (path_len > 1)
-		path_len -= 1;
-
-	*path = malloc(path_len + 1);
-	if (!*path)
-		return err_msg("cannot allocate %d bytes of memory",
-			       path_len + 1);
-	memcpy(*path, buf, path_len);
-	(*path)[path_len] = '\0';
-
-	*name = malloc(name_len + 1);
-	if (!*name) {
-		free(*path);
-		return err_msg("cannot allocate %d bytes of memory",
-			       name_len + 1);
-	}
-	memcpy(*name, n, name_len + 1);
-
-	return 0;
-}
-
-static int interpret_table_entry(const char *line)
-{
-	char buf[1024], type, *path = NULL, *name = NULL;
-	int len;
-	struct path_htbl_element *ph_elt = NULL;
-	struct name_htbl_element *nh_elt = NULL;
-	unsigned int mode = 0755, uid = 0, gid = 0, major = 0, minor = 0;
-	unsigned int start = 0, increment = 0, count = 0;
-
-	if (sscanf(line, "%1023s %c %o %u %u %u %u %u %u %u",
-		   buf, &type, &mode, &uid, &gid, &major, &minor,
-		   &start, &increment, &count) < 0)
-		return sys_err_msg("sscanf failed");
-
-	dbg_msg(3, "name %s, type %c, mode %o, uid %u, gid %u, major %u, "
-		"minor %u, start %u, inc %u, cnt %u",
-		buf, type, mode, uid, gid, major, minor, start,
-		increment, count);
-
-	len = strnlen(buf, 1024);
-	if (len == 1024)
-		return err_msg("too long path");
-
-	if (!strcmp(buf, "/"))
-		return err_msg("device table entries require absolute paths");
-	if (buf[1] == '\0')
-		return err_msg("root directory cannot be created");
-	if (strstr(buf, "//"))
-		return err_msg("'//' cannot be used in the path");
-	if (buf[len - 1] == '/')
-		return err_msg("do not put '/' at the end");
-
-	if (strstr(buf, "/./") || strstr(buf, "/../") ||
-	    !strcmp(buf + len - 2, "/.") || !strcmp(buf + len - 3, "/.."))
-		return err_msg("'.' and '..' cannot be used in the path");
-
-	switch (type) {
-		case 'd':
-			mode |= S_IFDIR;
-			break;
-		case 'f':
-			mode |= S_IFREG;
-			break;
-		case 'p':
-			mode |= S_IFIFO;
-			break;
-		case 'c':
-			mode |= S_IFCHR;
-			break;
-		case 'b':
-			mode |= S_IFBLK;
-			break;
-		default:
-			return err_msg("unsupported file type '%c'", type);
-	}
-
-	if (separate_last(buf, len, &path, &name))
-		return -1;
-
-	/*
-	 * Check if this path already exist in the path hash table and add it
-	 * if it is not.
-	 */
-	ph_elt = hashtable_search(path_htbl, path);
-	if (!ph_elt) {
-		dbg_msg(3, "inserting '%s' into path hash table", path);
-		ph_elt = malloc(sizeof(struct path_htbl_element));
-		if (!ph_elt) {
-			err_msg("cannot allocate %zd bytes of memory",
-				sizeof(struct path_htbl_element));
-			goto out_free;
-		}
-
-		if (!hashtable_insert(path_htbl, path, ph_elt)) {
-			err_msg("cannot insert into path hash table");
-			goto out_free;
-		}
-
-		ph_elt->path = path;
-		path = NULL;
-		ph_elt->name_htbl = create_hashtable(128, &r5_hash,
-						     &is_equivalent);
-		if (!ph_elt->name_htbl) {
-			err_msg("cannot create name hash table");
-			goto out_free;
-		}
-	}
-
-	if (increment != 0 && count == 0)
-		return err_msg("count cannot be zero if increment is non-zero");
-
-	/*
-	 * Add the file/directory/device node (last component of the path) to
-	 * the name hashtable. The name hashtable resides in the corresponding
-	 * path hashtable element.
-	 */
-
-	if (count == 0) {
-		/* This entry does not require any iterating */
-		nh_elt = malloc(sizeof(struct name_htbl_element));
-		if (!nh_elt) {
-			err_msg("cannot allocate %zd bytes of memory",
-				sizeof(struct name_htbl_element));
-			goto out_free;
-		}
-
-		nh_elt->mode = mode;
-		nh_elt->uid = uid;
-		nh_elt->gid = gid;
-		nh_elt->dev = makedev(major, minor);
-
-		dbg_msg(3, "inserting '%s' into name hash table (major %d, minor %d)",
-			name, major(nh_elt->dev), minor(nh_elt->dev));
-
-		if (hashtable_search(ph_elt->name_htbl, name))
-			return err_msg("'%s' is referred twice", buf);
-
-		nh_elt->name = name;
-		if (!hashtable_insert(ph_elt->name_htbl, name, nh_elt)) {
-			err_msg("cannot insert into name hash table");
-			goto out_free;
-		}
-	} else {
-		int i, num = start + count, len = strlen(name) + 20;
-		char *nm;
-
-		for (i = start; i < num; i++) {
-			nh_elt = malloc(sizeof(struct name_htbl_element));
-			if (!nh_elt) {
-				err_msg("cannot allocate %zd bytes of memory",
-					sizeof(struct name_htbl_element));
-				goto out_free;
-			}
-
-			nh_elt->mode = mode;
-			nh_elt->uid = uid;
-			nh_elt->gid = gid;
-			nh_elt->dev = makedev(major, minor + (i - start) * increment);
-
-			nm = malloc(len);
-			if (!nm) {
-				err_msg("cannot allocate %d bytes of memory", len);
-				goto out_free;
-			}
-
-			sprintf(nm, "%s%d", name, i);
-			nh_elt->name = nm;
-
-			dbg_msg(3, "inserting '%s' into name hash table (major %d, minor %d)",
-			        nm, major(nh_elt->dev), minor(nh_elt->dev));
-
-			if (hashtable_search(ph_elt->name_htbl, nm)) {
-				err_msg("'%s' is referred twice", buf);
-				free (nm);
-				goto out_free;
-			}
-
-			if (!hashtable_insert(ph_elt->name_htbl, nm, nh_elt)) {
-				err_msg("cannot insert into name hash table");
-				free (nm);
-				goto out_free;
-			}
-		}
-		free(name);
-		name = NULL;
-	}
-
-	return 0;
-
-out_free:
-	free(ph_elt);
-	free(nh_elt);
-	free(path);
-	free(name);
-	return -1;
-}
-
-/**
- * parse_devtable - parse the device table.
- * @tbl_file: device table file name
- *
- * This function parses the device table and prepare the hash table which will
- * later be used by mkfs.ubifs to create the specified files/device nodes.
- * Returns zero in case of success and a negative error code in case of
- * failure.
- */
-int parse_devtable(const char *tbl_file)
-{
-	FILE *f;
-	char *line = NULL;
-	struct stat st;
-	size_t len;
-
-	dbg_msg(1, "parsing device table file '%s'", tbl_file);
-
-	path_htbl = create_hashtable(128, &r5_hash, &is_equivalent);
-	if (!path_htbl)
-		return err_msg("cannot create path hash table");
-
-	f = fopen(tbl_file, "r");
-	if (!f)
-		return sys_err_msg("cannot open '%s'", tbl_file);
-
-	if (fstat(fileno(f), &st) < 0) {
-		sys_err_msg("cannot stat '%s'", tbl_file);
-		goto out_close;
-	}
-
-	if (st.st_size < 10) {
-		sys_err_msg("'%s' is too short", tbl_file);
-		goto out_close;
-	}
-
-	/*
-	 * The general plan now is to read in one line at a time, check for
-	 * leading comment delimiters ('#'), then try and parse the line as a
-	 * device table
-	 */
-	while (getline(&line, &len, f) != -1) {
-		/* First trim off any white-space */
-		len = strlen(line);
-
-		/* Trim trailing white-space */
-		while (len > 0 && isspace(line[len - 1]))
-			line[--len] = '\0';
-		/* Trim leading white-space */
-		memmove(line, &line[strspn(line, " \n\r\t\v")], len);
-
-		/* How long are we after trimming? */
-		len = strlen(line);
-
-		/* If this is not a comment line, try to interpret it */
-		if (len && *line != '#') {
-			if (interpret_table_entry(line)) {
-				err_msg("cannot parse '%s'", line);
-				goto out_close;
-			}
-		}
-
-		free(line);
-		line = NULL;
-	}
-
-	dbg_msg(1, "finished parsing");
-	fclose(f);
-	return 0;
-
-out_close:
-	fclose(f);
-	free_devtable_info();
-	return -1;
-}
-
-/**
- * devtbl_find_path - find a path in the path hash table.
- * @path: UBIFS path to find.
- *
- * This looks up the path hash table. Returns the path hash table element
- * reference if @path was found and %NULL if not.
- */
-struct path_htbl_element *devtbl_find_path(const char *path)
-{
-	if (!path_htbl)
-		return NULL;
-
-	return hashtable_search(path_htbl, (void *)path);
-}
-
-/**
- * devtbl_find_name - find a name in the name hash table.
- * @ph_etl: path hash table element to find at
- * @name: name to find
- *
- * This looks up the name hash table. Returns the name hash table element
- * reference if @name found and %NULL if not.
- */
-struct name_htbl_element *devtbl_find_name(struct path_htbl_element *ph_elt,
-					   const char *name)
-{
-	if (!path_htbl)
-		return NULL;
-
-	return hashtable_search(ph_elt->name_htbl, (void *)name);
-}
-
-/**
- * override_attributes - override inode attributes.
- * @st: struct stat object to containing the attributes to override
- * @ph_elt: path hash table element object
- * @nh_elt: name hash table element object containing the new values
- *
- * The device table file may override attributes like UID of files. For
- * example, the device table may contain a "/dev" entry, and the UBIFS FS on
- * the host may contain "/dev" directory. In this case the attributes of the
- * "/dev" directory inode has to be as the device table specifies.
- *
- * Note, the hash element is removed by this function as well.
- */
-int override_attributes(struct stat *st, struct path_htbl_element *ph_elt,
-			struct name_htbl_element *nh_elt)
-{
-	if (!path_htbl)
-		return 0;
-
-	if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode) ||
-	    S_ISFIFO(st->st_mode))
-		return err_msg("%s/%s both exists at UBIFS root at host, "
-			       "and is referred from the device table",
-			       strcmp(ph_elt->path, "/") ? ph_elt->path : "",
-			       nh_elt->name);
-
-	if ((st->st_mode & S_IFMT) != (nh_elt->mode & S_IFMT))
-		return err_msg("%s/%s is referred from the device table also exists in "
-			       "the UBIFS root directory at host, but the file type is "
-			       "different", strcmp(ph_elt->path, "/") ? ph_elt->path : "",
-			       nh_elt->name);
-
-	dbg_msg(3, "set UID %d, GID %d, mode %o for %s/%s as device table says",
-		nh_elt->uid, nh_elt->gid, nh_elt->mode, ph_elt->path, nh_elt->name);
-
-	st->st_uid = nh_elt->uid;
-	st->st_gid = nh_elt->gid;
-	st->st_mode = nh_elt->mode;
-
-	hashtable_remove(ph_elt->name_htbl, (void *)nh_elt->name);
-	return 0;
-}
-
-/**
- * first_name_htbl_element - return first element of the name hash table.
- * @ph_elt: the path hash table the name hash table belongs to
- * @itr: double pointer to a 'struct hashtable_itr' object where the
- *       information about further iterations is stored
- *
- * This function implements name hash table iteration together with
- * 'next_name_htbl_element()'. Returns the first name hash table element or
- * %NULL if the hash table is empty.
- */
-struct name_htbl_element *
-first_name_htbl_element(struct path_htbl_element *ph_elt,
-			struct hashtable_itr **itr)
-{
-	if (!path_htbl || !ph_elt || hashtable_count(ph_elt->name_htbl) == 0)
-		return NULL;
-
-	*itr = hashtable_iterator(ph_elt->name_htbl);
-	return hashtable_iterator_value(*itr);
-}
-
-/**
- * first_name_htbl_element - return next element of the name hash table.
- * @ph_elt: the path hash table the name hash table belongs to
- * @itr: double pointer to a 'struct hashtable_itr' object where the
- *       information about further iterations is stored
- *
- * This function implements name hash table iteration together with
- * 'first_name_htbl_element()'. Returns the next name hash table element or
- * %NULL if there are no more elements.
- */
-struct name_htbl_element *
-next_name_htbl_element(struct path_htbl_element *ph_elt,
-		       struct hashtable_itr **itr)
-{
-	if (!path_htbl || !ph_elt || !hashtable_iterator_advance(*itr))
-		return NULL;
-
-	return hashtable_iterator_value(*itr);
-}
-
-/**
- * free_devtable_info - free device table information.
- *
- * This function frees the path hash table and the name hash tables.
- */
-void free_devtable_info(void)
-{
-	struct hashtable_itr *ph_itr;
-	struct path_htbl_element *ph_elt;
-
-	if (!path_htbl)
-		return;
-
-	if (hashtable_count(path_htbl) > 0) {
-		ph_itr = hashtable_iterator(path_htbl);
-		do {
-			ph_elt = hashtable_iterator_value(ph_itr);
-			/*
-			 * Note, since we use the same string for the key and
-			 * @name in the name hash table elements, we do not
-			 * have to iterate name hash table because @name memory
-			 * will be freed when freeing the key.
-			 */
-			hashtable_destroy(ph_elt->name_htbl, 1);
-		} while (hashtable_iterator_advance(ph_itr));
-	}
-	hashtable_destroy(path_htbl, 1);
-}
diff --git a/ubifs-utils/mkfs.ubifs/devtable.h b/ubifs-utils/mkfs.ubifs/devtable.h
deleted file mode 100644
index 987d4d4..0000000
--- a/ubifs-utils/mkfs.ubifs/devtable.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#include "ubifs_common.h"
-
-/**
- * struct path_htbl_element - an element of the path hash table.
- * @path: the UBIFS path the element describes (the key of the element)
- * @name_htbl: one more (nested) hash table containing names of all
- *             files/directories/device nodes which should be created at this
- *             path
- *
- * See device table handling for more information.
- */
-struct path_htbl_element {
-	const char *path;
-	struct hashtable *name_htbl;
-};
-
-/**
- * struct name_htbl_element - an element in the name hash table
- * @name: name of the file/directory/device node (the key of the element)
- * @mode: accsess rights and file type
- * @uid: user ID
- * @gid: group ID
- * @major: device node major number
- * @minor: device node minor number
- *
- * This is an element of the name hash table. Name hash table sits in the path
- * hash table elements and describes file names which should be created/changed
- * at this path.
- */
-struct name_htbl_element {
-	const char *name;
-	unsigned int mode;
-	unsigned int uid;
-	unsigned int gid;
-	dev_t dev;
-};
-
-extern struct ubifs_info info_;
-
-struct hashtable_itr;
-
-int parse_devtable(const char *tbl_file);
-struct path_htbl_element *devtbl_find_path(const char *path);
-struct name_htbl_element *devtbl_find_name(struct path_htbl_element *ph_elt,
-					   const char *name);
-int override_attributes(struct stat *st, struct path_htbl_element *ph_elt,
-			struct name_htbl_element *nh_elt);
-struct name_htbl_element *
-first_name_htbl_element(struct path_htbl_element *ph_elt,
-			struct hashtable_itr **itr);
-struct name_htbl_element *
-next_name_htbl_element(struct path_htbl_element *ph_elt,
-			struct hashtable_itr **itr);
-void free_devtable_info(void);
-
diff --git a/ubifs-utils/mkfs.ubifs/hashtable/hashtable.c b/ubifs-utils/mkfs.ubifs/hashtable/hashtable.c
deleted file mode 100644
index c1f99ed..0000000
--- a/ubifs-utils/mkfs.ubifs/hashtable/hashtable.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/* Copyright (C) 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
-
-#define PROGRAM_NAME "hashtable"
-
-#include "common.h"
-#include "hashtable.h"
-#include "hashtable_private.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-
-/*
-Credit for primes table: Aaron Krowne
- http://br.endernet.org/~akrowne/
- http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
-*/
-static const unsigned int primes[] = {
-53, 97, 193, 389,
-769, 1543, 3079, 6151,
-12289, 24593, 49157, 98317,
-196613, 393241, 786433, 1572869,
-3145739, 6291469, 12582917, 25165843,
-50331653, 100663319, 201326611, 402653189,
-805306457, 1610612741
-};
-const unsigned int prime_table_length = ARRAY_SIZE(primes);
-const float max_load_factor = 0.65;
-
-/*****************************************************************************/
-struct hashtable *
-create_hashtable(unsigned int minsize,
-                 unsigned int (*hashf) (void*),
-                 int (*eqf) (void*,void*))
-{
-    struct hashtable *h;
-    unsigned int pindex, size = primes[0];
-    /* Check requested hashtable isn't too large */
-    if (minsize > (1u << 30)) return NULL;
-    /* Enforce size as prime */
-    for (pindex=0; pindex < prime_table_length; pindex++) {
-        if (primes[pindex] > minsize) { size = primes[pindex]; break; }
-    }
-    h = (struct hashtable *)malloc(sizeof(struct hashtable));
-    if (NULL == h) return NULL; /*oom*/
-    h->table = (struct entry **)malloc(sizeof(struct entry*) * size);
-    if (NULL == h->table) { free(h); return NULL; } /*oom*/
-    memset(h->table, 0, size * sizeof(struct entry *));
-    h->tablelength  = size;
-    h->primeindex   = pindex;
-    h->entrycount   = 0;
-    h->hashfn       = hashf;
-    h->eqfn         = eqf;
-    h->loadlimit    = (unsigned int) ceil(size * max_load_factor);
-    return h;
-}
-
-/*****************************************************************************/
-unsigned int
-hash(struct hashtable *h, void *k)
-{
-    /* Aim to protect against poor hash functions by adding logic here
-     * - logic taken from java 1.4 hashtable source */
-    unsigned int i = h->hashfn(k);
-    i += ~(i << 9);
-    i ^=  ((i >> 14) | (i << 18)); /* >>> */
-    i +=  (i << 4);
-    i ^=  ((i >> 10) | (i << 22)); /* >>> */
-    return i;
-}
-
-/*****************************************************************************/
-static int
-hashtable_expand(struct hashtable *h)
-{
-    /* Double the size of the table to accomodate more entries */
-    struct entry **newtable;
-    struct entry *e;
-    struct entry **pE;
-    unsigned int newsize, i, index;
-    /* Check we're not hitting max capacity */
-    if (h->primeindex == (prime_table_length - 1)) return 0;
-    newsize = primes[++(h->primeindex)];
-
-    newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize);
-    if (NULL != newtable)
-    {
-        memset(newtable, 0, newsize * sizeof(struct entry *));
-        /* This algorithm is not 'stable'. ie. it reverses the list
-         * when it transfers entries between the tables */
-        for (i = 0; i < h->tablelength; i++) {
-            while (NULL != (e = h->table[i])) {
-                h->table[i] = e->next;
-                index = indexFor(newsize,e->h);
-                e->next = newtable[index];
-                newtable[index] = e;
-            }
-        }
-        free(h->table);
-        h->table = newtable;
-    }
-    /* Plan B: realloc instead */
-    else
-    {
-        newtable = (struct entry **)
-                   realloc(h->table, newsize * sizeof(struct entry *));
-        if (NULL == newtable) { (h->primeindex)--; return 0; }
-        h->table = newtable;
-        memset(newtable[h->tablelength], 0, newsize - h->tablelength);
-        for (i = 0; i < h->tablelength; i++) {
-            for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
-                index = indexFor(newsize,e->h);
-                if (index == i)
-                {
-                    pE = &(e->next);
-                }
-                else
-                {
-                    *pE = e->next;
-                    e->next = newtable[index];
-                    newtable[index] = e;
-                }
-            }
-        }
-    }
-    h->tablelength = newsize;
-    h->loadlimit   = (unsigned int) ceil(newsize * max_load_factor);
-    return -1;
-}
-
-/*****************************************************************************/
-unsigned int
-hashtable_count(struct hashtable *h)
-{
-    return h->entrycount;
-}
-
-/*****************************************************************************/
-int
-hashtable_insert(struct hashtable *h, void *k, void *v)
-{
-    /* This method allows duplicate keys - but they shouldn't be used */
-    unsigned int index;
-    struct entry *e;
-    if (++(h->entrycount) > h->loadlimit)
-    {
-        /* Ignore the return value. If expand fails, we should
-         * still try cramming just this value into the existing table
-         * -- we may not have memory for a larger table, but one more
-         * element may be ok. Next time we insert, we'll try expanding again.*/
-        hashtable_expand(h);
-    }
-    e = (struct entry *)malloc(sizeof(struct entry));
-    if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
-    e->h = hash(h,k);
-    index = indexFor(h->tablelength,e->h);
-    e->k = k;
-    e->v = v;
-    e->next = h->table[index];
-    h->table[index] = e;
-    return -1;
-}
-
-/*****************************************************************************/
-void * /* returns value associated with key */
-hashtable_search(struct hashtable *h, void *k)
-{
-    struct entry *e;
-    unsigned int hashvalue, index;
-    hashvalue = hash(h,k);
-    index = indexFor(h->tablelength,hashvalue);
-    e = h->table[index];
-    while (NULL != e)
-    {
-        /* Check hash value to short circuit heavier comparison */
-        if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v;
-        e = e->next;
-    }
-    return NULL;
-}
-
-/*****************************************************************************/
-void * /* returns value associated with key */
-hashtable_remove(struct hashtable *h, void *k)
-{
-    /* TODO: consider compacting the table when the load factor drops enough,
-     *       or provide a 'compact' method. */
-
-    struct entry *e;
-    struct entry **pE;
-    void *v;
-    unsigned int hashvalue, index;
-
-    hashvalue = hash(h,k);
-    index = indexFor(h->tablelength,hash(h,k));
-    pE = &(h->table[index]);
-    e = *pE;
-    while (NULL != e)
-    {
-        /* Check hash value to short circuit heavier comparison */
-        if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
-        {
-            *pE = e->next;
-            h->entrycount--;
-            v = e->v;
-            freekey(e->k);
-            free(e);
-            return v;
-        }
-        pE = &(e->next);
-        e = e->next;
-    }
-    return NULL;
-}
-
-/*****************************************************************************/
-/* destroy */
-void
-hashtable_destroy(struct hashtable *h, int free_values)
-{
-    unsigned int i;
-    struct entry *e, *f;
-    struct entry **table = h->table;
-    if (free_values)
-    {
-        for (i = 0; i < h->tablelength; i++)
-        {
-            e = table[i];
-            while (NULL != e)
-            { f = e; e = e->next; freekey(f->k); free(f->v); free(f); }
-        }
-    }
-    else
-    {
-        for (i = 0; i < h->tablelength; i++)
-        {
-            e = table[i];
-            while (NULL != e)
-            { f = e; e = e->next; freekey(f->k); free(f); }
-        }
-    }
-    free(h->table);
-    free(h);
-}
-
-/*
- * Copyright (c) 2002, Christopher Clark
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of the original author; nor the names of any contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
diff --git a/ubifs-utils/mkfs.ubifs/hashtable/hashtable.h b/ubifs-utils/mkfs.ubifs/hashtable/hashtable.h
deleted file mode 100644
index c0b0acd..0000000
--- a/ubifs-utils/mkfs.ubifs/hashtable/hashtable.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/* Copyright (C) 2002 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
-
-#ifndef __HASHTABLE_CWC22_H__
-#define __HASHTABLE_CWC22_H__
-
-struct hashtable;
-
-/* Example of use:
- *
- *      struct hashtable  *h;
- *      struct some_key   *k;
- *      struct some_value *v;
- *
- *      static unsigned int         hash_from_key_fn( void *k );
- *      static int                  keys_equal_fn ( void *key1, void *key2 );
- *
- *      h = create_hashtable(16, hash_from_key_fn, keys_equal_fn);
- *      k = (struct some_key *)     malloc(sizeof(struct some_key));
- *      v = (struct some_value *)   malloc(sizeof(struct some_value));
- *
- *      (initialise k and v to suitable values)
- *
- *      if (! hashtable_insert(h,k,v) )
- *      {     exit(-1);               }
- *
- *      if (NULL == (found = hashtable_search(h,k) ))
- *      {    printf("not found!");                  }
- *
- *      if (NULL == (found = hashtable_remove(h,k) ))
- *      {    printf("Not found\n");                 }
- *
- */
-
-/* Macros may be used to define type-safe(r) hashtable access functions, with
- * methods specialized to take known key and value types as parameters.
- *
- * Example:
- *
- * Insert this at the start of your file:
- *
- * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value);
- * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value);
- * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value);
- *
- * This defines the functions 'insert_some', 'search_some' and 'remove_some'.
- * These operate just like hashtable_insert etc., with the same parameters,
- * but their function signatures have 'struct some_key *' rather than
- * 'void *', and hence can generate compile time errors if your program is
- * supplying incorrect data as a key (and similarly for value).
- *
- * Note that the hash and key equality functions passed to create_hashtable
- * still take 'void *' parameters instead of 'some key *'. This shouldn't be
- * a difficult issue as they're only defined and passed once, and the other
- * functions will ensure that only valid keys are supplied to them.
- *
- * The cost for this checking is increased code size and runtime overhead
- * - if performance is important, it may be worth switching back to the
- * unsafe methods once your program has been debugged with the safe methods.
- * This just requires switching to some simple alternative defines - eg:
- * #define insert_some hashtable_insert
- *
- */
-
-/*****************************************************************************
- * create_hashtable
-
- * @name                    create_hashtable
- * @param   minsize         minimum initial size of hashtable
- * @param   hashfunction    function for hashing keys
- * @param   key_eq_fn       function for determining key equality
- * @return                  newly created hashtable or NULL on failure
- */
-
-struct hashtable *
-create_hashtable(unsigned int minsize,
-                 unsigned int (*hashfunction) (void*),
-                 int (*key_eq_fn) (void*,void*));
-
-/*****************************************************************************
- * hashtable_insert
-
- * @name        hashtable_insert
- * @param   h   the hashtable to insert into
- * @param   k   the key - hashtable claims ownership and will free on removal
- * @param   v   the value - does not claim ownership
- * @return      non-zero for successful insertion
- *
- * This function will cause the table to expand if the insertion would take
- * the ratio of entries to table size over the maximum load factor.
- *
- * This function does not check for repeated insertions with a duplicate key.
- * The value returned when using a duplicate key is undefined -- when
- * the hashtable changes size, the order of retrieval of duplicate key
- * entries is reversed.
- * If in doubt, remove before insert.
- */
-
-int
-hashtable_insert(struct hashtable *h, void *k, void *v);
-
-#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \
-int fnname (struct hashtable *h, keytype *k, valuetype *v) \
-{ \
-    return hashtable_insert(h,k,v); \
-}
-
-/*****************************************************************************
- * hashtable_search
-
- * @name        hashtable_search
- * @param   h   the hashtable to search
- * @param   k   the key to search for  - does not claim ownership
- * @return      the value associated with the key, or NULL if none found
- */
-
-void *
-hashtable_search(struct hashtable *h, void *k);
-
-#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \
-valuetype * fnname (struct hashtable *h, keytype *k) \
-{ \
-    return (valuetype *) (hashtable_search(h,k)); \
-}
-
-/*****************************************************************************
- * hashtable_remove
-
- * @name        hashtable_remove
- * @param   h   the hashtable to remove the item from
- * @param   k   the key to search for  - does not claim ownership
- * @return      the value associated with the key, or NULL if none found
- */
-
-void * /* returns value */
-hashtable_remove(struct hashtable *h, void *k);
-
-#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \
-valuetype * fnname (struct hashtable *h, keytype *k) \
-{ \
-    return (valuetype *) (hashtable_remove(h,k)); \
-}
-
-
-/*****************************************************************************
- * hashtable_count
-
- * @name        hashtable_count
- * @param   h   the hashtable
- * @return      the number of items stored in the hashtable
- */
-unsigned int
-hashtable_count(struct hashtable *h);
-
-
-/*****************************************************************************
- * hashtable_destroy
-
- * @name        hashtable_destroy
- * @param   h   the hashtable
- * @param       free_values     whether to call 'free' on the remaining values
- */
-
-void
-hashtable_destroy(struct hashtable *h, int free_values);
-
-#endif /* __HASHTABLE_CWC22_H__ */
-
-/*
- * Copyright (c) 2002, Christopher Clark
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of the original author; nor the names of any contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
diff --git a/ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.c b/ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.c
deleted file mode 100644
index d102453..0000000
--- a/ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/* Copyright (C) 2002, 2004 Christopher Clark  <firstname.lastname@cl.cam.ac.uk> */
-
-#include "hashtable.h"
-#include "hashtable_private.h"
-#include "hashtable_itr.h"
-#include <stdlib.h> /* defines NULL */
-
-/*****************************************************************************/
-/* hashtable_iterator    - iterator constructor */
-
-struct hashtable_itr *
-hashtable_iterator(struct hashtable *h)
-{
-    unsigned int i, tablelength;
-    struct hashtable_itr *itr = (struct hashtable_itr *)
-        malloc(sizeof(struct hashtable_itr));
-    if (NULL == itr) return NULL;
-    itr->h = h;
-    itr->e = NULL;
-    itr->parent = NULL;
-    tablelength = h->tablelength;
-    itr->index = tablelength;
-    if (0 == h->entrycount) return itr;
-
-    for (i = 0; i < tablelength; i++)
-    {
-        if (NULL != h->table[i])
-        {
-            itr->e = h->table[i];
-            itr->index = i;
-            break;
-        }
-    }
-    return itr;
-}
-
-/*****************************************************************************/
-/* advance - advance the iterator to the next element
- *           returns zero if advanced to end of table */
-
-int
-hashtable_iterator_advance(struct hashtable_itr *itr)
-{
-    unsigned int j,tablelength;
-    struct entry **table;
-    struct entry *next;
-    if (NULL == itr->e) return 0; /* stupidity check */
-
-    next = itr->e->next;
-    if (NULL != next)
-    {
-        itr->parent = itr->e;
-        itr->e = next;
-        return -1;
-    }
-    tablelength = itr->h->tablelength;
-    itr->parent = NULL;
-    if (tablelength <= (j = ++(itr->index)))
-    {
-        itr->e = NULL;
-        return 0;
-    }
-    table = itr->h->table;
-    while (NULL == (next = table[j]))
-    {
-        if (++j >= tablelength)
-        {
-            itr->index = tablelength;
-            itr->e = NULL;
-            return 0;
-        }
-    }
-    itr->index = j;
-    itr->e = next;
-    return -1;
-}
-
-/*****************************************************************************/
-/* remove - remove the entry at the current iterator position
- *          and advance the iterator, if there is a successive
- *          element.
- *          If you want the value, read it before you remove:
- *          beware memory leaks if you don't.
- *          Returns zero if end of iteration. */
-
-int
-hashtable_iterator_remove(struct hashtable_itr *itr)
-{
-    struct entry *remember_e, *remember_parent;
-    int ret;
-
-    /* Do the removal */
-    if (NULL == (itr->parent))
-    {
-        /* element is head of a chain */
-        itr->h->table[itr->index] = itr->e->next;
-    } else {
-        /* element is mid-chain */
-        itr->parent->next = itr->e->next;
-    }
-    /* itr->e is now outside the hashtable */
-    remember_e = itr->e;
-    itr->h->entrycount--;
-    freekey(remember_e->k);
-
-    /* Advance the iterator, correcting the parent */
-    remember_parent = itr->parent;
-    ret = hashtable_iterator_advance(itr);
-    if (itr->parent == remember_e) { itr->parent = remember_parent; }
-    free(remember_e);
-    return ret;
-}
-
-/*****************************************************************************/
-int /* returns zero if not found */
-hashtable_iterator_search(struct hashtable_itr *itr,
-                          struct hashtable *h, void *k)
-{
-    struct entry *e, *parent;
-    unsigned int hashvalue, index;
-
-    hashvalue = hash(h,k);
-    index = indexFor(h->tablelength,hashvalue);
-
-    e = h->table[index];
-    parent = NULL;
-    while (NULL != e)
-    {
-        /* Check hash value to short circuit heavier comparison */
-        if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
-        {
-            itr->index = index;
-            itr->e = e;
-            itr->parent = parent;
-            itr->h = h;
-            return -1;
-        }
-        parent = e;
-        e = e->next;
-    }
-    return 0;
-}
-
-
-/*
- * Copyright (c) 2002, 2004, Christopher Clark
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of the original author; nor the names of any contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
diff --git a/ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.h b/ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.h
deleted file mode 100644
index 5c94a04..0000000
--- a/ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
-
-#ifndef __HASHTABLE_ITR_CWC22__
-#define __HASHTABLE_ITR_CWC22__
-#include "hashtable.h"
-#include "hashtable_private.h" /* needed to enable inlining */
-
-/*****************************************************************************/
-/* This struct is only concrete here to allow the inlining of two of the
- * accessor functions. */
-struct hashtable_itr
-{
-    struct hashtable *h;
-    struct entry *e;
-    struct entry *parent;
-    unsigned int index;
-};
-
-
-/*****************************************************************************/
-/* hashtable_iterator
- */
-
-struct hashtable_itr *
-hashtable_iterator(struct hashtable *h);
-
-/*****************************************************************************/
-/* hashtable_iterator_key
- * - return the value of the (key,value) pair at the current position */
-
-static inline void *
-hashtable_iterator_key(struct hashtable_itr *i)
-{
-    return i->e->k;
-}
-
-/*****************************************************************************/
-/* value - return the value of the (key,value) pair at the current position */
-
-static inline void *
-hashtable_iterator_value(struct hashtable_itr *i)
-{
-    return i->e->v;
-}
-
-/*****************************************************************************/
-/* advance - advance the iterator to the next element
- *           returns zero if advanced to end of table */
-
-int
-hashtable_iterator_advance(struct hashtable_itr *itr);
-
-/*****************************************************************************/
-/* remove - remove current element and advance the iterator to the next element
- *          NB: if you need the value to free it, read it before
- *          removing. ie: beware memory leaks!
- *          returns zero if advanced to end of table */
-
-int
-hashtable_iterator_remove(struct hashtable_itr *itr);
-
-/*****************************************************************************/
-/* search - overwrite the supplied iterator, to point to the entry
- *          matching the supplied key.
-            h points to the hashtable to be searched.
- *          returns zero if not found. */
-int
-hashtable_iterator_search(struct hashtable_itr *itr,
-                          struct hashtable *h, void *k);
-
-#define DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \
-int fnname (struct hashtable_itr *i, struct hashtable *h, keytype *k) \
-{ \
-    return (hashtable_iterator_search(i,h,k)); \
-}
-
-
-
-#endif /* __HASHTABLE_ITR_CWC22__*/
-
-/*
- * Copyright (c) 2002, 2004, Christopher Clark
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of the original author; nor the names of any contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
diff --git a/ubifs-utils/mkfs.ubifs/hashtable/hashtable_private.h b/ubifs-utils/mkfs.ubifs/hashtable/hashtable_private.h
deleted file mode 100644
index 3a558e6..0000000
--- a/ubifs-utils/mkfs.ubifs/hashtable/hashtable_private.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
-
-#ifndef __HASHTABLE_PRIVATE_CWC22_H__
-#define __HASHTABLE_PRIVATE_CWC22_H__
-
-#include "hashtable.h"
-
-/*****************************************************************************/
-struct entry
-{
-    void *k, *v;
-    unsigned int h;
-    struct entry *next;
-};
-
-struct hashtable {
-    unsigned int tablelength;
-    struct entry **table;
-    unsigned int entrycount;
-    unsigned int loadlimit;
-    unsigned int primeindex;
-    unsigned int (*hashfn) (void *k);
-    int (*eqfn) (void *k1, void *k2);
-};
-
-/*****************************************************************************/
-unsigned int
-hash(struct hashtable *h, void *k);
-
-/*****************************************************************************/
-/* indexFor */
-static inline unsigned int
-indexFor(unsigned int tablelength, unsigned int hashvalue) {
-    return (hashvalue % tablelength);
-};
-
-/* Only works if tablelength == 2^N */
-/*static inline unsigned int
-indexFor(unsigned int tablelength, unsigned int hashvalue)
-{
-    return (hashvalue & (tablelength - 1u));
-}
-*/
-
-/*****************************************************************************/
-#define freekey(X) free(X)
-/*define freekey(X) ; */
-
-
-/*****************************************************************************/
-
-#endif /* __HASHTABLE_PRIVATE_CWC22_H__*/
-
-/*
- * Copyright (c) 2002, Christopher Clark
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of the original author; nor the names of any contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
diff --git a/ubifs-utils/mkfs.ubifs/io.c b/ubifs-utils/mkfs.ubifs/io.c
deleted file mode 100644
index 7aba0a6..0000000
--- a/ubifs-utils/mkfs.ubifs/io.c
+++ /dev/null
@@ -1,33 +0,0 @@
-#include "io.h"
-#define PROGRAM_NAME "ubifs-io"
-#include <common.h>
-
-int out_fd;
-int out_ubi;
-libubi_t ubi;
-
-/**
- * write_leb - copy the image of a LEB to the output target.
- * @lnum: LEB number
- * @len: length of data in the buffer
- * @buf: buffer (must be at least c->leb_size bytes)
- */
-int write_leb(struct ubifs_info *c, int lnum, int len, void *buf)
-{
-	off_t pos = (off_t)lnum * c->leb_size;
-
-	dbg_msg(3, "LEB %d len %d", lnum, len);
-	memset(buf + len, 0xff, c->leb_size - len);
-	if (out_ubi)
-		if (ubi_leb_change_start(ubi, out_fd, lnum, c->leb_size))
-			return sys_err_msg("ubi_leb_change_start failed");
-
-	if (lseek(out_fd, pos, SEEK_SET) != pos)
-		return sys_err_msg("lseek failed seeking %"PRIdoff_t, pos);
-
-	if (write(out_fd, buf, c->leb_size) != c->leb_size)
-		return sys_err_msg("write failed writing %d bytes at pos %"PRIdoff_t,
-				   c->leb_size, pos);
-
-	return 0;
-}
diff --git a/ubifs-utils/mkfs.ubifs/io.h b/ubifs-utils/mkfs.ubifs/io.h
deleted file mode 100644
index e24d0c6..0000000
--- a/ubifs-utils/mkfs.ubifs/io.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/**
- * Header file for the io to ubi volume
- */
-#ifndef __UBIFS_IO_H__
-#define __UBIFS_IO_H__
-
-#include "ubifs_common.h"
-#include "ubifs.h"
-
-extern int out_fd;
-extern int out_ubi;
-extern libubi_t ubi;
-
-int write_leb(struct ubifs_info *c, int lnum, int len, void *buf);
-#endif
diff --git a/ubifs-utils/mkfs.ubifs/key.h b/ubifs-utils/mkfs.ubifs/key.h
deleted file mode 100644
index 39379fd..0000000
--- a/ubifs-utils/mkfs.ubifs/key.h
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * This file is part of UBIFS.
- *
- * Copyright (C) 2006-2008 Nokia Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Authors: Artem Bityutskiy (Битюцкий Артём)
- *          Adrian Hunter
- */
-
-/*
- * This header contains various key-related definitions and helper function.
- * UBIFS allows several key schemes, so we access key fields only via these
- * helpers. At the moment only one key scheme is supported.
- *
- * Simple key scheme
- * ~~~~~~~~~~~~~~~~~
- *
- * Keys are 64-bits long. First 32-bits are inode number (parent inode number
- * in case of direntry key). Next 3 bits are node type. The last 29 bits are
- * 4KiB offset in case of inode node, and direntry hash in case of a direntry
- * node. We use "r5" hash borrowed from reiserfs.
- */
-
-#ifndef __UBIFS_KEY_H__
-#define __UBIFS_KEY_H__
-
-/**
- * key_mask_hash - mask a valid hash value.
- * @val: value to be masked
- *
- * We use hash values as offset in directories, so values %0 and %1 are
- * reserved for "." and "..". %2 is reserved for "end of readdir" marker. This
- * function makes sure the reserved values are not used.
- */
-static inline uint32_t key_mask_hash(uint32_t hash)
-{
-	hash &= UBIFS_S_KEY_HASH_MASK;
-	if (unlikely(hash <= 2))
-		hash += 3;
-	return hash;
-}
-
-/**
- * key_r5_hash - R5 hash function (borrowed from reiserfs).
- * @s: direntry name
- * @len: name length
- */
-static inline uint32_t key_r5_hash(const char *s, int len)
-{
-	uint32_t a = 0;
-	const signed char *str = (const signed char *)s;
-
-	len = len;
-	while (*str) {
-		a += *str << 4;
-		a += *str >> 4;
-		a *= 11;
-		str++;
-	}
-
-	return key_mask_hash(a);
-}
-
-/**
- * key_test_hash - testing hash function.
- * @str: direntry name
- * @len: name length
- */
-static inline uint32_t key_test_hash(const char *str, int len)
-{
-	uint32_t a = 0;
-
-	len = min_t(uint32_t, len, 4);
-	memcpy(&a, str, len);
-	return key_mask_hash(a);
-}
-
-/**
- * ino_key_init - initialize inode key.
- * @c: UBIFS file-system description object
- * @key: key to initialize
- * @inum: inode number
- */
-static inline void ino_key_init(union ubifs_key *key, ino_t inum)
-{
-	key->u32[0] = inum;
-	key->u32[1] = UBIFS_INO_KEY << UBIFS_S_KEY_BLOCK_BITS;
-}
-
-/**
- * dent_key_init - initialize directory entry key.
- * @c: UBIFS file-system description object
- * @key: key to initialize
- * @inum: parent inode number
- * @nm: direntry name and length
- */
-static inline void dent_key_init(const struct ubifs_info *c,
-				 union ubifs_key *key, ino_t inum,
-				 const struct qstr *nm)
-{
-	uint32_t hash = c->key_hash(nm->name, nm->len);
-
-	ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
-	key->u32[0] = inum;
-	key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS);
-}
-
-/**
- * xent_key_init - initialize extended attribute entry key.
- * @c: UBIFS file-system description object
- * @key: key to initialize
- * @inum: host inode number
- * @nm: extended attribute entry name and length
- */
-static inline void xent_key_init(const struct ubifs_info *c,
-				 union ubifs_key *key, ino_t inum,
-				 const struct qstr *nm)
-{
-	uint32_t hash = c->key_hash(nm->name, nm->len);
-
-	ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
-	key->u32[0] = inum;
-	key->u32[1] = hash | (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS);
-}
-
-/**
- * data_key_init - initialize data key.
- * @c: UBIFS file-system description object
- * @key: key to initialize
- * @inum: inode number
- * @block: block number
- */
-static inline void data_key_init(union ubifs_key *key, ino_t inum,
-				 unsigned int block)
-{
-	ubifs_assert(!(block & ~UBIFS_S_KEY_BLOCK_MASK));
-	key->u32[0] = inum;
-	key->u32[1] = block | (UBIFS_DATA_KEY << UBIFS_S_KEY_BLOCK_BITS);
-}
-
-/**
- * key_write - transform a key from in-memory format.
- * @c: UBIFS file-system description object
- * @from: the key to transform
- * @to: the key to store the result
- */
-static inline void key_write(const union ubifs_key *from, void *to)
-{
-	union ubifs_key *t = to;
-
-	t->j32[0] = cpu_to_le32(from->u32[0]);
-	t->j32[1] = cpu_to_le32(from->u32[1]);
-	memset(to + 8, 0, UBIFS_MAX_KEY_LEN - 8);
-}
-
-/**
- * key_write_idx - transform a key from in-memory format for the index.
- * @c: UBIFS file-system description object
- * @from: the key to transform
- * @to: the key to store the result
- */
-static inline void key_write_idx(const union ubifs_key *from, void *to)
-{
-	union ubifs_key *t = to;
-
-	t->j32[0] = cpu_to_le32(from->u32[0]);
-	t->j32[1] = cpu_to_le32(from->u32[1]);
-}
-
-/**
- * keys_cmp - compare keys.
- * @c: UBIFS file-system description object
- * @key1: the first key to compare
- * @key2: the second key to compare
- *
- * This function compares 2 keys and returns %-1 if @key1 is less than
- * @key2, 0 if the keys are equivalent and %1 if @key1 is greater than @key2.
- */
-static inline int keys_cmp(const union ubifs_key *key1,
-			   const union ubifs_key *key2)
-{
-	if (key1->u32[0] < key2->u32[0])
-		return -1;
-	if (key1->u32[0] > key2->u32[0])
-		return 1;
-	if (key1->u32[1] < key2->u32[1])
-		return -1;
-	if (key1->u32[1] > key2->u32[1])
-		return 1;
-
-	return 0;
-}
-
-#endif /* !__UBIFS_KEY_H__ */
diff --git a/ubifs-utils/mkfs.ubifs/lpt.c b/ubifs-utils/mkfs.ubifs/lpt.c
deleted file mode 100644
index 100d747..0000000
--- a/ubifs-utils/mkfs.ubifs/lpt.c
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * This file is part of UBIFS.
- *
- * Copyright (C) 2006, 2007 Nokia Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Authors: Adrian Hunter
- *          Artem Bityutskiy
- */
-
-#include "ubifs_common.h"
-
-/* common.h requires the PROGRAM_NAME macro */
-#define PROGRAM_NAME "ubifs-lpt"
-#include "common.h"
-
-#include "crc16.h"
-#include "ubifs.h"
-#include "lpt.h"
-#include "io.h"
-
-/**
- * do_calc_lpt_geom - calculate sizes for the LPT area.
- * @c: the UBIFS file-system description object
- *
- * Calculate the sizes of LPT bit fields, nodes, and tree, based on the
- * properties of the flash and whether LPT is "big" (c->big_lpt).
- */
-static void do_calc_lpt_geom(struct ubifs_info *c)
-{
-	int n, bits, per_leb_wastage;
-	long long sz, tot_wastage;
-
-	c->pnode_cnt = (c->main_lebs + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT;
-
-	n = (c->pnode_cnt + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT;
-	c->nnode_cnt = n;
-	while (n > 1) {
-		n = (n + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT;
-		c->nnode_cnt += n;
-	}
-
-	c->lpt_hght = 1;
-	n = UBIFS_LPT_FANOUT;
-	while (n < c->pnode_cnt) {
-		c->lpt_hght += 1;
-		n <<= UBIFS_LPT_FANOUT_SHIFT;
-	}
-
-	c->space_bits = fls(c->leb_size) - 3;
-	c->lpt_lnum_bits = fls(c->lpt_lebs);
-	c->lpt_offs_bits = fls(c->leb_size - 1);
-	c->lpt_spc_bits = fls(c->leb_size);
-
-	n = (c->max_leb_cnt + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT;
-	c->pcnt_bits = fls(n - 1);
-
-	c->lnum_bits = fls(c->max_leb_cnt - 1);
-
-	bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
-	       (c->big_lpt ? c->pcnt_bits : 0) +
-	       (c->space_bits * 2 + 1) * UBIFS_LPT_FANOUT;
-	c->pnode_sz = (bits + 7) / 8;
-
-	bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
-	       (c->big_lpt ? c->pcnt_bits : 0) +
-	       (c->lpt_lnum_bits + c->lpt_offs_bits) * UBIFS_LPT_FANOUT;
-	c->nnode_sz = (bits + 7) / 8;
-
-	bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
-	       c->lpt_lebs * c->lpt_spc_bits * 2;
-	c->ltab_sz = (bits + 7) / 8;
-
-	bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
-	       c->lnum_bits * c->lsave_cnt;
-	c->lsave_sz = (bits + 7) / 8;
-
-	/* Calculate the minimum LPT size */
-	c->lpt_sz = (long long)c->pnode_cnt * c->pnode_sz;
-	c->lpt_sz += (long long)c->nnode_cnt * c->nnode_sz;
-	c->lpt_sz += c->ltab_sz;
-	c->lpt_sz += c->lsave_sz;
-
-	/* Add wastage */
-	sz = c->lpt_sz;
-	per_leb_wastage = max_t(int, c->pnode_sz, c->nnode_sz);
-	sz += per_leb_wastage;
-	tot_wastage = per_leb_wastage;
-	while (sz > c->leb_size) {
-		sz += per_leb_wastage;
-		sz -= c->leb_size;
-		tot_wastage += per_leb_wastage;
-	}
-	tot_wastage += ALIGN(sz, c->min_io_size) - sz;
-	c->lpt_sz += tot_wastage;
-}
-
-/**
- * calc_dflt_lpt_geom - calculate default LPT geometry.
- * @c: the UBIFS file-system description object
- * @main_lebs: number of main area LEBs is passed and returned here
- * @big_lpt: whether the LPT area is "big" is returned here
- *
- * The size of the LPT area depends on parameters that themselves are dependent
- * on the size of the LPT area. This function, successively recalculates the LPT
- * area geometry until the parameters and resultant geometry are consistent.
- *
- * This function returns %0 on success and a negative error code on failure.
- */
-int calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs, int *big_lpt)
-{
-	int i, lebs_needed;
-	long long sz;
-
-	/* Start by assuming the minimum number of LPT LEBs */
-	c->lpt_lebs = UBIFS_MIN_LPT_LEBS;
-	c->main_lebs = *main_lebs - c->lpt_lebs;
-	if (c->main_lebs <= 0)
-		return -EINVAL;
-
-	/* And assume we will use the small LPT model */
-	c->big_lpt = 0;
-
-	/*
-	 * Calculate the geometry based on assumptions above and then see if it
-	 * makes sense
-	 */
-	do_calc_lpt_geom(c);
-
-	/* Small LPT model must have lpt_sz < leb_size */
-	if (c->lpt_sz > c->leb_size) {
-		/* Nope, so try again using big LPT model */
-		c->big_lpt = 1;
-		do_calc_lpt_geom(c);
-	}
-
-	/* Now check there are enough LPT LEBs */
-	for (i = 0; i < 64 ; i++) {
-		sz = c->lpt_sz * 4; /* Allow 4 times the size */
-		sz += c->leb_size - 1;
-		do_div(sz, c->leb_size);
-		lebs_needed = sz;
-		if (lebs_needed > c->lpt_lebs) {
-			/* Not enough LPT LEBs so try again with more */
-			c->lpt_lebs = lebs_needed;
-			c->main_lebs = *main_lebs - c->lpt_lebs;
-			if (c->main_lebs <= 0)
-				return -EINVAL;
-			do_calc_lpt_geom(c);
-			continue;
-		}
-		if (c->ltab_sz > c->leb_size) {
-			err_msg("LPT ltab too big");
-			return -EINVAL;
-		}
-		*main_lebs = c->main_lebs;
-		*big_lpt = c->big_lpt;
-		return 0;
-	}
-	return -EINVAL;
-}
-
-/**
- * pack_bits - pack bit fields end-to-end.
- * @addr: address at which to pack (passed and next address returned)
- * @pos: bit position at which to pack (passed and next position returned)
- * @val: value to pack
- * @nrbits: number of bits of value to pack (1-32)
- */
-static void pack_bits(uint8_t **addr, int *pos, uint32_t val, int nrbits)
-{
-	uint8_t *p = *addr;
-	int b = *pos;
-
-	if (b) {
-		*p |= ((uint8_t)val) << b;
-		nrbits += b;
-		if (nrbits > 8) {
-			*++p = (uint8_t)(val >>= (8 - b));
-			if (nrbits > 16) {
-				*++p = (uint8_t)(val >>= 8);
-				if (nrbits > 24) {
-					*++p = (uint8_t)(val >>= 8);
-					if (nrbits > 32)
-						*++p = (uint8_t)(val >>= 8);
-				}
-			}
-		}
-	} else {
-		*p = (uint8_t)val;
-		if (nrbits > 8) {
-			*++p = (uint8_t)(val >>= 8);
-			if (nrbits > 16) {
-				*++p = (uint8_t)(val >>= 8);
-				if (nrbits > 24)
-					*++p = (uint8_t)(val >>= 8);
-			}
-		}
-	}
-	b = nrbits & 7;
-	if (b == 0)
-		p++;
-	*addr = p;
-	*pos = b;
-}
-
-/**
- * pack_pnode - pack all the bit fields of a pnode.
- * @c: UBIFS file-system description object
- * @buf: buffer into which to pack
- * @pnode: pnode to pack
- */
-static void pack_pnode(struct ubifs_info *c, void *buf,
-		       struct ubifs_pnode *pnode)
-{
-	uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
-	int i, pos = 0;
-	uint16_t crc;
-
-	pack_bits(&addr, &pos, UBIFS_LPT_PNODE, UBIFS_LPT_TYPE_BITS);
-	if (c->big_lpt)
-		pack_bits(&addr, &pos, pnode->num, c->pcnt_bits);
-	for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-		pack_bits(&addr, &pos, pnode->lprops[i].free >> 3,
-			  c->space_bits);
-		pack_bits(&addr, &pos, pnode->lprops[i].dirty >> 3,
-			  c->space_bits);
-		if (pnode->lprops[i].flags & LPROPS_INDEX)
-			pack_bits(&addr, &pos, 1, 1);
-		else
-			pack_bits(&addr, &pos, 0, 1);
-	}
-	crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
-		    c->pnode_sz - UBIFS_LPT_CRC_BYTES);
-	addr = buf;
-	pos = 0;
-	pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
-}
-
-/**
- * pack_nnode - pack all the bit fields of a nnode.
- * @c: UBIFS file-system description object
- * @buf: buffer into which to pack
- * @nnode: nnode to pack
- */
-static void pack_nnode(struct ubifs_info *c, void *buf,
-		       struct ubifs_nnode *nnode)
-{
-	uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
-	int i, pos = 0;
-	uint16_t crc;
-
-	pack_bits(&addr, &pos, UBIFS_LPT_NNODE, UBIFS_LPT_TYPE_BITS);
-	if (c->big_lpt)
-		pack_bits(&addr, &pos, nnode->num, c->pcnt_bits);
-	for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-		int lnum = nnode->nbranch[i].lnum;
-
-		if (lnum == 0)
-			lnum = c->lpt_last + 1;
-		pack_bits(&addr, &pos, lnum - c->lpt_first, c->lpt_lnum_bits);
-		pack_bits(&addr, &pos, nnode->nbranch[i].offs,
-			  c->lpt_offs_bits);
-	}
-	crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
-		    c->nnode_sz - UBIFS_LPT_CRC_BYTES);
-	addr = buf;
-	pos = 0;
-	pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
-}
-
-/**
- * pack_ltab - pack the LPT's own lprops table.
- * @c: UBIFS file-system description object
- * @buf: buffer into which to pack
- * @ltab: LPT's own lprops table to pack
- */
-static void pack_ltab(struct ubifs_info *c, void *buf,
-			 struct ubifs_lpt_lprops *ltab)
-{
-	uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
-	int i, pos = 0;
-	uint16_t crc;
-
-	pack_bits(&addr, &pos, UBIFS_LPT_LTAB, UBIFS_LPT_TYPE_BITS);
-	for (i = 0; i < c->lpt_lebs; i++) {
-		pack_bits(&addr, &pos, ltab[i].free, c->lpt_spc_bits);
-		pack_bits(&addr, &pos, ltab[i].dirty, c->lpt_spc_bits);
-	}
-	crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
-		    c->ltab_sz - UBIFS_LPT_CRC_BYTES);
-	addr = buf;
-	pos = 0;
-	pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
-}
-
-/**
- * pack_lsave - pack the LPT's save table.
- * @c: UBIFS file-system description object
- * @buf: buffer into which to pack
- * @lsave: LPT's save table to pack
- */
-static void pack_lsave(struct ubifs_info *c, void *buf, int *lsave)
-{
-	uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
-	int i, pos = 0;
-	uint16_t crc;
-
-	pack_bits(&addr, &pos, UBIFS_LPT_LSAVE, UBIFS_LPT_TYPE_BITS);
-	for (i = 0; i < c->lsave_cnt; i++)
-		pack_bits(&addr, &pos, lsave[i], c->lnum_bits);
-	crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
-		    c->lsave_sz - UBIFS_LPT_CRC_BYTES);
-	addr = buf;
-	pos = 0;
-	pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
-}
-
-/**
- * set_ltab - set LPT LEB properties.
- * @c: UBIFS file-system description object
- * @lnum: LEB number
- * @free: amount of free space
- * @dirty: amount of dirty space
- */
-static void set_ltab(struct ubifs_info *c, int lnum, int free, int dirty)
-{
-	dbg_msg(3, "LEB %d free %d dirty %d to %d %d",
-		lnum, c->ltab[lnum - c->lpt_first].free,
-		c->ltab[lnum - c->lpt_first].dirty, free, dirty);
-	c->ltab[lnum - c->lpt_first].free = free;
-	c->ltab[lnum - c->lpt_first].dirty = dirty;
-}
-
-/**
- * calc_nnode_num - calculate nnode number.
- * @row: the row in the tree (root is zero)
- * @col: the column in the row (leftmost is zero)
- *
- * The nnode number is a number that uniquely identifies a nnode and can be used
- * easily to traverse the tree from the root to that nnode.
- *
- * This function calculates and returns the nnode number for the nnode at @row
- * and @col.
- */
-static int calc_nnode_num(int row, int col)
-{
-	int num, bits;
-
-	num = 1;
-	while (row--) {
-		bits = (col & (UBIFS_LPT_FANOUT - 1));
-		col >>= UBIFS_LPT_FANOUT_SHIFT;
-		num <<= UBIFS_LPT_FANOUT_SHIFT;
-		num |= bits;
-	}
-	return num;
-}
-
-/**
- * create_lpt - create LPT.
- * @c: UBIFS file-system description object
- *
- * This function returns %0 on success and a negative error code on failure.
- */
-int create_lpt(struct ubifs_info *c)
-{
-	int lnum, err = 0, i, j, cnt, len, alen, row;
-	int blnum, boffs, bsz, bcnt;
-	struct ubifs_pnode *pnode = NULL;
-	struct ubifs_nnode *nnode = NULL;
-	void *buf = NULL, *p;
-	int *lsave = NULL;
-
-	pnode = malloc(sizeof(struct ubifs_pnode));
-	nnode = malloc(sizeof(struct ubifs_nnode));
-	buf = malloc(c->leb_size);
-	lsave = malloc(sizeof(int) * c->lsave_cnt);
-	if (!pnode || !nnode || !buf || !lsave) {
-		err = -ENOMEM;
-		goto out;
-	}
-	memset(pnode, 0 , sizeof(struct ubifs_pnode));
-	memset(nnode, 0 , sizeof(struct ubifs_nnode));
-
-	c->lscan_lnum = c->main_first;
-
-	lnum = c->lpt_first;
-	p = buf;
-	len = 0;
-	/* Number of leaf nodes (pnodes) */
-	cnt = (c->main_lebs + UBIFS_LPT_FANOUT - 1) >> UBIFS_LPT_FANOUT_SHIFT;
-	//printf("pnode_cnt=%d\n",cnt);
-
-	/*
-	 * To calculate the internal node branches, we keep information about
-	 * the level below.
-	 */
-	blnum = lnum; /* LEB number of level below */
-	boffs = 0; /* Offset of level below */
-	bcnt = cnt; /* Number of nodes in level below */
-	bsz = c->pnode_sz; /* Size of nodes in level below */
-
-	/* Add pnodes */
-	for (i = 0; i < cnt; i++) {
-		if (len + c->pnode_sz > c->leb_size) {
-			alen = ALIGN(len, c->min_io_size);
-			set_ltab(c, lnum, c->leb_size - alen, alen - len);
-			memset(p, 0xff, alen - len);
-			err = write_leb(c, lnum++, alen, buf);
-			if (err)
-				goto out;
-			p = buf;
-			len = 0;
-		}
-		/* Fill in the pnode */
-		for (j = 0; j < UBIFS_LPT_FANOUT; j++) {
-			int k = (i << UBIFS_LPT_FANOUT_SHIFT) + j;
-
-			if (k < c->main_lebs)
-				pnode->lprops[j] = c->lpt[k];
-			else {
-				pnode->lprops[j].free = c->leb_size;
-				pnode->lprops[j].dirty = 0;
-				pnode->lprops[j].flags = 0;
-			}
-		}
-		pack_pnode(c, p, pnode);
-		p += c->pnode_sz;
-		len += c->pnode_sz;
-		/*
-		 * pnodes are simply numbered left to right starting at zero,
-		 * which means the pnode number can be used easily to traverse
-		 * down the tree to the corresponding pnode.
-		 */
-		pnode->num += 1;
-	}
-
-	row = c->lpt_hght - 1;
-	/* Add all nnodes, one level at a time */
-	while (1) {
-		/* Number of internal nodes (nnodes) at next level */
-		cnt = (cnt + UBIFS_LPT_FANOUT - 1) / UBIFS_LPT_FANOUT;
-		if (cnt == 0)
-			cnt = 1;
-		for (i = 0; i < cnt; i++) {
-			if (len + c->nnode_sz > c->leb_size) {
-				alen = ALIGN(len, c->min_io_size);
-				set_ltab(c, lnum, c->leb_size - alen,
-					    alen - len);
-				memset(p, 0xff, alen - len);
-				err = write_leb(c, lnum++, alen, buf);
-				if (err)
-					goto out;
-				p = buf;
-				len = 0;
-			}
-			/* The root is on row zero */
-			if (row == 0) {
-				c->lpt_lnum = lnum;
-				c->lpt_offs = len;
-			}
-			/* Set branches to the level below */
-			for (j = 0; j < UBIFS_LPT_FANOUT; j++) {
-				if (bcnt) {
-					if (boffs + bsz > c->leb_size) {
-						blnum += 1;
-						boffs = 0;
-					}
-					nnode->nbranch[j].lnum = blnum;
-					nnode->nbranch[j].offs = boffs;
-					boffs += bsz;
-					bcnt--;
-				} else {
-					nnode->nbranch[j].lnum = 0;
-					nnode->nbranch[j].offs = 0;
-				}
-			}
-			nnode->num = calc_nnode_num(row, i);
-			pack_nnode(c, p, nnode);
-			p += c->nnode_sz;
-			len += c->nnode_sz;
-		}
-		/* Row zero  is the top row */
-		if (row == 0)
-			break;
-		/* Update the information about the level below */
-		bcnt = cnt;
-		bsz = c->nnode_sz;
-		row -= 1;
-	}
-
-	if (c->big_lpt) {
-		/* Need to add LPT's save table */
-		if (len + c->lsave_sz > c->leb_size) {
-			alen = ALIGN(len, c->min_io_size);
-			set_ltab(c, lnum, c->leb_size - alen, alen - len);
-			memset(p, 0xff, alen - len);
-			err = write_leb(c, lnum++, alen, buf);
-			if (err)
-				goto out;
-			p = buf;
-			len = 0;
-		}
-
-		c->lsave_lnum = lnum;
-		c->lsave_offs = len;
-
-		for (i = 0; i < c->lsave_cnt; i++)
-			lsave[i] = c->main_first + i;
-
-		pack_lsave(c, p, lsave);
-		p += c->lsave_sz;
-		len += c->lsave_sz;
-	}
-
-	/* Need to add LPT's own LEB properties table */
-	if (len + c->ltab_sz > c->leb_size) {
-		alen = ALIGN(len, c->min_io_size);
-		set_ltab(c, lnum, c->leb_size - alen, alen - len);
-		memset(p, 0xff, alen - len);
-		err = write_leb(c, lnum++, alen, buf);
-		if (err)
-			goto out;
-		p = buf;
-		len = 0;
-	}
-
-	c->ltab_lnum = lnum;
-	c->ltab_offs = len;
-
-	/* Update ltab before packing it */
-	len += c->ltab_sz;
-	alen = ALIGN(len, c->min_io_size);
-	set_ltab(c, lnum, c->leb_size - alen, alen - len);
-
-	pack_ltab(c, p, c->ltab);
-	p += c->ltab_sz;
-
-	/* Write remaining buffer */
-	memset(p, 0xff, alen - len);
-	err = write_leb(c, lnum, alen, buf);
-	if (err)
-		goto out;
-
-	c->nhead_lnum = lnum;
-	c->nhead_offs = ALIGN(len, c->min_io_size);
-
-	dbg_msg(1, "lpt_sz:         %lld", c->lpt_sz);
-	dbg_msg(1, "space_bits:     %d", c->space_bits);
-	dbg_msg(1, "lpt_lnum_bits:  %d", c->lpt_lnum_bits);
-	dbg_msg(1, "lpt_offs_bits:  %d", c->lpt_offs_bits);
-	dbg_msg(1, "lpt_spc_bits:   %d", c->lpt_spc_bits);
-	dbg_msg(1, "pcnt_bits:      %d", c->pcnt_bits);
-	dbg_msg(1, "lnum_bits:      %d", c->lnum_bits);
-	dbg_msg(1, "pnode_sz:       %d", c->pnode_sz);
-	dbg_msg(1, "nnode_sz:       %d", c->nnode_sz);
-	dbg_msg(1, "ltab_sz:        %d", c->ltab_sz);
-	dbg_msg(1, "lsave_sz:       %d", c->lsave_sz);
-	dbg_msg(1, "lsave_cnt:      %d", c->lsave_cnt);
-	dbg_msg(1, "lpt_hght:       %d", c->lpt_hght);
-	dbg_msg(1, "big_lpt:        %d", c->big_lpt);
-	dbg_msg(1, "LPT root is at  %d:%d", c->lpt_lnum, c->lpt_offs);
-	dbg_msg(1, "LPT head is at  %d:%d", c->nhead_lnum, c->nhead_offs);
-	dbg_msg(1, "LPT ltab is at  %d:%d", c->ltab_lnum, c->ltab_offs);
-	if (c->big_lpt)
-		dbg_msg(1, "LPT lsave is at %d:%d",
-		        c->lsave_lnum, c->lsave_offs);
-out:
-	free(lsave);
-	free(buf);
-	free(nnode);
-	free(pnode);
-	return err;
-}
diff --git a/ubifs-utils/mkfs.ubifs/lpt.h b/ubifs-utils/mkfs.ubifs/lpt.h
deleted file mode 100644
index 4cde59d..0000000
--- a/ubifs-utils/mkfs.ubifs/lpt.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2008 Nokia Corporation.
- * Copyright (C) 2008 University of Szeged, Hungary
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Authors: Artem Bityutskiy
- *          Adrian Hunter
- */
-
-#ifndef __UBIFS_LPT_H__
-#define __UBIFS_LPT_H__
-
-int calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs, int *big_lpt);
-int create_lpt(struct ubifs_info *c);
-
-#endif
diff --git a/ubifs-utils/mkfs.ubifs/ubifs.h b/ubifs-utils/mkfs.ubifs/ubifs.h
deleted file mode 100644
index 2f080a8..0000000
--- a/ubifs-utils/mkfs.ubifs/ubifs.h
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * This file is part of UBIFS.
- *
- * Copyright (C) 2008 Nokia Corporation.
- * Copyright (C) 2008 University of Szeged, Hungary
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Authors: Artem Bityutskiy
- *          Adrian Hunter
- *          Zoltan Sogor
- */
-
-#ifndef __UBIFS_H__
-#define __UBIFS_H__
-
-/* Maximum logical eraseblock size in bytes */
-#define UBIFS_MAX_LEB_SZ (2*1024*1024)
-
-/* Minimum amount of data UBIFS writes to the flash */
-#define MIN_WRITE_SZ (UBIFS_DATA_NODE_SZ + 8)
-
-/* Largest key size supported in this implementation */
-#define CUR_MAX_KEY_LEN UBIFS_SK_LEN
-
-/*
- * There is no notion of truncation key because truncation nodes do not exist
- * in TNC. However, when replaying, it is handy to introduce fake "truncation"
- * keys for truncation nodes because the code becomes simpler. So we define
- * %UBIFS_TRUN_KEY type.
- */
-#define UBIFS_TRUN_KEY UBIFS_KEY_TYPES_CNT
-
-/*
- * How much a directory entry/extended attribute entry adds to the parent/host
- * inode.
- */
-#define CALC_DENT_SIZE(name_len) ALIGN(UBIFS_DENT_NODE_SZ + (name_len) + 1, 8)
-
-/* How much an extended attribute adds to the host inode */
-#define CALC_XATTR_BYTES(data_len) ALIGN(UBIFS_INO_NODE_SZ + (data_len) + 1, 8)
-
-/* The below union makes it easier to deal with keys */
-union ubifs_key
-{
-	uint8_t u8[CUR_MAX_KEY_LEN];
-	uint32_t u32[CUR_MAX_KEY_LEN/4];
-	uint64_t u64[CUR_MAX_KEY_LEN/8];
-	__le32 j32[CUR_MAX_KEY_LEN/4];
-};
-
-/*
- * LEB properties flags.
- *
- * LPROPS_UNCAT: not categorized
- * LPROPS_DIRTY: dirty > 0, not index
- * LPROPS_DIRTY_IDX: dirty + free > UBIFS_CH_SZ and index
- * LPROPS_FREE: free > 0, not empty, not index
- * LPROPS_HEAP_CNT: number of heaps used for storing categorized LEBs
- * LPROPS_EMPTY: LEB is empty, not taken
- * LPROPS_FREEABLE: free + dirty == leb_size, not index, not taken
- * LPROPS_FRDI_IDX: free + dirty == leb_size and index, may be taken
- * LPROPS_CAT_MASK: mask for the LEB categories above
- * LPROPS_TAKEN: LEB was taken (this flag is not saved on the media)
- * LPROPS_INDEX: LEB contains indexing nodes (this flag also exists on flash)
- */
-enum {
-	LPROPS_UNCAT     =  0,
-	LPROPS_DIRTY     =  1,
-	LPROPS_DIRTY_IDX =  2,
-	LPROPS_FREE      =  3,
-	LPROPS_HEAP_CNT  =  3,
-	LPROPS_EMPTY     =  4,
-	LPROPS_FREEABLE  =  5,
-	LPROPS_FRDI_IDX  =  6,
-	LPROPS_CAT_MASK  = 15,
-	LPROPS_TAKEN     = 16,
-	LPROPS_INDEX     = 32,
-};
-
-/**
- * struct ubifs_lprops - logical eraseblock properties.
- * @free: amount of free space in bytes
- * @dirty: amount of dirty space in bytes
- * @flags: LEB properties flags (see above)
- */
-struct ubifs_lprops
-{
-	int free;
-	int dirty;
-	int flags;
-};
-
-/**
- * struct ubifs_lpt_lprops - LPT logical eraseblock properties.
- * @free: amount of free space in bytes
- * @dirty: amount of dirty space in bytes
- */
-struct ubifs_lpt_lprops
-{
-	int free;
-	int dirty;
-};
-
-struct ubifs_nnode;
-
-/**
- * struct ubifs_cnode - LEB Properties Tree common node.
- * @parent: parent nnode
- * @cnext: next cnode to commit
- * @flags: flags (%DIRTY_LPT_NODE or %OBSOLETE_LPT_NODE)
- * @iip: index in parent
- * @level: level in the tree (zero for pnodes, greater than zero for nnodes)
- * @num: node number
- */
-struct ubifs_cnode
-{
-	struct ubifs_nnode *parent;
-	struct ubifs_cnode *cnext;
-	unsigned long flags;
-	int iip;
-	int level;
-	int num;
-};
-
-/**
- * struct ubifs_pnode - LEB Properties Tree leaf node.
- * @parent: parent nnode
- * @cnext: next cnode to commit
- * @flags: flags (%DIRTY_LPT_NODE or %OBSOLETE_LPT_NODE)
- * @iip: index in parent
- * @level: level in the tree (always zero for pnodes)
- * @num: node number
- * @lprops: LEB properties array
- */
-struct ubifs_pnode
-{
-	struct ubifs_nnode *parent;
-	struct ubifs_cnode *cnext;
-	unsigned long flags;
-	int iip;
-	int level;
-	int num;
-	struct ubifs_lprops lprops[UBIFS_LPT_FANOUT];
-};
-
-/**
- * struct ubifs_nbranch - LEB Properties Tree internal node branch.
- * @lnum: LEB number of child
- * @offs: offset of child
- * @nnode: nnode child
- * @pnode: pnode child
- * @cnode: cnode child
- */
-struct ubifs_nbranch
-{
-	int lnum;
-	int offs;
-	union
-	{
-		struct ubifs_nnode *nnode;
-		struct ubifs_pnode *pnode;
-		struct ubifs_cnode *cnode;
-	};
-};
-
-/**
- * struct ubifs_nnode - LEB Properties Tree internal node.
- * @parent: parent nnode
- * @cnext: next cnode to commit
- * @flags: flags (%DIRTY_LPT_NODE or %OBSOLETE_LPT_NODE)
- * @iip: index in parent
- * @level: level in the tree (always greater than zero for nnodes)
- * @num: node number
- * @nbranch: branches to child nodes
- */
-struct ubifs_nnode
-{
-	struct ubifs_nnode *parent;
-	struct ubifs_cnode *cnext;
-	unsigned long flags;
-	int iip;
-	int level;
-	int num;
-	struct ubifs_nbranch nbranch[UBIFS_LPT_FANOUT];
-};
-
-/**
- * struct ubifs_lp_stats - statistics of eraseblocks in the main area.
- * @empty_lebs: number of empty LEBs
- * @taken_empty_lebs: number of taken LEBs
- * @idx_lebs: number of indexing LEBs
- * @total_free: total free space in bytes
- * @total_dirty: total dirty space in bytes
- * @total_used: total used space in bytes (includes only data LEBs)
- * @total_dead: total dead space in bytes (includes only data LEBs)
- * @total_dark: total dark space in bytes (includes only data LEBs)
- */
-struct ubifs_lp_stats {
-	int empty_lebs;
-	int taken_empty_lebs;
-	int idx_lebs;
-	long long total_free;
-	long long total_dirty;
-	long long total_used;
-	long long total_dead;
-	long long total_dark;
-};
-
-/**
- * struct ubifs_zbranch - key/coordinate/length branch stored in znodes.
- * @key: key
- * @znode: znode address in memory
- * @lnum: LEB number of the indexing node
- * @offs: offset of the indexing node within @lnum
- * @len: target node length
- */
-struct ubifs_zbranch
-{
-	union ubifs_key key;
-	struct ubifs_znode *znode;
-	int lnum;
-	int offs;
-	int len;
-};
-
-/**
- * struct ubifs_znode - in-memory representation of an indexing node.
- * @parent: parent znode or NULL if it is the root
- * @cnext: next znode to commit
- * @flags: flags
- * @time: last access time (seconds)
- * @level: level of the entry in the TNC tree
- * @child_cnt: count of child znodes
- * @iip: index in parent's zbranch array
- * @alt: lower bound of key range has altered i.e. child inserted at slot 0
- * @zbranch: array of znode branches (@c->fanout elements)
- */
-struct ubifs_znode
-{
-	struct ubifs_znode *parent;
-	struct ubifs_znode *cnext;
-	unsigned long flags;
-	unsigned long time;
-	int level;
-	int child_cnt;
-	int iip;
-	int alt;
-#ifdef CONFIG_UBIFS_FS_DEBUG
-	int lnum, offs, len;
-#endif
-	struct ubifs_zbranch zbranch[];
-};
-
-/**
- * struct ubifs_info - UBIFS file-system description data structure
- * (per-superblock).
- *
- * @highest_inum: highest used inode number
- * @max_sqnum: current global sequence number
- *
- * @jhead_cnt: count of journal heads
- * @max_bud_bytes: maximum number of bytes allowed in buds
- *
- * @zroot: zbranch which points to the root index node and znode
- * @ihead_lnum: LEB number of index head
- * @ihead_offs: offset of index head
- *
- * @log_lebs: number of logical eraseblocks in the log
- * @lpt_lebs: number of LEBs used for lprops table
- * @lpt_first: first LEB of the lprops table area
- * @lpt_last: last LEB of the lprops table area
- * @main_lebs: count of LEBs in the main area
- * @main_first: first LEB of the main area
- * @default_compr: default compression type
- * @favor_lzo: favor LZO compression method
- * @favor_percent: lzo vs. zlib threshold used in case favor LZO
- *
- * @key_hash_type: type of the key hash
- * @key_hash: direntry key hash function
- * @key_fmt: key format
- * @key_len: key length
- * @fanout: fanout of the index tree (number of links per indexing node)
- *
- * @min_io_size: minimal input/output unit size
- * @leb_size: logical eraseblock size in bytes
- * @leb_cnt: count of logical eraseblocks
- * @max_leb_cnt: maximum count of logical eraseblocks
- *
- * @old_idx_sz: size of index on flash
- * @lst: lprops statistics
- *
- * @dead_wm: LEB dead space watermark
- * @dark_wm: LEB dark space watermark
- *
- * @di: UBI device information
- * @vi: UBI volume information
- *
- * @gc_lnum: LEB number used for garbage collection
- * @rp_size: reserved pool size
- *
- * @space_bits: number of bits needed to record free or dirty space
- * @lpt_lnum_bits: number of bits needed to record a LEB number in the LPT
- * @lpt_offs_bits: number of bits needed to record an offset in the LPT
- * @lpt_spc_bits: number of bits needed to space in the LPT
- * @pcnt_bits: number of bits needed to record pnode or nnode number
- * @lnum_bits: number of bits needed to record LEB number
- * @nnode_sz: size of on-flash nnode
- * @pnode_sz: size of on-flash pnode
- * @ltab_sz: size of on-flash LPT lprops table
- * @lsave_sz: size of on-flash LPT save table
- * @pnode_cnt: number of pnodes
- * @nnode_cnt: number of nnodes
- * @lpt_hght: height of the LPT
- *
- * @lpt_lnum: LEB number of the root nnode of the LPT
- * @lpt_offs: offset of the root nnode of the LPT
- * @nhead_lnum: LEB number of LPT head
- * @nhead_offs: offset of LPT head
- * @big_lpt: flag that LPT is too big to write whole during commit
- * @space_fixup: flag indicating that free space in LEBs needs to be cleaned up
- * @lpt_sz: LPT size
- *
- * @ltab_lnum: LEB number of LPT's own lprops table
- * @ltab_offs: offset of LPT's own lprops table
- * @lpt: lprops table
- * @ltab: LPT's own lprops table
- * @lsave_cnt: number of LEB numbers in LPT's save table
- * @lsave_lnum: LEB number of LPT's save table
- * @lsave_offs: offset of LPT's save table
- * @lsave: LPT's save table
- * @lscan_lnum: LEB number of last LPT scan
- */
-struct ubifs_info
-{
-	ino_t highest_inum;
-	unsigned long long max_sqnum;
-
-	int jhead_cnt;
-	long long max_bud_bytes;
-
-	struct ubifs_zbranch zroot;
-	int ihead_lnum;
-	int ihead_offs;
-
-	int log_lebs;
-	int lpt_lebs;
-	int lpt_first;
-	int lpt_last;
-	int orph_lebs;
-	int main_lebs;
-	int main_first;
-	int default_compr;
-	int favor_lzo;
-	int favor_percent;
-
-	uint8_t key_hash_type;
-	uint32_t (*key_hash)(const char *str, int len);
-	int key_fmt;
-	int key_len;
-	int fanout;
-
-	int min_io_size;
-	int leb_size;
-	int leb_cnt;
-	int max_leb_cnt;
-
-	unsigned long long old_idx_sz;
-	struct ubifs_lp_stats lst;
-
-	int dead_wm;
-	int dark_wm;
-
-	struct ubi_dev_info di;
-	struct ubi_vol_info vi;
-
-	int gc_lnum;
-	long long rp_size;
-
-	int space_bits;
-	int lpt_lnum_bits;
-	int lpt_offs_bits;
-	int lpt_spc_bits;
-	int pcnt_bits;
-	int lnum_bits;
-	int nnode_sz;
-	int pnode_sz;
-	int ltab_sz;
-	int lsave_sz;
-	int pnode_cnt;
-	int nnode_cnt;
-	int lpt_hght;
-
-	int lpt_lnum;
-	int lpt_offs;
-	int nhead_lnum;
-	int nhead_offs;
-	int big_lpt;
-	int space_fixup;
-	long long lpt_sz;
-
-	int ltab_lnum;
-	int ltab_offs;
-	struct ubifs_lprops *lpt;
-	struct ubifs_lpt_lprops *ltab;
-	int lsave_cnt;
-	int lsave_lnum;
-	int lsave_offs;
-	int *lsave;
-	int lscan_lnum;
-
-};
-
-/**
- * ubifs_idx_node_sz - return index node size.
- * @c: the UBIFS file-system description object
- * @child_cnt: number of children of this index node
- */
-static inline int ubifs_idx_node_sz(const struct ubifs_info *c, int child_cnt)
-{
-	return UBIFS_IDX_NODE_SZ + (UBIFS_BRANCH_SZ + c->key_len) * child_cnt;
-}
-
-/**
- * ubifs_idx_branch - return pointer to an index branch.
- * @c: the UBIFS file-system description object
- * @idx: index node
- * @bnum: branch number
- */
-static inline
-struct ubifs_branch *ubifs_idx_branch(const struct ubifs_info *c,
-				      const struct ubifs_idx_node *idx,
-				      int bnum)
-{
-	return (struct ubifs_branch *)((void *)idx->branches +
-				       (UBIFS_BRANCH_SZ + c->key_len) * bnum);
-}
-
-#endif /* __UBIFS_H__ */
diff --git a/ubifs-utils/mkfs.ubifs/ubifs_common.h b/ubifs-utils/mkfs.ubifs/ubifs_common.h
deleted file mode 100644
index 958c20a..0000000
--- a/ubifs-utils/mkfs.ubifs/ubifs_common.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef __UBIFS_COMMON_H__
-#define __UBIFS_COMMON_H__
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <limits.h>
-#include <string.h>
-#include <stdint.h>
-#include <endian.h>
-#include <byteswap.h>
-#include <linux/types.h>
-#include <linux/fs.h>
-
-#include <getopt.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <errno.h>
-#include <libgen.h>
-#include <ctype.h>
-#include <uuid/uuid.h>
-#include <sys/file.h>
-
-#include <mtd/ubifs-media.h>
-
-#include "libubi.h"
-#include "defs.h"
-
-extern int verbose;
-extern int debug_level;
-
-#define dbg_msg(lvl, fmt, ...) do {if (debug_level >= lvl)                \
-	printf("ubifs: %s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__); \
-} while(0)
-
-#define err_msg(fmt, ...) ({                                \
-	fprintf(stderr, "Error: " fmt "\n", ##__VA_ARGS__); \
-	-1;                                                 \
-})
-
-#define sys_err_msg(fmt, ...) ({                                         \
-	int err_ = errno;                                                \
-	fprintf(stderr, "Error: " fmt "\n", ##__VA_ARGS__);              \
-	fprintf(stderr, "       %s (error %d)\n", strerror(err_), err_); \
-	-1;                                                              \
-})
-#endif
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 07/38] ubifs: move more functions into io lib
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (5 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 06/38] ubifs: introduce ubifs-utils/include and ubifs-utils/lib Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 08/38] ubifs: introduce a new tool ubifs_dump Dongsheng Yang
                   ` (30 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

Move some common functions in mkfs.ubifs.c to io.c
to let others can use them.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/include/io.h            |   4 ++
 ubifs-utils/lib/io.c                | 101 +++++++++++++++++++++++++++++++++++
 ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 102 +-----------------------------------
 3 files changed, 107 insertions(+), 100 deletions(-)

diff --git a/ubifs-utils/include/io.h b/ubifs-utils/include/io.h
index e24d0c6..920645d 100644
--- a/ubifs-utils/include/io.h
+++ b/ubifs-utils/include/io.h
@@ -10,6 +10,10 @@
 extern int out_fd;
 extern int out_ubi;
 extern libubi_t ubi;
+extern char *output;
 
 int write_leb(struct ubifs_info *c, int lnum, int len, void *buf);
+int close_target(void);
+int open_target(struct ubifs_info *c, int yes);
+int open_ubi(struct ubifs_info *c, const char *node);
 #endif
diff --git a/ubifs-utils/lib/io.c b/ubifs-utils/lib/io.c
index 7aba0a6..9817d2a 100644
--- a/ubifs-utils/lib/io.c
+++ b/ubifs-utils/lib/io.c
@@ -5,6 +5,107 @@
 int out_fd;
 int out_ubi;
 libubi_t ubi;
+char *output;
+
+/**
+ * check_volume_empty - check if the UBI volume is empty.
+ *
+ * This function checks if the UBI volume is empty by looking if its LEBs are
+ * mapped or not.
+ *
+ * Returns %0 in case of success, %1 is the volume is not empty,
+ * and a negative error code in case of failure.
+ */
+static int check_volume_empty(struct ubifs_info *c)
+{
+	int lnum, err;
+
+	for (lnum = 0; lnum < c->vi.rsvd_lebs; lnum++) {
+		err = ubi_is_mapped(out_fd, lnum);
+		if (err < 0)
+			return err;
+		if (err == 1)
+			return 1;
+	}
+	return 0;
+}
+
+/**
+ * open_ubi - open the UBI volume.
+ * @node: name of the UBI volume character device to fetch information about
+ *
+ * Returns %0 in case of success and %-1 in case of failure
+ */
+int open_ubi(struct ubifs_info *c, const char *node)
+{
+	struct stat st;
+
+	if (stat(node, &st) || !S_ISCHR(st.st_mode))
+		return -1;
+
+	ubi = libubi_open();
+	if (!ubi)
+		return -1;
+	if (ubi_get_vol_info(ubi, node, &c->vi))
+		return -1;
+	if (ubi_get_dev_info1(ubi, c->vi.dev_num, &c->di))
+		return -1;
+	return 0;
+}
+
+/**
+ * open_target - open the output target.
+ * @yes: always ansure yes
+ *
+ * Open the output target. The target can be an UBI volume
+ * or a file.
+ *
+ * Returns %0 in case of success and %-1 in case of failure.
+ */
+int open_target(struct ubifs_info *c, int yes)
+{
+	if (out_ubi) {
+		out_fd = open(output, O_RDWR | O_EXCL);
+
+		if (out_fd == -1)
+			return sys_err_msg("cannot open the UBI volume '%s'",
+					   output);
+		if (ubi_set_property(out_fd, UBI_VOL_PROP_DIRECT_WRITE, 1))
+			return sys_err_msg("ubi_set_property failed");
+
+		if (!yes && check_volume_empty(c)) {
+			if (!prompt("UBI volume is not empty.  Format anyways?", false))
+				return err_msg("UBI volume is not empty");
+		}
+	} else {
+		out_fd = open(output, O_CREAT | O_RDWR | O_TRUNC,
+			      S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
+		if (out_fd == -1)
+			return sys_err_msg("cannot create output file '%s'",
+					   output);
+	}
+	return 0;
+}
+
+/**
+ * close_target - close the output target.
+ *
+ * Close the output target. If the target was an UBI
+ * volume, also close libubi.
+ *
+ * Returns %0 in case of success and %-1 in case of failure.
+ */
+int close_target(void)
+{
+	if (ubi)
+		libubi_close(ubi);
+	if (out_fd >= 0 && close(out_fd) == -1)
+		return sys_err_msg("cannot close the target '%s'", output);
+	if (output)
+		free(output);
+	return 0;
+}
+
 
 /**
  * write_leb - copy the image of a LEB to the output target.
diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index b2df5b1..8ac09f2 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -110,7 +110,6 @@ int yes;
 static char *root;
 static int root_len;
 static struct stat root_st;
-static char *output;
 static int squash_owner;
 static int do_create_inum_attr;
 
@@ -446,28 +445,6 @@ static long long get_bytes(const char *str)
 
 	return bytes;
 }
-/**
- * open_ubi - open the UBI volume.
- * @node: name of the UBI volume character device to fetch information about
- *
- * Returns %0 in case of success and %-1 in case of failure
- */
-static int open_ubi(const char *node)
-{
-	struct stat st;
-
-	if (stat(node, &st) || !S_ISCHR(st.st_mode))
-		return -1;
-
-	ubi = libubi_open();
-	if (!ubi)
-		return -1;
-	if (ubi_get_vol_info(ubi, node, &c->vi))
-		return -1;
-	if (ubi_get_dev_info1(ubi, c->vi.dev_num, &c->di))
-		return -1;
-	return 0;
-}
 
 static int get_options(int argc, char**argv)
 {
@@ -643,7 +620,7 @@ static int get_options(int argc, char**argv)
 	if (!output)
 		return err_msg("not output device or file specified");
 
-	out_ubi = !open_ubi(output);
+	out_ubi = !open_ubi(c, output);
 
 	if (out_ubi) {
 		c->min_io_size = c->di.min_io_size;
@@ -2248,81 +2225,6 @@ static int write_orphan_area(void)
 	return 0;
 }
 
-/**
- * check_volume_empty - check if the UBI volume is empty.
- *
- * This function checks if the UBI volume is empty by looking if its LEBs are
- * mapped or not.
- *
- * Returns %0 in case of success, %1 is the volume is not empty,
- * and a negative error code in case of failure.
- */
-static int check_volume_empty(void)
-{
-	int lnum, err;
-
-	for (lnum = 0; lnum < c->vi.rsvd_lebs; lnum++) {
-		err = ubi_is_mapped(out_fd, lnum);
-		if (err < 0)
-			return err;
-		if (err == 1)
-			return 1;
-	}
-	return 0;
-}
-
-/**
- * open_target - open the output target.
- *
- * Open the output target. The target can be an UBI volume
- * or a file.
- *
- * Returns %0 in case of success and %-1 in case of failure.
- */
-static int open_target(void)
-{
-	if (out_ubi) {
-		out_fd = open(output, O_RDWR | O_EXCL);
-
-		if (out_fd == -1)
-			return sys_err_msg("cannot open the UBI volume '%s'",
-					   output);
-		if (ubi_set_property(out_fd, UBI_VOL_PROP_DIRECT_WRITE, 1))
-			return sys_err_msg("ubi_set_property failed");
-
-		if (!yes && check_volume_empty()) {
-			if (!prompt("UBI volume is not empty.  Format anyways?", false))
-				return err_msg("UBI volume is not empty");
-		}
-	} else {
-		out_fd = open(output, O_CREAT | O_RDWR | O_TRUNC,
-			      S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
-		if (out_fd == -1)
-			return sys_err_msg("cannot create output file '%s'",
-					   output);
-	}
-	return 0;
-}
-
-
-/**
- * close_target - close the output target.
- *
- * Close the output target. If the target was an UBI
- * volume, also close libubi.
- *
- * Returns %0 in case of success and %-1 in case of failure.
- */
-static int close_target(void)
-{
-	if (ubi)
-		libubi_close(ubi);
-	if (out_fd >= 0 && close(out_fd) == -1)
-		return sys_err_msg("cannot close the target '%s'", output);
-	if (output)
-		free(output);
-	return 0;
-}
 
 /**
  * init - initialize things.
@@ -2473,7 +2375,7 @@ int main(int argc, char *argv[])
 	if (err)
 		return err;
 
-	err = open_target();
+	err = open_target(c, yes);
 	if (err)
 		return err;
 
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 08/38] ubifs: introduce a new tool ubifs_dump
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (6 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 07/38] ubifs: move more functions into io lib Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 09/38] ubifs: introduce list.h Dongsheng Yang
                   ` (29 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

Init a new tool named as ubifs_dump

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 Makefile                            |  8 ++++-
 ubifs-utils/ubifs_dump/ubifs_dump.c | 68 +++++++++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+), 1 deletion(-)
 create mode 100644 ubifs-utils/ubifs_dump/ubifs_dump.c

diff --git a/Makefile b/Makefile
index ad0526f..a1aaa6e 100644
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,8 @@ UBI_BINS = \
 	ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \
 	ubidetach ubinize ubiformat ubirename mtdinfo ubirsvol ubiblock
 UBIFS_BINS = \
-	mkfs.ubifs/mkfs.ubifs
+	mkfs.ubifs/mkfs.ubifs \
+	ubifs_dump/ubifs_dump
 JFFSX_BINS = \
 	mkfs.jffs2 sumtool jffs2reader jffs2dump
 NAND_BINS = \
@@ -128,6 +129,11 @@ $(foreach v,$(UBI_BINS),$(eval $(call mkdep,ubi-utils/,$(v),libubi.a ubiutils-co
 #
 $(foreach v,crc16.o lpt.o compr.o devtable.o io.o hashtable.o hashtable_itr.o,$(eval UBIFS_LIBS += ../lib/$(v)))
 
+obj-ubifs_dump = $(UBIFS_LIBS)
+LDFLAGS_ubifs_dump = $(ZLIBLDFLAGS) $(LZOLDFLAGS) $(UUIDLDFLAGS)
+LDLIBS_ubifs_dump = -lz -llzo2 -lm -luuid
+$(call mkdep,ubifs-utils/ubifs_dump/,ubifs_dump,,ubi-utils/libubi.a)
+
 obj-mkfs.ubifs = $(UBIFS_LIBS)
 LDFLAGS_mkfs.ubifs = $(ZLIBLDFLAGS) $(LZOLDFLAGS) $(UUIDLDFLAGS)
 LDLIBS_mkfs.ubifs = -lz $(LZOLDLIBS) -lm -luuid
diff --git a/ubifs-utils/ubifs_dump/ubifs_dump.c b/ubifs-utils/ubifs_dump/ubifs_dump.c
new file mode 100644
index 0000000..bbe1269
--- /dev/null
+++ b/ubifs-utils/ubifs_dump/ubifs_dump.c
@@ -0,0 +1,68 @@
+#include "ubifs_common.h"
+#define PROGRAM_NAME "ubifs-dump"
+#include "common.h"
+#include "io.h"
+
+static const char *optstring = "";
+
+static const struct option longopts[] = {
+	{NULL, 0, NULL, 0}
+};
+
+struct ubifs_info info_;
+static struct ubifs_info *c = &info_;
+
+static int get_options(int argc, char**argv)
+{
+	int opt, i;
+
+	while (1) {
+		opt = getopt_long(argc, argv, optstring, longopts, &i);
+		if (opt == -1)
+			break;
+		switch (opt) {
+		default:
+			break;
+		}
+	}
+
+	if (optind != argc && !output)
+		output = xstrdup(argv[optind]);
+
+	if (!output)
+		return err_msg("not output device or file specified");
+
+	if (open_ubi(c, output))
+		return err_msg("open ubi (%s) failed.", output);
+
+	return 0;
+}
+
+static int dump()
+{
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	int err;
+
+	err = get_options(argc, argv);
+	if (err)
+		return err;
+	err = open_target(c, 1);
+	if (err)
+		return err;
+
+	err = dump();
+	if (err) {
+		close_target();
+		return err;
+	}
+
+	err = close_target();
+	if (err)
+		return err;
+
+	return 0;
+}
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 09/38] ubifs: introduce list.h
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (7 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 08/38] ubifs: introduce a new tool ubifs_dump Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 10/38] ubifs: copy some important data in ubifs.h from kernel to ubifs-utils Dongsheng Yang
                   ` (28 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

Copy the list.h from kernel to ubifs-utils/

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/include/list.h | 484 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 484 insertions(+)
 create mode 100644 ubifs-utils/include/list.h

diff --git a/ubifs-utils/include/list.h b/ubifs-utils/include/list.h
new file mode 100644
index 0000000..0cffa33
--- /dev/null
+++ b/ubifs-utils/include/list.h
@@ -0,0 +1,484 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+#define LIST_POISON1  ((struct list_head *) 0x00100100)
+#define LIST_POISON2  ((struct list_head *) 0x00200200)
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+	struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+	struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void INIT_LIST_HEAD(struct list_head *list)
+{
+	list->next = list;
+	list->prev = list;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+#ifndef CONFIG_DEBUG_LIST
+static inline void __list_add(struct list_head *xnew,
+			      struct list_head *prev,
+			      struct list_head *next)
+{
+	next->prev = xnew;
+	xnew->next = next;
+	xnew->prev = prev;
+	prev->next = xnew;
+}
+#else
+extern void __list_add(struct list_head *xnew,
+			      struct list_head *prev,
+			      struct list_head *next);
+#endif
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+#ifndef CONFIG_DEBUG_LIST
+static inline void list_add(struct list_head *xnew, struct list_head *head)
+{
+	__list_add(xnew, head, head->next);
+}
+#else
+extern void list_add(struct list_head *xnew, struct list_head *head);
+#endif
+
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *xnew, struct list_head *head)
+{
+	__list_add(xnew, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+	next->prev = prev;
+	prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+#ifndef CONFIG_DEBUG_LIST
+static inline void list_del(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+	entry->next = LIST_POISON1;
+	entry->prev = LIST_POISON2;
+}
+#else
+extern void list_del(struct list_head *entry);
+#endif
+
+/**
+ * list_replace - replace old entry by new one
+ * @old : the element to be replaced
+ * @new : the new element to insert
+ * Note: if 'old' was empty, it will be overwritten.
+ */
+static inline void list_replace(struct list_head *old,
+				struct list_head *xnew)
+{
+	xnew->next = old->next;
+	xnew->next->prev = xnew;
+	xnew->prev = old->prev;
+	xnew->prev->next = xnew;
+}
+
+static inline void list_replace_init(struct list_head *old,
+					struct list_head *xnew)
+{
+	list_replace(old, xnew);
+	INIT_LIST_HEAD(old);
+}
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+	INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+        __list_del(list->prev, list->next);
+        list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+				  struct list_head *head)
+{
+        __list_del(list->prev, list->next);
+        list_add_tail(list, head);
+}
+
+/**
+ * list_is_last - tests whether @list is the last entry in list @head
+ * @list: the entry to test
+ * @head: the head of the list
+ */
+static inline int list_is_last(const struct list_head *list,
+				const struct list_head *head)
+{
+	return list->next == head;
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+	return head->next == head;
+}
+
+/**
+ * list_empty_careful - tests whether a list is empty and not being modified
+ * @head: the list to test
+ *
+ * Description:
+ * tests whether a list is empty _and_ checks that no other CPU might be
+ * in the process of modifying either member (next or prev)
+ *
+ * NOTE: using list_empty_careful() without synchronization
+ * can only be safe if the only activity that can happen
+ * to the list entry is list_del_init(). Eg. it cannot be used
+ * if another CPU could re-list_add() it.
+ */
+static inline int list_empty_careful(const struct list_head *head)
+{
+	struct list_head *next = head->next;
+	return (next == head) && (next == head->prev);
+}
+
+static inline void __list_splice(const struct list_head *list,
+				 struct list_head *prev,
+				 struct list_head *next)
+{
+	struct list_head *first = list->next;
+	struct list_head *last = list->prev;
+
+	first->prev = prev;
+	prev->next = first;
+
+	last->next = next;
+	next->prev = last;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+	if (!list_empty(list))
+		__list_splice(list, head, head->next);
+}
+
+/**
+ * list_splice_tail - join two lists, each list being a queue
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice_tail(struct list_head *list,
+				struct list_head *head)
+{
+	if (!list_empty(list))
+		__list_splice(list, head->prev, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+				    struct list_head *head)
+{
+	if (!list_empty(list)) {
+		__list_splice(list, head, head->next);
+		INIT_LIST_HEAD(list);
+	}
+}
+
+/**
+ * list_splice_tail_init - join two lists and reinitialise the emptied list
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * Each of the lists is a queue.
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_tail_init(struct list_head *list,
+					 struct list_head *head)
+{
+	if (!list_empty(list)) {
+		__list_splice(list, head->prev, head);
+		INIT_LIST_HEAD(list);
+	}
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:	the &struct list_head pointer.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+	container_of(ptr, type, member)
+
+/**
+ * list_first_entry - get the first element from a list
+ * @ptr:	the list head to take the element from.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_first_entry(ptr, type, member) \
+	list_entry((ptr)->next, type, member)
+
+/**
+ * list_next_entry - get the next element from a list
+ * @ptr:	the list head to take the element from.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Note, that next is expected to be not null.
+ */
+#define list_next_entry(ptr, member) \
+	list_entry((ptr)->member.next, typeof(*ptr), member)
+
+/**
+ * list_for_each	-	iterate over a list
+ * @pos:	the &struct list_head to use as a loop cursor.
+ * @head:	the head for your list.
+ */
+#define list_for_each(pos, head) \
+	for (pos = (head)->next; pos != (head); \
+        	pos = pos->next)
+
+/**
+ * __list_for_each	-	iterate over a list
+ * @pos:	the &struct list_head to use as a loop cursor.
+ * @head:	the head for your list.
+ *
+ * This variant differs from list_for_each() in that it's the
+ * simplest possible list iteration code, no prefetching is done.
+ * Use this for code that knows the list to be very short (empty
+ * or 1 entry) most of the time.
+ */
+#define __list_for_each(pos, head) \
+	for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_prev	-	iterate over a list backwards
+ * @pos:	the &struct list_head to use as a loop cursor.
+ * @head:	the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+	for (pos = (head)->prev; pos != (head); \
+        	pos = pos->prev)
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos:	the &struct list_head to use as a loop cursor.
+ * @n:		another &struct list_head to use as temporary storage
+ * @head:	the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+	for (pos = (head)->next, n = pos->next; pos != (head); \
+		pos = n, n = pos->next)
+
+/**
+ * list_for_each_entry	-	iterate over list of given type
+ * @pos:	the type * to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member)				\
+	for (pos = list_entry((head)->next, typeof(*pos), member);	\
+	     &pos->member != (head); 	\
+	     pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos:	the type * to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_reverse(pos, head, member)			\
+	for (pos = list_entry((head)->prev, typeof(*pos), member);	\
+	     &pos->member != (head); 	\
+	     pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
+ * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue
+ * @pos:	the type * to use as a start point
+ * @head:	the head of the list
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Prepares a pos entry for use as a start point in list_for_each_entry_continue.
+ */
+#define list_prepare_entry(pos, head, member) \
+	((pos) ? : list_entry(head, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue - continue iteration over list of given type
+ * @pos:	the type * to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Continue to iterate over list of given type, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue(pos, head, member) 		\
+	for (pos = list_entry(pos->member.next, typeof(*pos), member);	\
+	     &pos->member != (head);	\
+	     pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_from - iterate over list of given type from the current point
+ * @pos:	the type * to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing from current position.
+ */
+#define list_for_each_entry_from(pos, head, member) 			\
+	for (; &pos->member != (head);	\
+	     pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos:	the type * to use as a loop cursor.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member)			\
+	for (pos = list_entry((head)->next, typeof(*pos), member),	\
+		n = list_entry(pos->member.next, typeof(*pos), member);	\
+	     &pos->member != (head); 					\
+	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_continue
+ * @pos:	the type * to use as a loop cursor.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing after current point,
+ * safe against removal of list entry.
+ */
+#define list_for_each_entry_safe_continue(pos, n, head, member) 		\
+	for (pos = list_entry(pos->member.next, typeof(*pos), member), 		\
+		n = list_entry(pos->member.next, typeof(*pos), member);		\
+	     &pos->member != (head);						\
+	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_from
+ * @pos:	the type * to use as a loop cursor.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type from current point, safe against
+ * removal of list entry.
+ */
+#define list_for_each_entry_safe_from(pos, n, head, member) 			\
+	for (n = list_entry(pos->member.next, typeof(*pos), member);		\
+	     &pos->member != (head);						\
+	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_reverse
+ * @pos:	the type * to use as a loop cursor.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Iterate backwards over list of given type, safe against removal
+ * of list entry.
+ */
+#define list_for_each_entry_safe_reverse(pos, n, head, member)		\
+	for (pos = list_entry((head)->prev, typeof(*pos), member),	\
+		n = list_entry(pos->member.prev, typeof(*pos), member);	\
+	     &pos->member != (head); 					\
+	     pos = n, n = list_entry(n->member.prev, typeof(*n), member))
+
+#endif
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 10/38] ubifs: copy some important data in ubifs.h from kernel to ubifs-utils
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (8 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 09/38] ubifs: introduce list.h Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 11/38] ubifs: copy some important functions in key.h " Dongsheng Yang
                   ` (27 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

There are some definitions in ubifs.h in kernel we need but
not in userspace currently. Then copy it here.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/include/ubifs.h | 96 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 91 insertions(+), 5 deletions(-)

diff --git a/ubifs-utils/include/ubifs.h b/ubifs-utils/include/ubifs.h
index 2f080a8..1678663 100644
--- a/ubifs-utils/include/ubifs.h
+++ b/ubifs-utils/include/ubifs.h
@@ -25,6 +25,10 @@
 #ifndef __UBIFS_H__
 #define __UBIFS_H__
 
+#include "defs.h"
+#include "list.h"
+#include "libubi.h"
+
 /* Maximum logical eraseblock size in bytes */
 #define UBIFS_MAX_LEB_SZ (2*1024*1024)
 
@@ -34,6 +38,7 @@
 /* Largest key size supported in this implementation */
 #define CUR_MAX_KEY_LEN UBIFS_SK_LEN
 
+#define NONDATA_JHEADS_CNT 2
 /*
  * There is no notion of truncation key because truncation nodes do not exist
  * in TNC. However, when replaying, it is handy to introduce fake "truncation"
@@ -41,6 +46,7 @@
  * %UBIFS_TRUN_KEY type.
  */
 #define UBIFS_TRUN_KEY UBIFS_KEY_TYPES_CNT
+#define UBIFS_INVALID_KEY UBIFS_KEY_TYPES_CNT
 
 /*
  * How much a directory entry/extended attribute entry adds to the parent/host
@@ -94,25 +100,34 @@ enum {
  * @free: amount of free space in bytes
  * @dirty: amount of dirty space in bytes
  * @flags: LEB properties flags (see above)
+ * @lnum: LEB number
+ * @list: list of same-category lprops (for LPROPS_EMPTY and LPROPS_FREEABLE)
+ * @hpos: heap position in heap of same-category lprops (other categories)
  */
-struct ubifs_lprops
-{
+struct ubifs_lprops {
 	int free;
 	int dirty;
 	int flags;
+	int lnum;
+	union {
+		struct list_head list;
+		int hpos;
+	};
 };
 
 /**
  * struct ubifs_lpt_lprops - LPT logical eraseblock properties.
  * @free: amount of free space in bytes
  * @dirty: amount of dirty space in bytes
+ * @tgc: trivial GC flag (1 => unmap after commit end)
+ * @cmt: commit flag (1 => reserved for commit)
  */
-struct ubifs_lpt_lprops
-{
+struct ubifs_lpt_lprops {
 	int free;
 	int dirty;
+	unsigned tgc:1;
+	unsigned cmt:1;
 };
-
 struct ubifs_nnode;
 
 /**
@@ -263,6 +278,12 @@ struct ubifs_znode
 	struct ubifs_zbranch zbranch[];
 };
 
+enum {
+	LPT_SCAN_CONTINUE = 0,
+	LPT_SCAN_ADD = 1,
+	LPT_SCAN_STOP = 2,
+};
+
 /**
  * struct ubifs_info - UBIFS file-system description data structure
  * (per-superblock).
@@ -401,6 +422,7 @@ struct ubifs_info
 	int pnode_cnt;
 	int nnode_cnt;
 	int lpt_hght;
+	void *lpt_nod_buf;
 
 	int lpt_lnum;
 	int lpt_offs;
@@ -420,8 +442,68 @@ struct ubifs_info
 	int *lsave;
 	int lscan_lnum;
 
+	struct ubifs_nnode *nroot;
+	struct ubifs_cnode *lpt_cnext;
+
+	int min_idx_node_sz;
+	int max_idx_node_sz;
+
+	int max_znode_sz;
+};
+/**
+ * struct ubifs_scan_node - UBIFS scanned node information.
+ * @list: list of scanned nodes
+ * @key: key of node scanned (if it has one)
+ * @sqnum: sequence number
+ * @type: type of node scanned
+ * @offs: offset with LEB of node scanned
+ * @len: length of node scanned
+ * @node: raw node
+ */
+struct ubifs_scan_node {
+	struct list_head list;
+	union ubifs_key key;
+	unsigned long long sqnum;
+	int type;
+	int offs;
+	int len;
+	void *node;
+};
+
+/**
+ * struct ubifs_scan_leb - UBIFS scanned LEB information.
+ * @lnum: logical eraseblock number
+ * @nodes_cnt: number of nodes scanned
+ * @nodes: list of struct ubifs_scan_node
+ * @endpt: end point (and therefore the start of empty space)
+ * @buf: buffer containing entire LEB scanned
+ */
+struct ubifs_scan_leb {
+	int lnum;
+	int nodes_cnt;
+	struct list_head nodes;
+	int endpt;
+	void *buf;
 };
 
+/*
+ * 'ubifs_scan_a_node()' return values.
+ *
+ * SCANNED_GARBAGE:  scanned garbage
+ * SCANNED_EMPTY_SPACE: scanned empty space
+ * SCANNED_A_NODE: scanned a valid node
+ * SCANNED_A_CORRUPT_NODE: scanned a corrupted node
+ * SCANNED_A_BAD_PAD_NODE: scanned a padding node with invalid pad length
+ *
+ * Greater than zero means: 'scanned that number of padding bytes'
+ */
+enum {
+	SCANNED_GARBAGE        = 0,
+	SCANNED_EMPTY_SPACE    = -1,
+	SCANNED_A_NODE         = -2,
+	SCANNED_A_CORRUPT_NODE = -3,
+	SCANNED_A_BAD_PAD_NODE = -4,
+};
 /**
  * ubifs_idx_node_sz - return index node size.
  * @c: the UBIFS file-system description object
@@ -447,4 +529,8 @@ struct ubifs_branch *ubifs_idx_branch(const struct ubifs_info *c,
 				       (UBIFS_BRANCH_SZ + c->key_len) * bnum);
 }
 
+/* Callback used by the 'ubifs_lpt_scan_nolock()' function */
+typedef int (*ubifs_lpt_scan_callback)(struct ubifs_info *c,
+				       const struct ubifs_lprops *lprops,
+				       int in_tree, void *data);
 #endif /* __UBIFS_H__ */
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 11/38] ubifs: copy some important functions in key.h from kernel to ubifs-utils
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (9 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 10/38] ubifs: copy some important data in ubifs.h from kernel to ubifs-utils Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 12/38] ubifs: ubifs_dump: add dump_ch and dump_node functions Dongsheng Yang
                   ` (26 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

We need some more functions in key.h, then copy it from kernel.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/include/key.h | 76 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 1 deletion(-)

diff --git a/ubifs-utils/include/key.h b/ubifs-utils/include/key.h
index 39379fd..1b61928 100644
--- a/ubifs-utils/include/key.h
+++ b/ubifs-utils/include/key.h
@@ -37,6 +37,8 @@
 #ifndef __UBIFS_KEY_H__
 #define __UBIFS_KEY_H__
 
+#include "defs.h"
+
 /**
  * key_mask_hash - mask a valid hash value.
  * @val: value to be masked
@@ -107,7 +109,7 @@ static inline void ino_key_init(union ubifs_key *key, ino_t inum)
  * @inum: parent inode number
  * @nm: direntry name and length
  */
-static inline void dent_key_init(const struct ubifs_info *c,
+static inline void dent_key_init(const struct ubifs_info *c __attribute__((unused)),
 				 union ubifs_key *key, ino_t inum,
 				 const struct qstr *nm)
 {
@@ -204,4 +206,76 @@ static inline int keys_cmp(const union ubifs_key *key1,
 	return 0;
 }
 
+/**
+ * key_read - transform a key to in-memory format.
+ * @c: UBIFS file-system description object
+ * @from: the key to transform
+ * @to: the key to store the result
+ */
+static inline void key_read(const struct ubifs_info *c __attribute__((unused)), const void *from,
+			    union ubifs_key *to)
+{
+	const union ubifs_key *f = from;
+
+	to->u32[0] = le32_to_cpu(f->j32[0]);
+	to->u32[1] = le32_to_cpu(f->j32[1]);
+}
+
+/**
+ * invalid_key_init - initialize invalid node key.
+ * @c: UBIFS file-system description object
+ * @key: key to initialize
+ *
+ * This is a helper function which marks a @key object as invalid.
+ */
+static inline void invalid_key_init(const struct ubifs_info *c __attribute__((unused)),
+				    union ubifs_key *key)
+{
+	key->u32[0] = 0xDEADBEAF;
+	key->u32[1] = UBIFS_INVALID_KEY;
+}
+/**
+ * key_type - get key type.
+ * @c: UBIFS file-system description object
+ * @key: key to get type of
+ */
+static inline int key_type(const struct ubifs_info *c __attribute__((unused)),
+			   const union ubifs_key *key)
+{
+	return key->u32[1] >> UBIFS_S_KEY_BLOCK_BITS;
+}
+
+/*
+ * key_hash - get directory entry hash.
+ * @c: UBIFS file-system description object
+ * @key: the key to get hash from
+ */
+static inline uint32_t key_hash(const struct ubifs_info *c __attribute__((unused)),
+				const union ubifs_key *key)
+{
+	return key->u32[1] & UBIFS_S_KEY_HASH_MASK;
+}
+
+/**
+ * key_inum - fetch inode number from key.
+ * @c: UBIFS file-system description object
+ * @k: key to fetch inode number from
+ */
+static inline ino_t key_inum(const struct ubifs_info *c __attribute__((unused)), const void *k)
+{
+	const union ubifs_key *key = k;
+
+	return key->u32[0];
+}
+
+/**
+ * key_block - get data block number.
+ * @c: UBIFS file-system description object
+ * @key: the key to get the block number from
+ */
+static inline unsigned int key_block(const struct ubifs_info *c __attribute__((unused)),
+				     const union ubifs_key *key)
+{
+	return key->u32[1] & UBIFS_S_KEY_BLOCK_MASK;
+}
 #endif /* !__UBIFS_KEY_H__ */
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 12/38] ubifs: ubifs_dump: add dump_ch and dump_node functions
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (10 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 11/38] ubifs: copy some important functions in key.h " Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 13/38] ubifs: defs.h: introduce some compatible definition for printk class Dongsheng Yang
                   ` (25 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/ubifs_dump/ubifs_dump.c | 337 ++++++++++++++++++++++++++++++++++++
 1 file changed, 337 insertions(+)

diff --git a/ubifs-utils/ubifs_dump/ubifs_dump.c b/ubifs-utils/ubifs_dump/ubifs_dump.c
index bbe1269..a510aeb 100644
--- a/ubifs-utils/ubifs_dump/ubifs_dump.c
+++ b/ubifs-utils/ubifs_dump/ubifs_dump.c
@@ -1,7 +1,11 @@
 #include "ubifs_common.h"
 #define PROGRAM_NAME "ubifs-dump"
 #include "common.h"
+
 #include "io.h"
+#include "key.h"
+
+#define DBG_KEY_BUF_LEN		48
 
 static const char *optstring = "";
 
@@ -38,6 +42,339 @@ static int get_options(int argc, char**argv)
 	return 0;
 }
 
+static const char *node_type_to_str[] = {
+		"UBIFS_INO_NODE",
+		"UBIFS_DATA_NODE",
+		"UBIFS_DENT_NODE",
+		"UBIFS_XENT_NODE",
+		"UBIFS_TRUN_NODE",
+		"UBIFS_PAD_NODE",
+		"UBIFS_SB_NODE",
+		"UBIFS_MST_NODE",
+		"UBIFS_REF_NODE",
+		"UBIFS_IDX_NODE",
+		"UBIFS_CS_NODE",
+		"UBIFS_ORPH_NODE"
+};
+
+static const char *get_key_type(int type)
+{
+	return node_type_to_str[type];
+}
+
+static const char *group_type_to_str[] = {
+		"UBIFS_NO_NODE_GROUP",
+		"UBIFS_IN_NODE_GROUP",
+		"UBIFS_LAST_OF_NODE_GROUP"
+};
+
+static const char *hash_type_to_str[] = {
+		"UBIFS_KEY_HASH_R5",
+		"UBIFS_KEY_HASH_TEST"
+};
+
+static const char *compr_type_to_str[] = {
+		"UBIFS_COMPR_NONE",
+		"UBIFS_COMPR_LZO",
+		"UBIFS_COMPR_ZLIB",
+		"UBIFS_COMPR_TYPES_CNT",
+};
+
+static const char *key_fmt_to_str[] = {
+	"UBIFS_SIMPLE_KEY_FMT"
+};
+
+const char *dbg_snprintf_key(const struct ubifs_info *c,
+			     const union ubifs_key *key, char *buffer, int len)
+{
+	char *p = buffer;
+	int type = key_type(c, key);
+
+	if (c->key_fmt == UBIFS_SIMPLE_KEY_FMT) {
+		switch (type) {
+
+		case UBIFS_INO_KEY:
+			len -= snprintf(p, len, "(%lu, %s)",
+					(unsigned long)key_inum(c, key),
+					get_key_type(type));
+			break;
+		case UBIFS_DENT_KEY:
+		case UBIFS_XENT_KEY:
+			len -= snprintf(p, len, "(%lu, %s, %#08x)",
+					(unsigned long)key_inum(c, key),
+					get_key_type(type), key_hash(c, key));
+			break;
+		case UBIFS_DATA_KEY:
+			len -= snprintf(p, len, "(%lu, %s, %u)",
+					(unsigned long)key_inum(c, key),
+					get_key_type(type), key_block(c, key));
+			break;
+		case UBIFS_TRUN_KEY:
+			len -= snprintf(p, len, "(%lu, %s)",
+					(unsigned long)key_inum(c, key),
+					get_key_type(type));
+			break;
+		default:
+			len -= snprintf(p, len, "(bad key type: %#08x, %#08x)",
+					key->u32[0], key->u32[1]);
+		}
+	} else
+		len -= snprintf(p, len, "bad key format %d", c->key_fmt);
+	ubifs_assert(len > 0);
+	return p;
+}
+
+static void show_ch(const struct ubifs_ch *ch) 
+{ 
+	printf("\tCommon header: \n");
+        printf("\tmagic \t\t\t\t%#x\n", le32_to_cpu(ch->magic)); 
+        printf("\tcrc \t\t\t\t%#x\n", le32_to_cpu(ch->crc)); 
+        printf("\tnode_type \t\t\t%d (%s)\n", ch->node_type, 
+               node_type_to_str[ch->node_type]); 
+        printf("\tgroup_type \t\t\t%d (%s)\n", ch->group_type, 
+               group_type_to_str[ch->group_type]); 
+        printf("\tsqnum \t\t\t\t%llu\n", 
+               (unsigned long long)le64_to_cpu(ch->sqnum)); 
+        printf("\tlen \t\t\t\t%u\n", le32_to_cpu(ch->len)); 
+} 
+
+void dump_node(const struct ubifs_info *c, const void *node)
+{
+	int i, n;
+	union ubifs_key key;
+	const struct ubifs_ch *ch = node;
+	char key_buf[DBG_KEY_BUF_LEN];
+
+	show_ch(node);
+
+	switch (ch->node_type) {
+	case UBIFS_PAD_NODE:
+	{
+		const struct ubifs_pad_node *pad = node;
+
+		printf("\t\tpad_len \t\t\t%u\n", le32_to_cpu(pad->pad_len));
+		break;
+	}
+	case UBIFS_SB_NODE:
+	{
+		const struct ubifs_sb_node *sup = node;
+		unsigned int sup_flags = le32_to_cpu(sup->flags);
+		char uuid[40];
+
+		uuid_unparse_upper(sup->uuid, uuid);
+		printf("\t\tUUID \t\t\t\t%s\n", uuid);
+		printf("\t\tkey_hash \t\t\t%d (%s)\n",
+		       (int)sup->key_hash, hash_type_to_str[sup->key_hash]);
+		printf("\t\tkey_fmt \t\t\t%d (%s)\n",
+		       (int)sup->key_fmt, key_fmt_to_str[sup->key_fmt]);
+		printf("\t\tflags \t\t\t\t%#x\n", sup_flags);
+		printf("\t\tbig_lpt \t\t\t%u\n",
+		       !!(sup_flags & UBIFS_FLG_BIGLPT));
+		printf("\t\tspace_fixup \t\t\t%u\n",
+		       !!(sup_flags & UBIFS_FLG_SPACE_FIXUP));
+		printf("\t\tmin_io_size \t\t\t%u\n", le32_to_cpu(sup->min_io_size));
+		printf("\t\tleb_size \t\t\t%u\n", le32_to_cpu(sup->leb_size));
+		printf("\t\tleb_cnt \t\t\t%u\n", le32_to_cpu(sup->leb_cnt));
+		printf("\t\tmax_leb_cnt \t\t\t%u\n", le32_to_cpu(sup->max_leb_cnt));
+		printf("\t\tmax_bud_bytes \t\t\t%llu\n",
+		       (unsigned long long)le64_to_cpu(sup->max_bud_bytes));
+		printf("\t\tlog_lebs \t\t\t%u\n", le32_to_cpu(sup->log_lebs));
+		printf("\t\tlpt_lebs \t\t\t%u\n", le32_to_cpu(sup->lpt_lebs));
+		printf("\t\torph_lebs \t\t\t%u\n", le32_to_cpu(sup->orph_lebs));
+		printf("\t\tjhead_cnt \t\t\t%u\n", le32_to_cpu(sup->jhead_cnt));
+		printf("\t\tfanout \t\t\t\t%u\n", le32_to_cpu(sup->fanout));
+		printf("\t\tlsave_cnt \t\t\t%u\n", le32_to_cpu(sup->lsave_cnt));
+		printf("\t\tdefault_compr \t\t\t%u\n",
+		       (int)le16_to_cpu(sup->default_compr));
+		printf("\t\trp_size \t\t\t%llu\n",
+		       (unsigned long long)le64_to_cpu(sup->rp_size));
+		printf("\t\trp_uid \t\t\t\t%u\n", le32_to_cpu(sup->rp_uid));
+		printf("\t\trp_gid \t\t\t\t%u\n", le32_to_cpu(sup->rp_gid));
+		printf("\t\tfmt_version \t\t\t%u\n", le32_to_cpu(sup->fmt_version));
+		printf("\t\ttime_gran \t\t\t%u\n", le32_to_cpu(sup->time_gran));
+		break;
+	}
+	case UBIFS_MST_NODE:
+	{
+		const struct ubifs_mst_node *mst = node;
+
+		printf("\t\thighest_inum \t\t\t%llu\n",
+		       (unsigned long long)le64_to_cpu(mst->highest_inum));
+		printf("\t\tcommit number \t\t\t%llu\n",
+		       (unsigned long long)le64_to_cpu(mst->cmt_no));
+		printf("\t\tflags \t\t\t\t%#x\n", le32_to_cpu(mst->flags));
+		printf("\t\tlog_lnum \t\t\t%u\n", le32_to_cpu(mst->log_lnum));
+		printf("\t\troot_lnum \t\t\t%u\n", le32_to_cpu(mst->root_lnum));
+		printf("\t\troot_offs \t\t\t%u\n", le32_to_cpu(mst->root_offs));
+		printf("\t\troot_len \t\t\t%u\n", le32_to_cpu(mst->root_len));
+		printf("\t\tgc_lnum \t\t\t%u\n", le32_to_cpu(mst->gc_lnum));
+		printf("\t\tihead_lnum \t\t\t%u\n", le32_to_cpu(mst->ihead_lnum));
+		printf("\t\tihead_offs \t\t\t%u\n", le32_to_cpu(mst->ihead_offs));
+		printf("\t\tindex_size \t\t\t%llu\n",
+		       (unsigned long long)le64_to_cpu(mst->index_size));
+		printf("\t\tlpt_lnum \t\t\t%u\n", le32_to_cpu(mst->lpt_lnum));
+		printf("\t\tlpt_offs \t\t\t%u\n", le32_to_cpu(mst->lpt_offs));
+		printf("\t\tnhead_lnum \t\t\t%u\n", le32_to_cpu(mst->nhead_lnum));
+		printf("\t\tnhead_offs \t\t\t%u\n", le32_to_cpu(mst->nhead_offs));
+		printf("\t\tltab_lnum \t\t\t%u\n", le32_to_cpu(mst->ltab_lnum));
+		printf("\t\tltab_offs \t\t\t%u\n", le32_to_cpu(mst->ltab_offs));
+		printf("\t\tlsave_lnum \t\t\t%u\n", le32_to_cpu(mst->lsave_lnum));
+		printf("\t\tlsave_offs \t\t\t%u\n", le32_to_cpu(mst->lsave_offs));
+		printf("\t\tlscan_lnum \t\t\t%u\n", le32_to_cpu(mst->lscan_lnum));
+		printf("\t\tleb_cnt \t\t\t%u\n", le32_to_cpu(mst->leb_cnt));
+		printf("\t\tempty_lebs \t\t\t%u\n", le32_to_cpu(mst->empty_lebs));
+		printf("\t\tidx_lebs \t\t\t%u\n", le32_to_cpu(mst->idx_lebs));
+		printf("\t\ttotal_free \t\t\t%llu\n",
+		       (unsigned long long)le64_to_cpu(mst->total_free));
+		printf("\t\ttotal_dirty \t\t\t%llu\n",
+		       (unsigned long long)le64_to_cpu(mst->total_dirty));
+		printf("\t\ttotal_used \t\t\t%llu\n",
+		       (unsigned long long)le64_to_cpu(mst->total_used));
+		printf("\t\ttotal_dead \t\t\t%llu\n",
+		       (unsigned long long)le64_to_cpu(mst->total_dead));
+		printf("\t\ttotal_dark \t\t\t%llu\n",
+		       (unsigned long long)le64_to_cpu(mst->total_dark));
+		break;
+	}
+	case UBIFS_REF_NODE:
+	{
+		const struct ubifs_ref_node *ref = node;
+
+		printf("\t\tlnum \t\t\t\t%u\n", le32_to_cpu(ref->lnum));
+		printf("\t\toffs \t\t\t\t%u\n", le32_to_cpu(ref->offs));
+		printf("\t\tjhead \t\t\t\t%u\n", le32_to_cpu(ref->jhead));
+		break;
+	}
+	case UBIFS_INO_NODE:
+	{
+		const struct ubifs_ino_node *ino = node;
+
+		key_read(c, &ino->key, &key);
+		printf("\t\tkey \t\t\t%s\n",
+		       dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
+		printf("\t\tcreat_sqnum \t\t\t%llu\n",
+		       (unsigned long long)le64_to_cpu(ino->creat_sqnum));
+		printf("\t\tsize \t\t\t%llu\n",
+		       (unsigned long long)le64_to_cpu(ino->size));
+		printf("\t\tnlink \t\t\t%u\n", le32_to_cpu(ino->nlink));
+		printf("\t\tatime \t\t\t%lld.%u\n",
+		       (long long)le64_to_cpu(ino->atime_sec),
+		       le32_to_cpu(ino->atime_nsec));
+		printf("\t\tmtime \t\t\t%lld.%u\n",
+		       (long long)le64_to_cpu(ino->mtime_sec),
+		       le32_to_cpu(ino->mtime_nsec));
+		printf("\t\tctime \t\t\t%lld.%u\n",
+		       (long long)le64_to_cpu(ino->ctime_sec),
+		       le32_to_cpu(ino->ctime_nsec));
+		printf("\t\tuid \t\t\t%u\n", le32_to_cpu(ino->uid));
+		printf("\t\tgid \t\t\t%u\n", le32_to_cpu(ino->gid));
+		printf("\t\tmode \t\t\t%u\n", le32_to_cpu(ino->mode));
+		printf("\t\tflags \t\t\t%#x\n", le32_to_cpu(ino->flags));
+		printf("\t\txattr_cnt \t\t\t%u\n", le32_to_cpu(ino->xattr_cnt));
+		printf("\t\txattr_size \t\t\t%u\n", le32_to_cpu(ino->xattr_size));
+		printf("\t\txattr_names \t\t\t%u\n", le32_to_cpu(ino->xattr_names));
+		printf("\t\tcompr_type \t\t\t%#x\n",
+		       (int)le16_to_cpu(ino->compr_type));
+		printf("\t\tdata len \t\t\t%u\n", le32_to_cpu(ino->data_len));
+		break;
+	}
+	case UBIFS_DENT_NODE:
+	case UBIFS_XENT_NODE:
+	{
+		const struct ubifs_dent_node *dent = node;
+		int nlen = le16_to_cpu(dent->nlen);
+
+		key_read(c, &dent->key, &key);
+		printf("\t\tkey \t\t\t%s\n",
+		       dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
+		printf("\t\tinum \t\t\t%llu\n",
+		       (unsigned long long)le64_to_cpu(dent->inum));
+		printf("\t\ttype \t\t\t%d\n", (int)dent->type);
+		printf("\t\tnlen \t\t\t%d\n", nlen);
+		printf("\t\tname           ");
+
+		if (nlen > UBIFS_MAX_NLEN)
+			printf("(bad name length, not printing, bad or corrupted node)");
+		else {
+			for (i = 0; i < nlen && dent->name[i]; i++)
+				printf("%c", dent->name[i]);
+		}
+		printf("\n");
+
+		break;
+	}
+	case UBIFS_DATA_NODE:
+	{
+		const struct ubifs_data_node *dn = node;
+		int dlen = le32_to_cpu(ch->len) - UBIFS_DATA_NODE_SZ;
+
+		key_read(c, &dn->key, &key);
+		printf("\t\tkey \t\t\t%s\n",
+		       dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
+		printf("\t\tsize \t\t\t%u\n", le32_to_cpu(dn->size));
+		printf("\t\tcompr_typ \t\t\t%d\n",
+		       (int)le16_to_cpu(dn->compr_type));
+		printf("\t\tdata size \t\t\t%d\n", dlen);
+		break;
+	}
+	case UBIFS_TRUN_NODE:
+	{
+		const struct ubifs_trun_node *trun = node;
+
+		printf("\t\tinum \t\t\t%u\n", le32_to_cpu(trun->inum));
+		printf("\t\told_size \t\t\t%llu\n",
+		       (unsigned long long)le64_to_cpu(trun->old_size));
+		printf("\t\tnew_size \t\t\t%llu\n",
+		       (unsigned long long)le64_to_cpu(trun->new_size));
+		break;
+	}
+	case UBIFS_IDX_NODE:
+	{
+		const struct ubifs_idx_node *idx = node;
+
+		n = le16_to_cpu(idx->child_cnt);
+		printf("\t\tchild_cnt \t\t%d\n", n);
+		printf("\t\tlevel \t\t\t%d\n", (int)le16_to_cpu(idx->level));
+		printf("\t\tBranches:\n");
+
+		for (i = 0; i < n && i < c->fanout - 1; i++) {
+			const struct ubifs_branch *br;
+
+			br = ubifs_idx_branch(c, idx, i);
+			key_read(c, &br->key, &key);
+			printf("\t\t%d: LEB %d:%d len %d key %s\n",
+			       i, le32_to_cpu(br->lnum), le32_to_cpu(br->offs),
+			       le32_to_cpu(br->len),
+			       dbg_snprintf_key(c, &key, key_buf,
+						DBG_KEY_BUF_LEN));
+		}
+		break;
+	}
+	case UBIFS_CS_NODE:
+		break;
+	case UBIFS_ORPH_NODE:
+	{
+		const struct ubifs_orph_node *orph = node;
+
+		printf("\t\tcommit number \t\t\t%llu\n",
+		       (unsigned long long)
+				le64_to_cpu(orph->cmt_no) & LLONG_MAX);
+		printf("\t\tlast node flag \t\t\t%llu\n",
+		       (unsigned long long)(le64_to_cpu(orph->cmt_no)) >> 63);
+		n = (le32_to_cpu(ch->len) - UBIFS_ORPH_NODE_SZ) >> 3;
+		printf("\t\t%d orphan inode numbers:\n", n);
+		for (i = 0; i < n; i++)
+			printf("\t\t  ino \t\t\t%llu\n",
+			       (unsigned long long)le64_to_cpu(orph->inos[i]));
+		break;
+	}
+	default:
+		printf("node type \t\t\t%d was not recognized\n",
+		       (int)ch->node_type);
+	}
+	printf("\n");
+}
+
 static int dump()
 {
 	return 0;
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 13/38] ubifs: defs.h: introduce some compatible definition for printk class
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (11 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 12/38] ubifs: ubifs_dump: add dump_ch and dump_node functions Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 14/38] ubifs: io: introduce ubifs_read function to read ubi volume Dongsheng Yang
                   ` (24 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

There are some functions of printk class in code copied from kernel.
Then add a compatible definitions in defs.h for them.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/include/defs.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/ubifs-utils/include/defs.h b/ubifs-utils/include/defs.h
index 1fa3316..739af7f 100644
--- a/ubifs-utils/include/defs.h
+++ b/ubifs-utils/include/defs.h
@@ -81,6 +81,15 @@ __res = ((unsigned long) n) % (unsigned) base; \
 n = ((unsigned long) n) / (unsigned) base; \
 __res; })
 
+/*
+ * printk
+ */
+#define printk(fmt, args...) fprintf(stderr, fmt, ##args)
+#define	KERN_CRIT	""
+#define KERN_ERR	""
+#define ubifs_err(c, fmt, args...) printk(fmt, ##args)
+#define pr_err(fmt, args...) printk(fmt, ##args)
+
 #if INT_MAX != 0x7fffffff
 #error : sizeof(int) must be 4 for this program
 #endif
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 14/38] ubifs: io: introduce ubifs_read function to read ubi volume
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (12 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 13/38] ubifs: defs.h: introduce some compatible definition for printk class Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 15/38] ubifs: ubifs_dump: dump super block Dongsheng Yang
                   ` (23 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

Implement a ubifs_read function in io lib. This function
will read the data at offset in length of len from ubi volume
to buf.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/include/io.h |  2 ++
 ubifs-utils/lib/io.c     | 18 ++++++++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/ubifs-utils/include/io.h b/ubifs-utils/include/io.h
index 920645d..11f568c 100644
--- a/ubifs-utils/include/io.h
+++ b/ubifs-utils/include/io.h
@@ -16,4 +16,6 @@ int write_leb(struct ubifs_info *c, int lnum, int len, void *buf);
 int close_target(void);
 int open_target(struct ubifs_info *c, int yes);
 int open_ubi(struct ubifs_info *c, const char *node);
+
+int ubifs_read(loff_t offset, int len, void *buf);
 #endif
diff --git a/ubifs-utils/lib/io.c b/ubifs-utils/lib/io.c
index 9817d2a..d05cf86 100644
--- a/ubifs-utils/lib/io.c
+++ b/ubifs-utils/lib/io.c
@@ -132,3 +132,21 @@ int write_leb(struct ubifs_info *c, int lnum, int len, void *buf)
 
 	return 0;
 }
+
+/**
+ * ubifs_read - read data from ubi volume.
+ * @offset: offset of data in volume
+ * @len: length of data in the buffer
+ * @buf: buffer (must be at least c->leb_size bytes)
+ */
+int ubifs_read(loff_t offset, int len, void *buf)
+{
+	if (lseek(out_fd, offset, SEEK_SET) != offset)
+		return sys_err_msg("lseek failed seeking %"PRIdoff_t, offset);
+
+	if (read(out_fd, buf, len) != len)
+		return sys_err_msg("write failed writing %d bytes at pos %"PRIdoff_t,
+				   len, offset);
+
+	return 0;
+}
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 15/38] ubifs: ubifs_dump: dump super block
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (13 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 14/38] ubifs: io: introduce ubifs_read function to read ubi volume Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 16/38] ubifs: introduce scan for ubifs-utils Dongsheng Yang
                   ` (22 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

Read the super block from ubi volume and dump it out.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/include/lpt.h           |   1 +
 ubifs-utils/lib/lpt.c               |  29 +++++++
 ubifs-utils/ubifs_dump/ubifs_dump.c | 151 ++++++++++++++++++++++++++++++++++--
 3 files changed, 173 insertions(+), 8 deletions(-)

diff --git a/ubifs-utils/include/lpt.h b/ubifs-utils/include/lpt.h
index 4cde59d..e2f7348 100644
--- a/ubifs-utils/include/lpt.h
+++ b/ubifs-utils/include/lpt.h
@@ -24,5 +24,6 @@
 
 int calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs, int *big_lpt);
 int create_lpt(struct ubifs_info *c);
+int ubifs_calc_lpt_geom(struct ubifs_info *c);
 
 #endif
diff --git a/ubifs-utils/lib/lpt.c b/ubifs-utils/lib/lpt.c
index 100d747..26fb4dd 100644
--- a/ubifs-utils/lib/lpt.c
+++ b/ubifs-utils/lib/lpt.c
@@ -585,3 +585,32 @@ out:
 	free(pnode);
 	return err;
 }
+
+/**
+ * ubifs_calc_lpt_geom - calculate and check sizes for the LPT area.
+ * @c: the UBIFS file-system description object
+ *
+ * This function returns %0 on success and a negative error code on failure.
+ */
+int ubifs_calc_lpt_geom(struct ubifs_info *c)
+{
+	int lebs_needed;
+	long long sz;
+
+	do_calc_lpt_geom(c);
+
+	/* Verify that lpt_lebs is big enough */
+	sz = c->lpt_sz * 2; /* Must have at least 2 times the size */
+	lebs_needed = (sz + c->leb_size - 1) / c->leb_size;
+	if (lebs_needed > c->lpt_lebs) {
+		ubifs_err(c, "too few LPT LEBs, %d", lebs_needed);
+		return -EINVAL;
+	}
+
+	/* Verify that ltab fits in a single LEB (since ltab is a single node */
+	if (c->ltab_sz > c->leb_size) {
+		ubifs_err(c, "LPT ltab too big");
+		return -EINVAL;
+	}
+	return 0;
+}
diff --git a/ubifs-utils/ubifs_dump/ubifs_dump.c b/ubifs-utils/ubifs_dump/ubifs_dump.c
index a510aeb..9ddb0f7 100644
--- a/ubifs-utils/ubifs_dump/ubifs_dump.c
+++ b/ubifs-utils/ubifs_dump/ubifs_dump.c
@@ -4,6 +4,7 @@
 
 #include "io.h"
 #include "key.h"
+#include "lpt.h"
 
 #define DBG_KEY_BUF_LEN		48
 
@@ -16,6 +17,13 @@ static const struct option longopts[] = {
 struct ubifs_info info_;
 static struct ubifs_info *c = &info_;
 
+/* Global buffers */
+static void *leb_buf;
+
+/* Global nodes*/
+struct ubifs_mst_node mst;
+struct ubifs_sb_node sup;
+
 static int get_options(int argc, char**argv)
 {
 	int opt, i;
@@ -73,13 +81,6 @@ static const char *hash_type_to_str[] = {
 		"UBIFS_KEY_HASH_TEST"
 };
 
-static const char *compr_type_to_str[] = {
-		"UBIFS_COMPR_NONE",
-		"UBIFS_COMPR_LZO",
-		"UBIFS_COMPR_ZLIB",
-		"UBIFS_COMPR_TYPES_CNT",
-};
-
 static const char *key_fmt_to_str[] = {
 	"UBIFS_SIMPLE_KEY_FMT"
 };
@@ -375,11 +376,145 @@ void dump_node(const struct ubifs_info *c, const void *node)
 	printf("\n");
 }
 
-static int dump()
+/**
+ * init - initialize things.
+ */
+static int init(void)
+{
+	leb_buf = malloc(c->leb_size);
+	if (!leb_buf)
+		return err_msg("out of memory");
+
+	return 0;
+}
+
+/**
+ * deinit - deinitialize things.
+ */
+static void deinit(void)
+{
+	free(leb_buf);
+}
+
+/*
+ * init_constants_sb - initialize UBIFS constants.
+ * @c: UBIFS file-system description object
+ *
+ * This is a helper function which initializes various UBIFS constants after
+ * the superblock has been read. It also checks various UBIFS parameters and
+ * makes sure they are all right. Returns zero in case of success and a
+ * negative error code in case of failure.
+ */
+static int init_constants_sb(struct ubifs_info *c)
 {
+	int tmp, err;
+
+	tmp = ubifs_idx_node_sz(c, 1);
+	c->min_idx_node_sz = ALIGN(tmp, 8);
+
+	tmp = ubifs_idx_node_sz(c, c->fanout);
+	c->max_idx_node_sz = ALIGN(tmp, 8);
+
+	c->max_znode_sz = sizeof(struct ubifs_znode) +
+			c->fanout * sizeof(struct ubifs_zbranch);
+	/* Make sure LEB size is large enough to fit full commit */
+	tmp = UBIFS_CS_NODE_SZ + UBIFS_REF_NODE_SZ * c->jhead_cnt;
+	tmp = ALIGN(tmp, c->min_io_size);
+	if (tmp > c->leb_size) {
+		printf("too small LEB size %d, at least %d needed",
+			  c->leb_size, tmp);
+		return -EINVAL;
+	}
+
+	err = ubifs_calc_lpt_geom(c);
+	if (err)
+		return err;
+
 	return 0;
 }
 
+static int dump_super(void)
+{
+	int err = 0;
+	unsigned long sup_flags;
+
+	memset(&sup, 0, UBIFS_SB_NODE_SZ);
+	err = ubifs_read(0, UBIFS_SB_NODE_SZ, &sup);
+	if (err)
+		return err;
+
+	printf("SUPER BLOCK: \n");
+	dump_node(c, &sup);
+
+        switch (sup.key_hash) {
+        case UBIFS_KEY_HASH_R5:
+                c->key_hash = key_r5_hash;
+                c->key_hash_type = UBIFS_KEY_HASH_R5;
+                break;
+
+        case UBIFS_KEY_HASH_TEST:
+                c->key_hash = key_test_hash;
+                c->key_hash_type = UBIFS_KEY_HASH_TEST;
+                break;
+        };
+
+	c->key_fmt = sup.key_fmt;
+
+	switch (c->key_fmt) {
+	case UBIFS_SIMPLE_KEY_FMT:
+		c->key_len = UBIFS_SK_LEN;
+		break;
+	default:
+		printf("unsupported key format");
+		err = -EINVAL;
+		return err;
+	}
+
+	c->leb_size	 = le32_to_cpu(sup.leb_size);
+	c->min_io_size	 = le32_to_cpu(sup.min_io_size);
+	c->leb_cnt       = le32_to_cpu(sup.leb_cnt);
+	c->max_leb_cnt   = le32_to_cpu(sup.max_leb_cnt);
+	c->max_bud_bytes = le64_to_cpu(sup.max_bud_bytes);
+	c->log_lebs      = le32_to_cpu(sup.log_lebs);
+	c->lpt_lebs      = le32_to_cpu(sup.lpt_lebs);
+	c->orph_lebs     = le32_to_cpu(sup.orph_lebs);
+	c->jhead_cnt     = le32_to_cpu(sup.jhead_cnt) + NONDATA_JHEADS_CNT;
+	c->fanout        = le32_to_cpu(sup.fanout);
+	c->lsave_cnt     = le32_to_cpu(sup.lsave_cnt);
+	c->rp_size       = le64_to_cpu(sup.rp_size);
+	sup_flags        = le32_to_cpu(sup.flags);
+	c->default_compr = le16_to_cpu(sup.default_compr);
+
+	c->big_lpt = !!(sup_flags & UBIFS_FLG_BIGLPT);
+	c->space_fixup = !!(sup_flags & UBIFS_FLG_SPACE_FIXUP);
+
+	/* Automatically increase file system size to the maximum size */
+	c->lpt_first = UBIFS_LOG_LNUM + c->log_lebs;
+	c->lpt_last = c->lpt_first + c->lpt_lebs - 1;
+	c->main_lebs = c->leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS;
+	c->main_lebs -= c->log_lebs + c->lpt_lebs + c->orph_lebs;
+	c->main_first = c->leb_cnt - c->main_lebs;
+
+	return init_constants_sb(c);
+}
+
+static int dump()
+{
+	int err = 0;
+
+	err = init();
+	if (err)
+		goto out;
+
+	err = dump_super();
+	if (err)
+		goto out;
+
+out:
+	deinit();
+	return err;
+}
+
 int main(int argc, char *argv[])
 {
 	int err;
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 16/38] ubifs: introduce scan for ubifs-utils
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (14 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 15/38] ubifs: ubifs_dump: dump super block Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 17/38] ubifs: add some more compatible definitions in defs.h Dongsheng Yang
                   ` (21 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

It's a lib to scan a leb.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/include/scan.h |   8 ++
 ubifs-utils/lib/scan.c     | 318 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 326 insertions(+)
 create mode 100644 ubifs-utils/include/scan.h
 create mode 100644 ubifs-utils/lib/scan.c

diff --git a/ubifs-utils/include/scan.h b/ubifs-utils/include/scan.h
new file mode 100644
index 0000000..8447adf
--- /dev/null
+++ b/ubifs-utils/include/scan.h
@@ -0,0 +1,8 @@
+#ifndef __UBIFS_SCAN_H__
+#define __UBIFS_SCAN_H__
+
+struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
+				  int offs, void *sbuf, int quiet);
+
+void ubifs_scan_destroy(struct ubifs_scan_leb *sleb);
+#endif
diff --git a/ubifs-utils/lib/scan.c b/ubifs-utils/lib/scan.c
new file mode 100644
index 0000000..69c84d1
--- /dev/null
+++ b/ubifs-utils/lib/scan.c
@@ -0,0 +1,318 @@
+/*
+ * This file is part of UBIFS.
+ *
+ * Copied from kernel
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * This file implements the scan which is a general-purpose function for
+ * determining what nodes are in an eraseblock. The scan is used to replay the
+ * journal, to do garbage collection. for the TNC in-the-gaps method, and by
+ * debugging functions.
+ */
+#include "ubifs_common.h"
+
+#include "ubifs.h"
+#define PROGRAM_NAME "ubifs_scan"
+#include "common.h"
+#include "key.h"
+#include "io.h"
+#include "scan.h"
+
+/**
+ * scan_padding_bytes - scan for padding bytes.
+ * @buf: buffer to scan
+ * @len: length of buffer
+ *
+ * This function returns the number of padding bytes on success and
+ * %SCANNED_GARBAGE on failure.
+ */
+static int scan_padding_bytes(void *buf, int len)
+{
+	int pad_len = 0, max_pad_len = min_t(int, UBIFS_PAD_NODE_SZ, len);
+	int *p = buf;
+
+	while (pad_len < max_pad_len && *p++ == UBIFS_PADDING_BYTE)
+		pad_len += 1;
+
+	if (!pad_len || (pad_len & 7)) {
+		return SCANNED_GARBAGE;
+	}
+
+	return pad_len;
+}
+
+/**
+ * ubifs_scan_a_node - scan for a node or padding.
+ * @c: UBIFS file-system description object
+ * @buf: buffer to scan
+ * @len: length of buffer
+ * @lnum: logical eraseblock number
+ * @offs: offset within the logical eraseblock
+ * @quiet: print no messages
+ *
+ * This function returns a scanning code to indicate what was scanned.
+ */
+int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len,
+		      int lnum __attribute__((unused)), int offs,
+		      int quiet __attribute__((unused)))
+{
+	struct ubifs_ch *ch = buf;
+	uint32_t magic;
+
+	magic = le32_to_cpu(ch->magic);
+
+	if (magic == 0xFFFFFFFF)
+		return SCANNED_EMPTY_SPACE;
+
+	if (magic != UBIFS_NODE_MAGIC)
+		return scan_padding_bytes(buf, len);
+
+	if (len < UBIFS_CH_SZ) {
+		return SCANNED_GARBAGE;
+	}
+
+	if (ch->node_type == UBIFS_PAD_NODE) {
+		struct ubifs_pad_node *pad = buf;
+		int pad_len = le32_to_cpu(pad->pad_len);
+		int node_len = le32_to_cpu(ch->len);
+
+		/* Validate the padding node */
+		if (pad_len < 0 ||
+		    offs + node_len + pad_len > c->leb_size) {
+			return SCANNED_A_BAD_PAD_NODE;
+		}
+
+		/* Make the node pads to 8-byte boundary */
+		if ((node_len + pad_len) & 7) {
+			return SCANNED_A_BAD_PAD_NODE;
+		}
+
+		return node_len + pad_len;
+	}
+
+	return SCANNED_A_NODE;
+}
+
+/**
+ * ubifs_start_scan - create LEB scanning information at start of scan.
+ * @c: UBIFS file-system description object
+ * @lnum: logical eraseblock number
+ * @offs: offset to start at (usually zero)
+ * @sbuf: scan buffer (must be c->leb_size)
+ *
+ * This function returns the scanned information on success and a negative error
+ * code on failure.
+ */
+struct ubifs_scan_leb *ubifs_start_scan(const struct ubifs_info *c, int lnum,
+					int offs, void *sbuf)
+{
+	struct ubifs_scan_leb *sleb;
+	int err;
+
+	sleb = kzalloc(sizeof(struct ubifs_scan_leb), GFP_NOFS);
+	if (!sleb)
+		return ERR_PTR(-ENOMEM);
+
+	sleb->lnum = lnum;
+	INIT_LIST_HEAD(&sleb->nodes);
+	sleb->buf = sbuf;
+
+	err = ubifs_read(lnum * c->leb_size + offs, c->leb_size - offs, sbuf + offs);
+	if (err && err != -EBADMSG) {
+		kfree(sleb);
+		return ERR_PTR(err);
+	}
+
+	/*
+	 * Note, we ignore integrity errors (EBASMSG) because all the nodes are
+	 * protected by CRC checksums.
+	 */
+	return sleb;
+}
+
+/**
+ * ubifs_end_scan - update LEB scanning information at end of scan.
+ * @c: UBIFS file-system description object
+ * @sleb: scanning information
+ * @lnum: logical eraseblock number
+ * @offs: offset to start at (usually zero)
+ */
+void ubifs_end_scan(const struct ubifs_info *c, struct ubifs_scan_leb *sleb,
+		    int lnum, int offs)
+{
+	lnum = lnum;
+	ubifs_assert(offs % c->min_io_size == 0);
+
+	sleb->endpt = ALIGN(offs, c->min_io_size);
+}
+
+/**
+ * ubifs_add_snod - add a scanned node to LEB scanning information.
+ * @c: UBIFS file-system description object
+ * @sleb: scanning information
+ * @buf: buffer containing node
+ * @offs: offset of node on flash
+ *
+ * This function returns %0 on success and a negative error code on failure.
+ */
+int ubifs_add_snod(const struct ubifs_info *c, struct ubifs_scan_leb *sleb,
+		   void *buf, int offs)
+{
+	struct ubifs_ch *ch = buf;
+	struct ubifs_ino_node *ino = buf;
+	struct ubifs_scan_node *snod;
+
+	snod = kmalloc(sizeof(struct ubifs_scan_node), GFP_NOFS);
+	if (!snod)
+		return -ENOMEM;
+
+	snod->sqnum = le64_to_cpu(ch->sqnum);
+	snod->type = ch->node_type;
+	snod->offs = offs;
+	snod->len = le32_to_cpu(ch->len);
+	snod->node = buf;
+
+	switch (ch->node_type) {
+	case UBIFS_INO_NODE:
+	case UBIFS_DENT_NODE:
+	case UBIFS_XENT_NODE:
+	case UBIFS_DATA_NODE:
+		/*
+		 * The key is in the same place in all keyed
+		 * nodes.
+		 */
+		key_read(c, &ino->key, &snod->key);
+		break;
+	default:
+		invalid_key_init(c, &snod->key);
+		break;
+	}
+	list_add_tail(&snod->list, &sleb->nodes);
+	sleb->nodes_cnt += 1;
+	return 0;
+}
+
+/**
+ * ubifs_scan - scan a logical eraseblock.
+ * @c: UBIFS file-system description object
+ * @lnum: logical eraseblock number
+ * @offs: offset to start at (usually zero)
+ * @sbuf: scan buffer (must be of @c->leb_size bytes in size)
+ * @quiet: print no messages
+ *
+ * This function scans LEB number @lnum and returns complete information about
+ * its contents. Returns the scanned information in case of success and,
+ * %-EUCLEAN if the LEB neads recovery, and other negative error codes in case
+ * of failure.
+ *
+ * If @quiet is non-zero, this function does not print large and scary
+ * error messages and flash dumps in case of errors.
+ */
+struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
+				  int offs, void *sbuf, int quiet)
+{
+	void *buf = sbuf + offs;
+	int err, len = c->leb_size - offs;
+	struct ubifs_scan_leb *sleb;
+
+	sleb = ubifs_start_scan(c, lnum, offs, sbuf);
+	if (IS_ERR(sleb))
+		return sleb;
+
+	while (len >= 8) {
+		struct ubifs_ch *ch = buf;
+		int node_len, ret;
+
+		cond_resched();
+
+		ret = ubifs_scan_a_node(c, buf, len, lnum, offs, quiet);
+		if (ret > 0) {
+			/* Padding bytes or a valid padding node */
+			offs += ret;
+			buf += ret;
+			len -= ret;
+			continue;
+		}
+
+		if (ret == SCANNED_EMPTY_SPACE)
+			/* Empty space is checked later */
+			break;
+
+		switch (ret) {
+		case SCANNED_GARBAGE:
+			if (offs == 0)
+				break;
+			goto corrupted;
+		case SCANNED_A_NODE:
+			break;
+		case SCANNED_A_CORRUPT_NODE:
+		case SCANNED_A_BAD_PAD_NODE:
+			goto corrupted;
+		default:
+			err = -EINVAL;
+			goto error;
+		}
+
+		err = ubifs_add_snod(c, sleb, buf, offs);
+		if (err)
+			goto error;
+
+		node_len = ALIGN(le32_to_cpu(ch->len), 8);
+		offs += node_len;
+		buf += node_len;
+		len -= node_len;
+	}
+
+	if (offs % c->min_io_size) {
+		goto corrupted;
+	}
+
+	ubifs_end_scan(c, sleb, lnum, offs);
+
+	for (; len > 2; offs += 2, buf = buf + 2, len -= 2)
+		if ((*(const uint8_t *)buf) != 0xff)
+			goto corrupted;
+
+	return sleb;
+
+corrupted:
+	err = -EUCLEAN;
+	ubifs_scan_destroy(sleb);
+	return ERR_PTR(err);
+
+error:
+	ubifs_scan_destroy(sleb);
+	return ERR_PTR(err);
+}
+
+/**
+ * ubifs_scan_destroy - destroy LEB scanning information.
+ * @sleb: scanning information to free
+ */
+void ubifs_scan_destroy(struct ubifs_scan_leb *sleb)
+{
+	struct ubifs_scan_node *node;
+	struct list_head *head;
+
+	head = &sleb->nodes;
+	while (!list_empty(head)) {
+		node = list_entry(head->next, struct ubifs_scan_node, list);
+		list_del(&node->list);
+		kfree(node);
+	}
+	kfree(sleb);
+}
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 17/38] ubifs: add some more compatible definitions in defs.h
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (15 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 16/38] ubifs: introduce scan for ubifs-utils Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 18/38] ubifs: ubifs_dump: dump master node Dongsheng Yang
                   ` (20 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

Add kmalloc class compatible definitions to defs.h.
Add error pointer class compatible definitions to defs.h.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/include/defs.h | 84 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

diff --git a/ubifs-utils/include/defs.h b/ubifs-utils/include/defs.h
index 739af7f..ed42ab1 100644
--- a/ubifs-utils/include/defs.h
+++ b/ubifs-utils/include/defs.h
@@ -6,6 +6,37 @@
 #ifndef __UBIFS_DEFS_H__
 #define __UBIFS_DEFS_H__
 
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <endian.h>
+#include <byteswap.h>
+#include <assert.h>
+#include <stddef.h>
+#include <linux/types.h>
+#include <stdint.h>
+
+#include <features.h>
+
+#ifndef __GLIBC__
+#define BTRFS_DISABLE_BACKTRACE
+#define __always_inline __inline __attribute__ ((__always_inline__))
+#endif
+
+#ifndef BTRFS_DISABLE_BACKTRACE
+#include <execinfo.h>
+#endif
+
+#define ptr_to_u64(x)	((u64)(uintptr_t)x)
+#define u64_to_ptr(x)	((void *)(uintptr_t)x)
+
+#ifndef READ
+#define READ 0
+#define WRITE 1
+#define READA 2
+#endif
+
 #define t16(x) ({ \
 	uint16_t __b = (x); \
 	(__LITTLE_ENDIAN==__BYTE_ORDER) ? __b : bswap_16(__b); \
@@ -82,6 +113,41 @@ n = ((unsigned long) n) / (unsigned) base; \
 __res; })
 
 /*
+ * error pointer
+ */
+#define MAX_ERRNO	4095
+#define IS_ERR_VALUE(x) ((x) >= (unsigned long)-MAX_ERRNO)
+
+static inline void *ERR_PTR(long error)
+{
+	return (void *) error;
+}
+
+static inline long PTR_ERR(const void *ptr)
+{
+	return (long) ptr;
+}
+
+static inline long IS_ERR(const void *ptr)
+{
+	return IS_ERR_VALUE((unsigned long)ptr);
+}
+
+#define cond_resched()		do { } while (0)
+#define preempt_enable()	do { } while (0)
+#define preempt_disable()	do { } while (0)
+
+/*
+ * kmalloc/kfree
+ */
+#define kmalloc(x, y) malloc(x)
+#define kzalloc(x, y) calloc(1, x)
+#define kstrdup(x, y) strdup(x)
+#define kfree(x) free(x)
+#define vmalloc(x) malloc(x)
+#define vfree(x) free(x)
+
+/*
  * printk
  */
 #define printk(fmt, args...) fprintf(stderr, fmt, ##args)
@@ -90,6 +156,24 @@ __res; })
 #define ubifs_err(c, fmt, args...) printk(fmt, ##args)
 #define pr_err(fmt, args...) printk(fmt, ##args)
 
+#define container_of(ptr, type, member) ({                      \
+        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+	        (type *)( (char *)__mptr - offsetof(type,member) );})
+
+#define gfp_t int
+#define get_cpu_var(p) (p)
+#define __get_cpu_var(p) (p)
+#define BITS_PER_LONG (__SIZEOF_LONG__ * 8)
+#define __GFP_BITS_SHIFT 20
+#define __GFP_BITS_MASK ((int)((1 << __GFP_BITS_SHIFT) - 1))
+#define GFP_KERNEL 0
+#define GFP_NOFS 0
+#define __read_mostly
+
+#ifndef ULONG_MAX
+#define ULONG_MAX       (~0UL)
+#endif
+
 #if INT_MAX != 0x7fffffff
 #error : sizeof(int) must be 4 for this program
 #endif
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 18/38] ubifs: ubifs_dump: dump master node
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (16 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 17/38] ubifs: add some more compatible definitions in defs.h Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 19/38] ubifs: ubifs_dump: dump log area Dongsheng Yang
                   ` (19 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

Search the master lebs and found the latest master node.
Then dump it out.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 Makefile                            |   1 +
 ubifs-utils/ubifs_dump/ubifs_dump.c | 139 +++++++++++++++++++++++++++++-------
 2 files changed, 115 insertions(+), 25 deletions(-)

diff --git a/Makefile b/Makefile
index a1aaa6e..1d7e5f2 100644
--- a/Makefile
+++ b/Makefile
@@ -130,6 +130,7 @@ $(foreach v,$(UBI_BINS),$(eval $(call mkdep,ubi-utils/,$(v),libubi.a ubiutils-co
 $(foreach v,crc16.o lpt.o compr.o devtable.o io.o hashtable.o hashtable_itr.o,$(eval UBIFS_LIBS += ../lib/$(v)))
 
 obj-ubifs_dump = $(UBIFS_LIBS)
+obj-ubifs_dump += ../lib/scan.o
 LDFLAGS_ubifs_dump = $(ZLIBLDFLAGS) $(LZOLDFLAGS) $(UUIDLDFLAGS)
 LDLIBS_ubifs_dump = -lz -llzo2 -lm -luuid
 $(call mkdep,ubifs-utils/ubifs_dump/,ubifs_dump,,ubi-utils/libubi.a)
diff --git a/ubifs-utils/ubifs_dump/ubifs_dump.c b/ubifs-utils/ubifs_dump/ubifs_dump.c
index 9ddb0f7..4f67621 100644
--- a/ubifs-utils/ubifs_dump/ubifs_dump.c
+++ b/ubifs-utils/ubifs_dump/ubifs_dump.c
@@ -2,9 +2,11 @@
 #define PROGRAM_NAME "ubifs-dump"
 #include "common.h"
 
+#include "ubifs.h"
 #include "io.h"
 #include "key.h"
 #include "lpt.h"
+#include "scan.h"
 
 #define DBG_KEY_BUF_LEN		48
 
@@ -17,7 +19,6 @@ static const struct option longopts[] = {
 struct ubifs_info info_;
 static struct ubifs_info *c = &info_;
 
-/* Global buffers */
 static void *leb_buf;
 
 /* Global nodes*/
@@ -376,26 +377,6 @@ void dump_node(const struct ubifs_info *c, const void *node)
 	printf("\n");
 }
 
-/**
- * init - initialize things.
- */
-static int init(void)
-{
-	leb_buf = malloc(c->leb_size);
-	if (!leb_buf)
-		return err_msg("out of memory");
-
-	return 0;
-}
-
-/**
- * deinit - deinitialize things.
- */
-static void deinit(void)
-{
-	free(leb_buf);
-}
-
 /*
  * init_constants_sb - initialize UBIFS constants.
  * @c: UBIFS file-system description object
@@ -498,20 +479,128 @@ static int dump_super(void)
 	return init_constants_sb(c);
 }
 
-static int dump()
+/**
+ * scan_for_master - search the valid master node.
+ * @c: UBIFS file-system description object
+ *
+ * This function scans the master node LEBs and search for the latest master
+ * node. Returns zero in case of success, %-EUCLEAN if there master area is
+ * corrupted and requires recovery, and a negative error code in case of
+ * failure.
+ */
+static int scan_for_master(struct ubifs_info *c, struct ubifs_mst_node *mst_node)
 {
+	struct ubifs_scan_leb *sleb;
+	struct ubifs_scan_node *snod;
+	int lnum, offs = 0, nodes_cnt;
 	int err = 0;
 
-	err = init();
-	if (err)
+	lnum = UBIFS_MST_LNUM;
+
+	sleb = ubifs_scan(c, lnum, 0, leb_buf, 1);
+	if (IS_ERR(sleb))
+		return PTR_ERR(sleb);
+	nodes_cnt = sleb->nodes_cnt;
+	if (nodes_cnt > 0) {
+		snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node,
+				  list);
+		if (snod->type != UBIFS_MST_NODE) {
+			err = -EINVAL;
+			goto out;
+		}
+		memcpy(mst_node, snod->node, snod->len);
+		offs = snod->offs;
+	}
+	ubifs_scan_destroy(sleb);
+
+	lnum += 1;
+
+	sleb = ubifs_scan(c, lnum, 0, leb_buf, 1);
+	if (IS_ERR(sleb)) {
+		return PTR_ERR(sleb);
+	}
+	err = -EUCLEAN;
+	if (sleb->nodes_cnt != nodes_cnt)
+		goto out;
+	if (!sleb->nodes_cnt)
+		goto out;
+	snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, list);
+	if (snod->type != UBIFS_MST_NODE) {
+		err = -EINVAL;
+		goto out;
+	}
+	if (snod->offs != offs)
+		goto out;
+	if (memcmp((void *)mst_node + UBIFS_CH_SZ,
+		   (void *)snod->node + UBIFS_CH_SZ,
+		   UBIFS_MST_NODE_SZ - UBIFS_CH_SZ))
 		goto out;
+	err = 0;
+
+out:
+	ubifs_scan_destroy(sleb);
+	return err;
+}
+
+static int dump_master(void)
+{
+	int err = 0;
+
+	printf("MASTER: \n");
+	err = scan_for_master(c, &mst);
+	if (err)
+		return err;
+	dump_node(c, &mst);
+	mst.flags &= cpu_to_le32(~UBIFS_MST_RCVRY);
+
+	c->max_sqnum       = le64_to_cpu(mst.ch.sqnum);
+	c->highest_inum    = le64_to_cpu(mst.highest_inum);
+	c->zroot.lnum      = le32_to_cpu(mst.root_lnum);
+	c->zroot.offs      = le32_to_cpu(mst.root_offs);
+	c->zroot.len       = le32_to_cpu(mst.root_len);
+	c->gc_lnum         = le32_to_cpu(mst.gc_lnum);
+	c->ihead_lnum      = le32_to_cpu(mst.ihead_lnum);
+	c->ihead_offs      = le32_to_cpu(mst.ihead_offs);
+	c->lpt_lnum        = le32_to_cpu(mst.lpt_lnum);
+	c->lpt_offs        = le32_to_cpu(mst.lpt_offs);
+	c->nhead_lnum      = le32_to_cpu(mst.nhead_lnum);
+	c->nhead_offs      = le32_to_cpu(mst.nhead_offs);
+	c->ltab_lnum       = le32_to_cpu(mst.ltab_lnum);
+	c->ltab_offs       = le32_to_cpu(mst.ltab_offs);
+	c->lsave_lnum      = le32_to_cpu(mst.lsave_lnum);
+	c->lsave_offs      = le32_to_cpu(mst.lsave_offs);
+	c->lscan_lnum      = le32_to_cpu(mst.lscan_lnum);
+	c->lst.empty_lebs  = le32_to_cpu(mst.empty_lebs);
+	c->lst.idx_lebs    = le32_to_cpu(mst.idx_lebs);
+	c->lst.total_free  = le64_to_cpu(mst.total_free);
+	c->lst.total_dirty = le64_to_cpu(mst.total_dirty);
+	c->lst.total_used  = le64_to_cpu(mst.total_used);
+	c->lst.total_dead  = le64_to_cpu(mst.total_dead);
+	c->lst.total_dark  = le64_to_cpu(mst.total_dark);
+
+	return 0;
+}
+
+static int dump()
+{
+	int err = 0;
 
 	err = dump_super();
 	if (err)
 		goto out;
 
+	leb_buf = malloc(c->leb_size);
+	if (!leb_buf) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	err = dump_master();
+	if (err)
+		goto free;
+free:
+	free(leb_buf);
 out:
-	deinit();
 	return err;
 }
 
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 19/38] ubifs: ubifs_dump: dump log area
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (17 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 18/38] ubifs: ubifs_dump: dump master node Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 20/38] ubifs: introduce lprops lib Dongsheng Yang
                   ` (18 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

scan the log lebs and dump the log nodes out.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/ubifs_dump/ubifs_dump.c | 140 ++++++++++++++++++++++++++++++++++++
 1 file changed, 140 insertions(+)

diff --git a/ubifs-utils/ubifs_dump/ubifs_dump.c b/ubifs-utils/ubifs_dump/ubifs_dump.c
index 4f67621..d7a2951 100644
--- a/ubifs-utils/ubifs_dump/ubifs_dump.c
+++ b/ubifs-utils/ubifs_dump/ubifs_dump.c
@@ -581,6 +581,142 @@ static int dump_master(void)
 	return 0;
 }
 
+static int __dump_log_leb(int leb_num)
+{
+	int err = 0;
+	struct ubifs_scan_leb *sleb;
+	struct ubifs_scan_node *snod;
+	const struct ubifs_cs_node *node;
+	static int cs_sqnum = 0;
+	int lnum = leb_num;
+	loff_t offs = 0;
+	int node_num = 0;
+
+	sleb = ubifs_scan(c, lnum, offs, leb_buf, 0);
+	if (IS_ERR(sleb)) {
+		printf("Error in scaning log leb");
+		return PTR_ERR(sleb);
+	}
+
+	if (sleb->nodes_cnt == 0) {
+		err = 1;
+		goto out;
+	}
+
+	node = sleb->buf;
+	snod = list_entry(sleb->nodes.next, struct ubifs_scan_node, list);
+	if (cs_sqnum == 0) {
+		/*
+		 * This is the first log LEB we are looking at, make sure that
+		 * the first node is a commit start node. Also record its
+		 * sequence number so that UBIFS can determine where the log
+		 * ends, because all nodes which were have higher sequence
+		 * numbers.
+		 */
+		if (snod->type != UBIFS_CS_NODE) {
+			ubifs_err(c, "first log node at LEB %d:%lu is not CS node",
+				  lnum, offs);
+			goto out_dump;
+		}
+		if (le64_to_cpu(node->cmt_no) != mst.cmt_no) {
+			ubifs_err(c, "first CS node at LEB %d:%lu has wrong commit number %llu expected %llu",
+				  lnum, offs,
+				  (unsigned long long)le64_to_cpu(node->cmt_no),
+				  mst.cmt_no);
+			goto out_dump;
+		}
+
+		cs_sqnum = le64_to_cpu(node->ch.sqnum);
+	}
+
+	if (snod->sqnum < cs_sqnum) {
+		/*
+		 * This means that we reached end of log and now
+		 * look to the older log data, which was already
+		 * committed but the eraseblock was not erased (UBIFS
+		 * only un-maps it). So this basically means we have to
+		 * exit with "end of log" code.
+		 */
+		err = 1;
+		goto out;
+	}
+
+	/* Make sure the first node sits at offset zero of the LEB */
+	if (snod->offs != 0) {
+		ubifs_err(c, "first node is not at zero offset");
+		goto out_dump;
+	}
+
+	printf("\tLOG LEB %d\n", lnum);
+	list_for_each_entry(snod, &sleb->nodes, list) {
+		if (snod->sqnum < cs_sqnum) {
+			ubifs_err(c, "bad sqnum %llu, commit sqnum %d",
+				  snod->sqnum, cs_sqnum);
+			goto out_dump;
+		}
+
+		printf("\tNODE %d", node_num++);
+		switch (snod->type) {
+		case UBIFS_CS_NODE:
+			printf(" <START COMMIT>");
+		case UBIFS_REF_NODE: {
+			printf(":\n");
+			dump_node(c, snod->node);
+			break;
+		}
+		default:
+			ubifs_err(c, "unexpected node in log");
+			goto out_dump;
+		}
+	}
+	err = !sleb->endpt;
+out:
+	ubifs_scan_destroy(sleb);
+	return err;
+
+out_dump:
+	ubifs_err(c, "log error detected while replaying the log at LEB %d:%lu",
+		  lnum, offs + snod->offs);
+	ubifs_scan_destroy(sleb);
+	return -EINVAL;
+
+}
+
+static int dump_log(void)
+{
+	int err, lnum, ltail_lnum, log_last;
+
+	lnum = ltail_lnum = mst.log_lnum;
+	log_last = UBIFS_LOG_LNUM + sup.log_lebs - 1;
+	printf("LOG AREA:\n");
+	while (lnum <= log_last) {
+		err = __dump_log_leb(lnum);
+		if (err == 1) {
+			if (lnum != mst.log_lnum)
+				/* We hit the end of the log */
+				break;
+
+			/*
+			 * The head of the log must always start with the
+			 * "commit start" node on a properly formatted UBIFS.
+			 * But we found no nodes at all, which means that
+			 * someting went wrong and we cannot proceed mounting
+			 * the file-system.
+			 */
+			ubifs_err(c, "no UBIFS nodes found at the log head LEB %d:%d, possibly corrupted",
+				  lnum, 0);
+			err = -EINVAL;
+		}
+		if (err)
+			goto out;
+		lnum++;
+	}
+
+	err = 0;
+out:
+	return err;
+}
+
 static int dump()
 {
 	int err = 0;
@@ -598,6 +734,10 @@ static int dump()
 	err = dump_master();
 	if (err)
 		goto free;
+
+	err = dump_log();
+	if (err)
+		goto free;
 free:
 	free(leb_buf);
 out:
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 20/38] ubifs: introduce lprops lib
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (18 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 19/38] ubifs: ubifs_dump: dump log area Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 21/38] ubifs: lpt: implement functions to scan lpt Dongsheng Yang
                   ` (17 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

Copy lprops.c from kernel to ubifs-utils/.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/include/lprops.h |  6 ++++
 ubifs-utils/lib/lprops.c     | 79 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+)
 create mode 100644 ubifs-utils/include/lprops.h
 create mode 100644 ubifs-utils/lib/lprops.c

diff --git a/ubifs-utils/include/lprops.h b/ubifs-utils/include/lprops.h
new file mode 100644
index 0000000..5bf3108
--- /dev/null
+++ b/ubifs-utils/include/lprops.h
@@ -0,0 +1,6 @@
+#ifndef __UBIFS_LPROPS_H__
+#define __UBIFS_LPROPS_H__
+
+int ubifs_categorize_lprops(const struct ubifs_info *c,
+			    const struct ubifs_lprops *lprops);
+#endif
diff --git a/ubifs-utils/lib/lprops.c b/ubifs-utils/lib/lprops.c
new file mode 100644
index 0000000..818d220
--- /dev/null
+++ b/ubifs-utils/lib/lprops.c
@@ -0,0 +1,79 @@
+/*
+ * This file is part of UBIFS.
+ *
+ * Copyright (C) 2006-2008 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Adrian Hunter
+ *          Artem Bityutskiy (Битюцкий Артём)
+ */
+
+/*
+ * This file implements the functions that access LEB properties and their
+ * categories. LEBs are categorized based on the needs of UBIFS, and the
+ * categories are stored as either heaps or lists to provide a fast way of
+ * finding a LEB in a particular category. For example, UBIFS may need to find
+ * an empty LEB for the journal, or a very dirty LEB for garbage collection.
+ */
+
+#include "ubifs_common.h"
+
+/* common.h requires the PROGRAM_NAME macro */
+#define PROGRAM_NAME "ubifs-lprops"
+#include "common.h"
+
+#include "ubifs.h"
+
+/**
+ * ubifs_categorize_lprops - categorize LEB properties.
+ * @c: UBIFS file-system description object
+ * @lprops: LEB properties to categorize
+ *
+ * LEB properties are categorized to enable fast find operations. This function
+ * returns the LEB category to which the LEB properties belong. Note however
+ * that if the LEB category is stored as a heap and the heap is full, the
+ * LEB properties may have their category changed to %LPROPS_UNCAT.
+ */
+int ubifs_categorize_lprops(const struct ubifs_info *c,
+			    const struct ubifs_lprops *lprops)
+{
+	if (lprops->flags & LPROPS_TAKEN)
+		return LPROPS_UNCAT;
+
+	if (lprops->free == c->leb_size) {
+		ubifs_assert(!(lprops->flags & LPROPS_INDEX));
+		return LPROPS_EMPTY;
+	}
+
+	if (lprops->free + lprops->dirty == c->leb_size) {
+		if (lprops->flags & LPROPS_INDEX)
+			return LPROPS_FRDI_IDX;
+		else
+			return LPROPS_FREEABLE;
+	}
+
+	if (lprops->flags & LPROPS_INDEX) {
+		if (lprops->dirty + lprops->free >= c->min_idx_node_sz)
+			return LPROPS_DIRTY_IDX;
+	} else {
+		if (lprops->dirty >= c->dead_wm &&
+		    lprops->dirty > lprops->free)
+			return LPROPS_DIRTY;
+		if (lprops->free > 0)
+			return LPROPS_FREE;
+	}
+
+	return LPROPS_UNCAT;
+}
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 21/38] ubifs: lpt: implement functions to scan lpt
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (19 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 20/38] ubifs: introduce lprops lib Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 22/38] ubifs: ubifs_dump: dump lpt area Dongsheng Yang
                   ` (16 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

Implement ubifs_scan_lpt_nolock() in lpt to scan lpt.
And then we can use this function to scan the lpt
and dump all lprops out.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/include/lpt.h |   3 +
 ubifs-utils/lib/lpt.c     | 661 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 663 insertions(+), 1 deletion(-)

diff --git a/ubifs-utils/include/lpt.h b/ubifs-utils/include/lpt.h
index e2f7348..d4264c3 100644
--- a/ubifs-utils/include/lpt.h
+++ b/ubifs-utils/include/lpt.h
@@ -25,5 +25,8 @@
 int calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs, int *big_lpt);
 int create_lpt(struct ubifs_info *c);
 int ubifs_calc_lpt_geom(struct ubifs_info *c);
+int unpack_ltab(const struct ubifs_info *c, void *buf);
+int ubifs_lpt_scan_nolock(struct ubifs_info *c, int start_lnum, int end_lnum,
+			  ubifs_lpt_scan_callback scan_cb, void *data);
 
 #endif
diff --git a/ubifs-utils/lib/lpt.c b/ubifs-utils/lib/lpt.c
index 26fb4dd..52fbcfa 100644
--- a/ubifs-utils/lib/lpt.c
+++ b/ubifs-utils/lib/lpt.c
@@ -29,6 +29,7 @@
 #include "crc16.h"
 #include "ubifs.h"
 #include "lpt.h"
+#include "lprops.h"
 #include "io.h"
 
 /**
@@ -402,7 +403,6 @@ int create_lpt(struct ubifs_info *c)
 	len = 0;
 	/* Number of leaf nodes (pnodes) */
 	cnt = (c->main_lebs + UBIFS_LPT_FANOUT - 1) >> UBIFS_LPT_FANOUT_SHIFT;
-	//printf("pnode_cnt=%d\n",cnt);
 
 	/*
 	 * To calculate the internal node branches, we keep information about
@@ -614,3 +614,662 @@ int ubifs_calc_lpt_geom(struct ubifs_info *c)
 	}
 	return 0;
 }
+
+/**
+ * struct lpt_scan_node - somewhere to put nodes while we scan LPT.
+ * @nnode: where to keep a nnode
+ * @pnode: where to keep a pnode
+ * @cnode: where to keep a cnode
+ * @in_tree: is the node in the tree in memory
+ * @ptr.nnode: pointer to the nnode (if it is an nnode) which may be here or in
+ * the tree
+ * @ptr.pnode: ditto for pnode
+ * @ptr.cnode: ditto for cnode
+ */
+struct lpt_scan_node {
+	union {
+		struct ubifs_nnode nnode;
+		struct ubifs_pnode pnode;
+		struct ubifs_cnode cnode;
+	};
+	int in_tree;
+	union {
+		struct ubifs_nnode *nnode;
+		struct ubifs_pnode *pnode;
+		struct ubifs_cnode *cnode;
+	} ptr;
+};
+
+/**
+ * ubifs_unpack_bits - unpack bit fields.
+ * @addr: address at which to unpack (passed and next address returned)
+ * @pos: bit position at which to unpack (passed and next position returned)
+ * @nrbits: number of bits of value to unpack (1-32)
+ *
+ * This functions returns the value unpacked.
+ */
+uint32_t ubifs_unpack_bits(uint8_t **addr, int *pos, int nrbits)
+{
+	const int k = 32 - nrbits;
+	uint8_t *p = *addr;
+	int b = *pos;
+	uint32_t val = 0;
+	const int bytes = (nrbits + b + 7) >> 3;
+
+	ubifs_assert(nrbits > 0);
+	ubifs_assert(nrbits <= 32);
+	ubifs_assert(*pos >= 0);
+	ubifs_assert(*pos < 8);
+	if (b) {
+		switch (bytes) {
+		case 2:
+			val = p[1];
+			break;
+		case 3:
+			val = p[1] | ((uint32_t)p[2] << 8);
+			break;
+		case 4:
+			val = p[1] | ((uint32_t)p[2] << 8) |
+				     ((uint32_t)p[3] << 16);
+			break;
+		case 5:
+			val = p[1] | ((uint32_t)p[2] << 8) |
+				     ((uint32_t)p[3] << 16) |
+				     ((uint32_t)p[4] << 24);
+		}
+		val <<= (8 - b);
+		val |= *p >> b;
+		nrbits += b;
+	} else {
+		switch (bytes) {
+		case 1:
+			val = p[0];
+			break;
+		case 2:
+			val = p[0] | ((uint32_t)p[1] << 8);
+			break;
+		case 3:
+			val = p[0] | ((uint32_t)p[1] << 8) |
+				     ((uint32_t)p[2] << 16);
+			break;
+		case 4:
+			val = p[0] | ((uint32_t)p[1] << 8) |
+				     ((uint32_t)p[2] << 16) |
+				     ((uint32_t)p[3] << 24);
+			break;
+		}
+	}
+	val <<= k;
+	val >>= k;
+	b = nrbits & 7;
+	p += nrbits >> 3;
+	*addr = p;
+	*pos = b;
+	ubifs_assert((val >> nrbits) == 0 || nrbits - b == 32);
+	return val;
+}
+/**
+ * calc_nnode_num_from_parent - calculate nnode number.
+ * @c: UBIFS file-system description object
+ * @parent: parent nnode
+ * @iip: index in parent
+ *
+ * The nnode number is a number that uniquely identifies a nnode and can be used
+ * easily to traverse the tree from the root to that nnode.
+ *
+ * This function calculates and returns the nnode number based on the parent's
+ * nnode number and the index in parent.
+ */
+static int calc_nnode_num_from_parent(const struct ubifs_info *c,
+				      struct ubifs_nnode *parent, int iip)
+{
+	int num, shft;
+
+	if (!parent)
+		return 1;
+	shft = (c->lpt_hght - parent->level) * UBIFS_LPT_FANOUT_SHIFT;
+	num = parent->num ^ (1 << shft);
+	num |= (UBIFS_LPT_FANOUT + iip) << shft;
+	return num;
+}
+
+int ubifs_unpack_nnode(const struct ubifs_info *c, void *buf,
+		       struct ubifs_nnode *nnode);
+/**
+ * scan_get_nnode - for the scan, get a nnode from either the tree or flash.
+ * @c: the UBIFS file-system description object
+ * @path: where to put the nnode
+ * @parent: parent of the nnode
+ * @iip: index in parent of the nnode
+ *
+ * This function returns a pointer to the nnode on success or a negative error
+ * code on failure.
+ */
+static struct ubifs_nnode *scan_get_nnode(struct ubifs_info *c,
+					  struct lpt_scan_node *path,
+					  struct ubifs_nnode *parent, int iip)
+{
+	struct ubifs_nbranch *branch;
+	struct ubifs_nnode *nnode;
+	int i = max_t(int, c->nnode_sz, c->pnode_sz);
+	void *buf = malloc(i);;
+	int err;
+
+	branch = &parent->nbranch[iip];
+	nnode = branch->nnode;
+	if (nnode) {
+		path->in_tree = 1;
+		path->ptr.nnode = nnode;
+		free(buf);
+		return nnode;
+	}
+	nnode = &path->nnode;
+	path->in_tree = 0;
+	path->ptr.nnode = nnode;
+	memset(nnode, 0, sizeof(struct ubifs_nnode));
+	if (branch->lnum == 0) {
+		/*
+		 * This nnode was not written which just means that the LEB
+		 * properties in the subtree below it describe empty LEBs. We
+		 * make the nnode as though we had read it, which in fact means
+		 * doing almost nothing.
+		 */
+		if (c->big_lpt)
+			nnode->num = calc_nnode_num_from_parent(c, parent, iip);
+	} else {
+		err = ubifs_read(branch->lnum * c->leb_size + branch->offs, c->nnode_sz, buf);
+		if (err) {
+			free(buf);
+			return ERR_PTR(err);
+		}
+		err = ubifs_unpack_nnode(c, buf, nnode);
+		if (err) {
+			free(buf);
+			return ERR_PTR(err);
+		}
+	}
+	if (!c->big_lpt)
+		nnode->num = calc_nnode_num_from_parent(c, parent, iip);
+	nnode->level = parent->level - 1;
+	nnode->parent = parent;
+	nnode->iip = iip;
+
+	free(buf);
+	return nnode;
+}
+/**
+ * calc_pnode_num_from_parent - calculate pnode number.
+ * @c: UBIFS file-system description object
+ * @parent: parent nnode
+ * @iip: index in parent
+ *
+ * The pnode number is a number that uniquely identifies a pnode and can be used
+ * easily to traverse the tree from the root to that pnode.
+ *
+ * This function calculates and returns the pnode number based on the parent's
+ * nnode number and the index in parent.
+ */
+static int calc_pnode_num_from_parent(const struct ubifs_info *c,
+				      struct ubifs_nnode *parent, int iip)
+{
+	int i, n = c->lpt_hght - 1, pnum = parent->num, num = 0;
+
+	for (i = 0; i < n; i++) {
+		num <<= UBIFS_LPT_FANOUT_SHIFT;
+		num |= pnum & (UBIFS_LPT_FANOUT - 1);
+		pnum >>= UBIFS_LPT_FANOUT_SHIFT;
+	}
+	num <<= UBIFS_LPT_FANOUT_SHIFT;
+	num |= iip;
+	return num;
+}
+/**
+ * set_pnode_lnum - set LEB numbers on a pnode.
+ * @c: UBIFS file-system description object
+ * @pnode: pnode to update
+ *
+ * This function calculates the LEB numbers for the LEB properties it contains
+ * based on the pnode number.
+ */
+static void set_pnode_lnum(const struct ubifs_info *c,
+			   struct ubifs_pnode *pnode)
+{
+	int i, lnum;
+
+	lnum = (pnode->num << UBIFS_LPT_FANOUT_SHIFT) + c->main_first;
+	for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
+		if (lnum >= c->leb_cnt)
+			return;
+		pnode->lprops[i].lnum = lnum++;
+	}
+}
+/**
+ * check_lpt_crc - check LPT node crc is correct.
+ * @c: UBIFS file-system description object
+ * @buf: buffer containing node
+ * @len: length of node
+ *
+ * This function returns %0 on success and a negative error code on failure.
+ */
+int check_lpt_crc(const struct ubifs_info *c __attribute__((unused)), void *buf, int len)
+{
+	int pos = 0;
+	uint8_t *addr = buf;
+	uint16_t crc, calc_crc;
+
+	crc = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_CRC_BITS);
+	calc_crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
+			 len - UBIFS_LPT_CRC_BYTES);
+	if (crc != calc_crc) {
+		ubifs_err(c, "invalid crc in LPT node: crc %hx calc %hx",
+			  crc, calc_crc);
+		return -EINVAL;
+	}
+	return 0;
+}
+/**
+ * check_lpt_type - check LPT node type is correct.
+ * @c: UBIFS file-system description object
+ * @addr: address of type bit field is passed and returned updated here
+ * @pos: position of type bit field is passed and returned updated here
+ * @type: expected type
+ *
+ * This function returns %0 on success and a negative error code on failure.
+ */
+int check_lpt_type(const struct ubifs_info *c __attribute__((unused)), uint8_t **addr,
+			  int *pos, int type)
+{
+	int node_type;
+
+	node_type = ubifs_unpack_bits(addr, pos, UBIFS_LPT_TYPE_BITS);
+	if (node_type != type) {
+		ubifs_err(c, "invalid type (%d) in LPT node type %d",
+			  node_type, type);
+		return -EINVAL;
+	}
+	return 0;
+}
+/**
+ * unpack_pnode - unpack a pnode.
+ * @c: UBIFS file-system description object
+ * @buf: buffer containing packed pnode to unpack
+ * @pnode: pnode structure to fill
+ *
+ * This function returns %0 on success and a negative error code on failure.
+ */
+static int unpack_pnode(const struct ubifs_info *c, void *buf,
+			struct ubifs_pnode *pnode)
+{
+	uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
+	int i, pos = 0, err;
+
+	err = check_lpt_type(c, &addr, &pos, UBIFS_LPT_PNODE);
+	if (err)
+		return err;
+	if (c->big_lpt)
+		pnode->num = ubifs_unpack_bits(&addr, &pos, c->pcnt_bits);
+	for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
+		struct ubifs_lprops * const lprops = &pnode->lprops[i];
+
+		lprops->free = ubifs_unpack_bits(&addr, &pos, c->space_bits);
+		lprops->free <<= 3;
+		lprops->dirty = ubifs_unpack_bits(&addr, &pos, c->space_bits);
+		lprops->dirty <<= 3;
+
+		if (ubifs_unpack_bits(&addr, &pos, 1))
+			lprops->flags = LPROPS_INDEX;
+		else
+			lprops->flags = 0;
+		lprops->flags |= ubifs_categorize_lprops(c, lprops);
+	}
+	err = check_lpt_crc(c, buf, c->pnode_sz);
+	return err;
+}
+/**
+ * ubifs_unpack_nnode - unpack a nnode.
+ * @c: UBIFS file-system description object
+ * @buf: buffer containing packed nnode to unpack
+ * @nnode: nnode structure to fill
+ *
+ * This function returns %0 on success and a negative error code on failure.
+ */
+int ubifs_unpack_nnode(const struct ubifs_info *c, void *buf,
+		       struct ubifs_nnode *nnode)
+{
+	uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
+	int i, pos = 0, err;
+
+	err = check_lpt_type(c, &addr, &pos, UBIFS_LPT_NNODE);
+	if (err)
+		return err;
+	if (c->big_lpt)
+		nnode->num = ubifs_unpack_bits(&addr, &pos, c->pcnt_bits);
+	for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
+		int lnum;
+
+		lnum = ubifs_unpack_bits(&addr, &pos, c->lpt_lnum_bits) +
+		       c->lpt_first;
+		if (lnum == c->lpt_last + 1)
+			lnum = 0;
+		nnode->nbranch[i].lnum = lnum;
+		nnode->nbranch[i].offs = ubifs_unpack_bits(&addr, &pos,
+						     c->lpt_offs_bits);
+	}
+	err = check_lpt_crc(c, buf, c->nnode_sz);
+	return err;
+}
+/**
+ * unpack_ltab - unpack the LPT's own lprops table.
+ * @c: UBIFS file-system description object
+ * @buf: buffer from which to unpack
+ *
+ * This function returns %0 on success and a negative error code on failure.
+ */
+int unpack_ltab(const struct ubifs_info *c, void *buf)
+{
+	uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
+	int i, pos = 0, err;
+
+	err = check_lpt_type(c, &addr, &pos, UBIFS_LPT_LTAB);
+	if (err)
+		return err;
+	for (i = 0; i < c->lpt_lebs; i++) {
+		int free = ubifs_unpack_bits(&addr, &pos, c->lpt_spc_bits);
+		int dirty = ubifs_unpack_bits(&addr, &pos, c->lpt_spc_bits);
+
+		if (free < 0 || free > c->leb_size || dirty < 0 ||
+		    dirty > c->leb_size || free + dirty > c->leb_size)
+			return -EINVAL;
+
+		c->ltab[i].free = free;
+		c->ltab[i].dirty = dirty;
+		c->ltab[i].tgc = 0;
+		c->ltab[i].cmt = 0;
+	}
+	return 0;
+}
+
+/**
+ * scan_get_pnode - for the scan, get a pnode from either the tree or flash.
+ * @c: the UBIFS file-system description object
+ * @path: where to put the pnode
+ * @parent: parent of the pnode
+ * @iip: index in parent of the pnode
+ *
+ * This function returns a pointer to the pnode on success or a negative error
+ * code on failure.
+ */
+static struct ubifs_pnode *scan_get_pnode(struct ubifs_info *c,
+					  struct lpt_scan_node *path,
+					  struct ubifs_nnode *parent, int iip)
+{
+	struct ubifs_nbranch *branch;
+	struct ubifs_pnode *pnode;
+	int i = max_t(int, c->nnode_sz, c->pnode_sz);
+	void *buf = malloc(i);;
+	int err;
+
+	branch = &parent->nbranch[iip];
+	pnode = branch->pnode;
+	if (pnode) {
+		path->in_tree = 1;
+		path->ptr.pnode = pnode;
+		free(buf);
+		return pnode;
+	}
+	pnode = &path->pnode;
+	path->in_tree = 0;
+	path->ptr.pnode = pnode;
+	memset(pnode, 0, sizeof(struct ubifs_pnode));
+	if (branch->lnum == 0) {
+		/*
+		 * This pnode was not written which just means that the LEB
+		 * properties in it describe empty LEBs. We make the pnode as
+		 * though we had read it.
+		 */
+		int i;
+
+		if (c->big_lpt)
+			pnode->num = calc_pnode_num_from_parent(c, parent, iip);
+		for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
+			struct ubifs_lprops * const lprops = &pnode->lprops[i];
+
+			lprops->free = c->leb_size;
+			lprops->flags = ubifs_categorize_lprops(c, lprops);
+		}
+	} else {
+		ubifs_assert(branch->lnum >= c->lpt_first &&
+			     branch->lnum <= c->lpt_last);
+		ubifs_assert(branch->offs >= 0 && branch->offs < c->leb_size);
+		err = ubifs_read(branch->lnum * c->leb_size + branch->offs, c->pnode_sz, buf);
+		if (err) {
+			free(buf);
+			return ERR_PTR(err);
+		}
+		err = unpack_pnode(c, buf, pnode);
+		if (err) {
+			free(buf);
+			return ERR_PTR(err);
+		}
+	}
+	if (!c->big_lpt)
+		pnode->num = calc_pnode_num_from_parent(c, parent, iip);
+	pnode->parent = parent;
+	pnode->iip = iip;
+	set_pnode_lnum(c, pnode);
+	free(buf);
+	return pnode;
+}
+/**
+ * ubifs_read_nnode - read a nnode from flash and link it to the tree in memory.
+ * @c: UBIFS file-system description object
+ * @parent: parent nnode (or NULL for the root)
+ * @iip: index in parent
+ *
+ * This function returns %0 on success and a negative error code on failure.
+ */
+int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
+{
+	struct ubifs_nbranch *branch = NULL;
+	struct ubifs_nnode *nnode = NULL;
+	void *buf = c->lpt_nod_buf;
+	int err, lnum, offs;
+
+	if (parent) {
+		branch = &parent->nbranch[iip];
+		lnum = branch->lnum;
+		offs = branch->offs;
+	} else {
+		lnum = c->lpt_lnum;
+		offs = c->lpt_offs;
+	}
+	nnode = kzalloc(sizeof(struct ubifs_nnode), GFP_NOFS);
+	if (!nnode) {
+		err = -ENOMEM;
+		goto out;
+	}
+	if (lnum == 0) {
+		/*
+		 * This nnode was not written which just means that the LEB
+		 * properties in the subtree below it describe empty LEBs. We
+		 * make the nnode as though we had read it, which in fact means
+		 * doing almost nothing.
+		 */
+		if (c->big_lpt)
+			nnode->num = calc_nnode_num_from_parent(c, parent, iip);
+	} else {
+		err = ubifs_read(lnum * c->leb_size + offs, c->nnode_sz, buf);
+		if (err)
+			goto out;
+		err = ubifs_unpack_nnode(c, buf, nnode);
+		if (err)
+			goto out;
+	}
+	if (!c->big_lpt)
+		nnode->num = calc_nnode_num_from_parent(c, parent, iip);
+	if (parent) {
+		branch->nnode = nnode;
+		nnode->level = parent->level - 1;
+	} else {
+		c->nroot = nnode;
+		nnode->level = c->lpt_hght;
+	}
+	nnode->parent = parent;
+	nnode->iip = iip;
+	return 0;
+
+out:
+	ubifs_err(c, "error %d reading nnode at %d:%d", err, lnum, offs);
+	kfree(nnode);
+	return err;
+}
+
+/**
+ * ubifs_lpt_scan_nolock - scan the LPT.
+ * @c: the UBIFS file-system description object
+ * @start_lnum: LEB number from which to start scanning
+ * @end_lnum: LEB number at which to stop scanning
+ * @scan_cb: callback function called for each lprops
+ * @data: data to be passed to the callback function
+ *
+ * This function returns %0 on success and a negative error code on failure.
+ */
+int ubifs_lpt_scan_nolock(struct ubifs_info *c, int start_lnum, int end_lnum,
+			  ubifs_lpt_scan_callback scan_cb, void *data)
+{
+	int err = 0, i, h, iip, shft;
+	struct ubifs_nnode *nnode;
+	struct ubifs_pnode *pnode;
+	struct lpt_scan_node *path;
+
+	if (start_lnum == -1) {
+		start_lnum = end_lnum + 1;
+		if (start_lnum >= c->leb_cnt)
+			start_lnum = c->main_first;
+	}
+
+	ubifs_assert(start_lnum >= c->main_first && start_lnum < c->leb_cnt);
+	ubifs_assert(end_lnum >= c->main_first && end_lnum < c->leb_cnt);
+
+	if (!c->nroot) {
+		err = ubifs_read_nnode(c, NULL, 0);
+		if (err)
+			return err;
+	}
+
+	path = kmalloc(sizeof(struct lpt_scan_node) * (c->lpt_hght + 1),
+		       GFP_NOFS);
+	if (!path)
+		return -ENOMEM;
+
+	path[0].ptr.nnode = c->nroot;
+	path[0].in_tree = 1;
+again:
+	/* Descend to the pnode containing start_lnum */
+	nnode = c->nroot;
+	i = start_lnum - c->main_first;
+	shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT;
+	for (h = 1; h < c->lpt_hght; h++) {
+		iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
+		shft -= UBIFS_LPT_FANOUT_SHIFT;
+		nnode = scan_get_nnode(c, path + h, nnode, iip);
+		if (IS_ERR(nnode)) {
+			err = PTR_ERR(nnode);
+			goto out;
+		}
+	}
+	iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
+	pnode = scan_get_pnode(c, path + h, nnode, iip);
+	if (IS_ERR(pnode)) {
+		err = PTR_ERR(pnode);
+		goto out;
+	}
+	iip = (i & (UBIFS_LPT_FANOUT - 1));
+
+	/* Loop for each lprops */
+	while (1) {
+		struct ubifs_lprops *lprops = &pnode->lprops[iip];
+		int ret, lnum = lprops->lnum;
+
+		ret = scan_cb(c, lprops, path[h].in_tree, data);
+		if (ret < 0) {
+			err = ret;
+			goto out;
+		}
+		if (ret & LPT_SCAN_ADD) {
+			/* Add all the nodes in path to the tree in memory */
+			for (h = 1; h < c->lpt_hght; h++) {
+				const size_t sz = sizeof(struct ubifs_nnode);
+				struct ubifs_nnode *parent;
+
+				if (path[h].in_tree)
+					continue;
+				nnode = malloc(sz);
+				if (!nnode) {
+					err = -ENOMEM;
+					goto out;
+				}
+				memcpy(nnode, &path[h].nnode, sz);
+				parent = nnode->parent;
+				parent->nbranch[nnode->iip].nnode = nnode;
+				path[h].ptr.nnode = nnode;
+				path[h].in_tree = 1;
+				path[h + 1].cnode.parent = nnode;
+			}
+		}
+		if (ret & LPT_SCAN_STOP) {
+			err = 0;
+			break;
+		}
+		/* Get the next lprops */
+		if (lnum == end_lnum) {
+			/*
+			 * We got to the end without finding what we were
+			 * looking for
+			 */
+			err = -ENOSPC;
+			goto out;
+		}
+		if (lnum + 1 >= c->leb_cnt) {
+			/* Wrap-around to the beginning */
+			start_lnum = c->main_first;
+			goto again;
+		}
+		if (iip + 1 < UBIFS_LPT_FANOUT) {
+			/* Next lprops is in the same pnode */
+			iip += 1;
+			continue;
+		}
+		/* We need to get the next pnode. Go up until we can go right */
+		iip = pnode->iip;
+		while (1) {
+			h -= 1;
+			ubifs_assert(h >= 0);
+			nnode = path[h].ptr.nnode;
+			if (iip + 1 < UBIFS_LPT_FANOUT)
+				break;
+			iip = nnode->iip;
+		}
+		/* Go right */
+		iip += 1;
+		/* Descend to the pnode */
+		h += 1;
+		for (; h < c->lpt_hght; h++) {
+			nnode = scan_get_nnode(c, path + h, nnode, iip);
+			if (IS_ERR(nnode)) {
+				err = PTR_ERR(nnode);
+				goto out;
+			}
+			iip = 0;
+		}
+		pnode = scan_get_pnode(c, path + h, nnode, iip);
+		if (IS_ERR(pnode)) {
+			err = PTR_ERR(pnode);
+			goto out;
+		}
+		iip = 0;
+	}
+out:
+	kfree(path);
+	return err;
+}
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 22/38] ubifs: ubifs_dump: dump lpt area
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (20 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 21/38] ubifs: lpt: implement functions to scan lpt Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 23/38] ubifs: ubifs_dump: dump index area Dongsheng Yang
                   ` (15 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

At first dump the ltab and then scan the whole lpt,
dumping every lprops in it.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 Makefile                            |   2 +-
 ubifs-utils/ubifs_dump/ubifs_dump.c | 170 ++++++++++++++++++++++++++++++++++++
 2 files changed, 171 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 1d7e5f2..0be4772 100644
--- a/Makefile
+++ b/Makefile
@@ -130,7 +130,7 @@ $(foreach v,$(UBI_BINS),$(eval $(call mkdep,ubi-utils/,$(v),libubi.a ubiutils-co
 $(foreach v,crc16.o lpt.o compr.o devtable.o io.o hashtable.o hashtable_itr.o,$(eval UBIFS_LIBS += ../lib/$(v)))
 
 obj-ubifs_dump = $(UBIFS_LIBS)
-obj-ubifs_dump += ../lib/scan.o
+obj-ubifs_dump += ../lib/scan.o ../lib/lprops.o
 LDFLAGS_ubifs_dump = $(ZLIBLDFLAGS) $(LZOLDFLAGS) $(UUIDLDFLAGS)
 LDLIBS_ubifs_dump = -lz -llzo2 -lm -luuid
 $(call mkdep,ubifs-utils/ubifs_dump/,ubifs_dump,,ubi-utils/libubi.a)
diff --git a/ubifs-utils/ubifs_dump/ubifs_dump.c b/ubifs-utils/ubifs_dump/ubifs_dump.c
index d7a2951..4b255e3 100644
--- a/ubifs-utils/ubifs_dump/ubifs_dump.c
+++ b/ubifs-utils/ubifs_dump/ubifs_dump.c
@@ -717,6 +717,172 @@ out:
 	return err;
 }
 
+void ubifs_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp)
+{
+	int spc, dark = 0, dead = 0;
+
+	if ((lp->flags & LPROPS_CAT_MASK) == LPROPS_EMPTY)
+		return;
+
+	spc = lp->free + lp->dirty;
+	dead = spc;
+
+	if (lp->flags & LPROPS_INDEX)
+		printf("\tLEB %-7d free %-8d dirty %-8d used %-8d free + dirty %-8d flags %#x (",
+		       lp->lnum, lp->free, lp->dirty, c->leb_size - spc, spc,
+		       lp->flags);
+	else
+		printf("\tLEB %-7d free %-8d dirty %-8d used %-8d free + dirty %-8d dark %-4d dead %-4d nodes fit %-3d flags %#-4x (",
+		       lp->lnum, lp->free, lp->dirty, c->leb_size - spc, spc,
+		       dark, dead, (int)(spc / UBIFS_MAX_NODE_SZ), lp->flags);
+
+	if (lp->flags & LPROPS_TAKEN) {
+		if (lp->flags & LPROPS_INDEX)
+			printf("index, taken");
+		else
+			printf("taken");
+	} else {
+		const char *s;
+
+		if (lp->flags & LPROPS_INDEX) {
+			switch (lp->flags & LPROPS_CAT_MASK) {
+			case LPROPS_DIRTY_IDX:
+				s = "dirty index";
+				break;
+			case LPROPS_FRDI_IDX:
+				s = "freeable index";
+				break;
+			default:
+				s = "index";
+			}
+		} else {
+			switch (lp->flags & LPROPS_CAT_MASK) {
+			case LPROPS_UNCAT:
+				s = "not categorized";
+				break;
+			case LPROPS_DIRTY:
+				s = "dirty";
+				break;
+			case LPROPS_FREE:
+				s = "free";
+				break;
+			case LPROPS_EMPTY:
+				s = "empty";
+				break;
+			case LPROPS_FREEABLE:
+				s = "freeable";
+				break;
+			default:
+				s = NULL;
+				break;
+			}
+		}
+		printf("%s", s);
+	}
+
+	if (lp->lnum == c->gc_lnum)
+		printf(", GC LEB");
+	printf(")\n");
+}
+
+void ubifs_dump_lstats(const struct ubifs_lp_stats *lst)
+{
+	printf("\tempty_lebs %d, idx_lebs  %d\n",
+	       lst->empty_lebs, lst->idx_lebs);
+	printf("\ttaken_empty_lebs %d, total_free %lld, total_dirty %lld\n",
+	       lst->taken_empty_lebs, lst->total_free, lst->total_dirty);
+	printf("\ttotal_used %lld, total_dark %lld, total_dead %lld\n",
+	       lst->total_used, lst->total_dark, lst->total_dead);
+	printf("\n");
+}
+
+static int scan_dump_cb(struct ubifs_info *c,
+			 const struct ubifs_lprops *lp, int in_tree __attribute__((unused)),
+			 struct ubifs_lp_stats *lst __attribute__((unused)))
+{
+	ubifs_dump_lprop(c, lp);
+	return 0;
+}
+
+static int ubifs_dump_lprops(struct ubifs_info *c)
+{
+	printf("\tLPROPS statistics: \n");
+	ubifs_dump_lstats(&c->lst);
+	printf("\tLPROPS TREE: \n");
+	c->lpt_nod_buf = malloc(min(c->nnode_sz, c->pnode_sz));
+	ubifs_lpt_scan_nolock(c, c->main_first, c->leb_cnt - 1,
+			  (ubifs_lpt_scan_callback)scan_dump_cb, NULL);
+	printf("\n");
+
+	return 0;
+}
+
+/**
+ * read_ltab - read LPT's own lprops table.
+ * @c: UBIFS file-system description object
+ *
+ * This function returns %0 on success and a negative error code on failure.
+ */
+static int read_ltab(struct ubifs_info *c)
+{
+	int err;
+	void *buf;
+
+	buf = vmalloc(c->ltab_sz);
+	if (!buf)
+		return -ENOMEM;
+	err = ubifs_read(c->ltab_lnum * c->leb_size + c->ltab_offs, c->ltab_sz, buf);
+	if (err)
+		goto out;
+	err = unpack_ltab(c, buf);
+out:
+	vfree(buf);
+	return err;
+}
+
+static int ubifs_dump_lpt_info(struct ubifs_info *c)
+{
+	int i;
+	int ret = 0;
+
+	c->ltab = malloc(c->lpt_lebs * sizeof(struct ubifs_lprops));
+	if (!c->ltab)
+		return err_msg("unable to allocate LPT ltab");
+
+	ret = read_ltab(c);
+	if (ret)
+		return ret;
+	printf("\tLPT INFO: \n");
+	printf("\tLPT root is at %d:%d\n", c->lpt_lnum, c->lpt_offs);
+	printf("\tLPT head is at %d:%d\n",
+	       c->nhead_lnum, c->nhead_offs);
+	printf("\tLPT ltab is at %d:%d\n", c->ltab_lnum, c->ltab_offs);
+	if (c->big_lpt)
+		printf("\tLPT lsave is at %d:%d\n",
+		       c->lsave_lnum, c->lsave_offs);
+	for (i = 0; i < c->lpt_lebs; i++)
+		printf("\tLPT LEB %d free %d dirty %d tgc %d cmt %d\n",
+		       i + c->lpt_first, c->ltab[i].free, c->ltab[i].dirty,
+		       c->ltab[i].tgc, c->ltab[i].cmt);
+	printf("\n");
+	return 0;
+}
+
+static int dump_lpt(void)
+{
+	int ret = 0;
+
+	printf("LPT AREA: \n");
+	ret = ubifs_dump_lpt_info(c);
+	if (ret)
+		return ret;
+
+	ret = ubifs_dump_lprops(c);
+	if (ret)
+		return ret;
+	return 0;
+}
+
 static int dump()
 {
 	int err = 0;
@@ -738,6 +904,10 @@ static int dump()
 	err = dump_log();
 	if (err)
 		goto free;
+
+	err = dump_lpt();
+	if (err)
+		goto free;
 free:
 	free(leb_buf);
 out:
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 23/38] ubifs: ubifs_dump: dump index area
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (21 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 22/38] ubifs: ubifs_dump: dump lpt area Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 24/38] ubifs: defs.h: introduce some compatible definitions about integer such as __u16 Dongsheng Yang
                   ` (14 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

Scan the whole index tree and dump each index node.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/ubifs_dump/ubifs_dump.c | 95 +++++++++++++++++++++++++++++++++++++
 1 file changed, 95 insertions(+)

diff --git a/ubifs-utils/ubifs_dump/ubifs_dump.c b/ubifs-utils/ubifs_dump/ubifs_dump.c
index 4b255e3..e72b8dd 100644
--- a/ubifs-utils/ubifs_dump/ubifs_dump.c
+++ b/ubifs-utils/ubifs_dump/ubifs_dump.c
@@ -883,6 +883,97 @@ static int dump_lpt(void)
 	return 0;
 }
 
+/**
+ * ubifs_read_node - read node.
+ * @c: UBIFS file-system description object
+ * @buf: buffer to read to
+ * @type: node type
+ * @len: node length (not aligned)
+ * @lnum: logical eraseblock number
+ * @offs: offset within the logical eraseblock
+ *
+ * This function reads a node of known type and and length, checks it and
+ * stores in @buf. Returns zero in case of success, %-EUCLEAN if CRC mismatched
+ * and a negative error code in case of failure.
+ */
+int ubifs_read_node(const struct ubifs_info *c, void *buf, int len,
+		    int lnum, loff_t offs)
+{
+	int err;
+
+	ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
+	ubifs_assert(len >= UBIFS_CH_SZ && offs + len <= c->leb_size);
+	ubifs_assert(!(offs & 7) && offs < c->leb_size);
+	ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT);
+
+	err = ubifs_read((loff_t)lnum * c->leb_size + offs, len, buf);
+	if (err && err != -EBADMSG)
+		return err;
+
+	return 0;
+}
+
+static int dump_zbr(struct ubifs_info *c, struct ubifs_zbranch *zbr)
+{
+	int i = 0;
+	int err = 0;
+	struct ubifs_idx_node *idx;
+	void *buf;
+
+	buf = malloc(zbr->len);
+	if (!buf)
+		return -ENOMEM;
+
+	err = ubifs_read_node(c, buf, zbr->len, zbr->lnum, zbr->offs);
+	if (err)
+		goto out;
+
+	dump_node(c, buf);
+
+	if (((struct ubifs_ch *)buf)->node_type != UBIFS_IDX_NODE)
+		goto out;
+
+	idx = ((struct ubifs_idx_node *)buf);
+	for (i = 0; i < le16_to_cpu(idx->child_cnt); i++) {
+		struct ubifs_branch *br;
+		struct ubifs_zbranch child;
+
+		br = ubifs_idx_branch(c, idx, i);
+		child.lnum = le32_to_cpu(br->lnum);
+		child.offs = le32_to_cpu(br->offs);
+		child.len = le32_to_cpu(br->len);
+		err = dump_zbr(c, &child);
+		if (err)
+			goto out;
+	}
+
+out:
+	free(buf);
+	return err;
+}
+
+static int dump_index()
+{
+	int err = 0;
+
+	printf("\tINDEX AREA: \n");
+	err = dump_zbr(c, &c->zroot);
+	if (err)
+		return err;
+	return 0;
+}
+
+static int dump_main()
+{
+	int err = 0;
+	printf("MAIN AREA: \n");
+	err = dump_index();
+	if (err)
+		return err;
+
+	return 0;
+}
+
 static int dump()
 {
 	int err = 0;
@@ -908,6 +999,10 @@ static int dump()
 	err = dump_lpt();
 	if (err)
 		goto free;
+
+	err = dump_main();
+	if (err)
+		goto free;
 free:
 	free(leb_buf);
 out:
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 24/38] ubifs: defs.h: introduce some compatible definitions about integer such as __u16
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (22 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 23/38] ubifs: ubifs_dump: dump index area Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 25/38] ubifs: introduce hexdump lib Dongsheng Yang
                   ` (13 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

Add __uXX class compatible definitions in defs.h

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/include/defs.h | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/ubifs-utils/include/defs.h b/ubifs-utils/include/defs.h
index ed42ab1..91ef175 100644
--- a/ubifs-utils/include/defs.h
+++ b/ubifs-utils/include/defs.h
@@ -174,6 +174,36 @@ static inline long IS_ERR(const void *ptr)
 #define ULONG_MAX       (~0UL)
 #endif
 
+#ifndef __CHECKER__
+/*
+ * Since we're using primitive definitions from kernel-space, we need to
+ * define __KERNEL__ so that system header files know which definitions
+ * to use.
+ */
+#define __KERNEL__
+#include <asm/types.h>
+typedef __u32 u32;
+typedef __u64 u64;
+typedef __u16 u16;
+typedef __u8 u8;
+typedef __s64 s64;
+typedef __s32 s32;
+
+/*
+ * Continuing to define __KERNEL__ breaks others parts of the code, so
+ * we can just undefine it now that we have the correct headers...
+ */
+#undef __KERNEL__
+#else
+typedef unsigned int u32;
+typedef unsigned int __u32;
+typedef unsigned long long u64;
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef long long s64;
+typedef int s32;
+#endif
+
 #if INT_MAX != 0x7fffffff
 #error : sizeof(int) must be 4 for this program
 #endif
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 25/38] ubifs: introduce hexdump lib
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (23 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 24/38] ubifs: defs.h: introduce some compatible definitions about integer such as __u16 Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 26/38] ubifs: ubifs_dump: dump data in hex format Dongsheng Yang
                   ` (12 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

Introduce a hexdump lib to allow us to dump data in hex format

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/include/hexdump.h |  21 +++++
 ubifs-utils/lib/hexdump.c     | 200 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 221 insertions(+)
 create mode 100644 ubifs-utils/include/hexdump.h
 create mode 100644 ubifs-utils/lib/hexdump.c

diff --git a/ubifs-utils/include/hexdump.h b/ubifs-utils/include/hexdump.h
new file mode 100644
index 0000000..f5f2800
--- /dev/null
+++ b/ubifs-utils/include/hexdump.h
@@ -0,0 +1,21 @@
+#ifndef __UBIFS_HEXDUMP_H__
+#define __UBIFS_HEXDUMP_H__
+
+#include "ubifs_common.h"
+
+static const char hex_asc[] = "0123456789abcdef";
+static const char hex_asc_upper[] = "0123456789ABCDEF";
+
+#define hex_asc_lo(x)	hex_asc[((x) & 0x0f)]
+#define hex_asc_hi(x)	hex_asc[((x) & 0xf0) >> 4]
+
+enum {
+	DUMP_PREFIX_NONE,
+	DUMP_PREFIX_ADDRESS,
+	DUMP_PREFIX_OFFSET
+};
+
+void print_hex_dump(const char *prefix_str, int prefix_type,
+		    int rowsize, int groupsize,
+		    const void *buf, size_t len, int ascii);
+#endif
diff --git a/ubifs-utils/lib/hexdump.c b/ubifs-utils/lib/hexdump.c
new file mode 100644
index 0000000..c58f7cc
--- /dev/null
+++ b/ubifs-utils/lib/hexdump.c
@@ -0,0 +1,200 @@
+/*
+ * lib/hexdump.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ */
+#include "hexdump.h"
+#define PROGRAM_NAME "hexdump"
+#include "common.h"
+/**
+ * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ * @rowsize: number of bytes to print per line; must be 16 or 32
+ * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
+ * @linebuf: where to put the converted data
+ * @linebuflen: total size of @linebuf, including space for terminating NUL
+ * @ascii: include ASCII after the hex output
+ *
+ * hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
+ * 16 or 32 bytes of input data converted to hex + ASCII output.
+ *
+ * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
+ * to a hex + ASCII dump at the supplied memory location.
+ * The converted output is always NUL-terminated.
+ *
+ * E.g.:
+ *   hex_dump_to_buffer(frame->data, frame->len, 16, 1,
+ *			linebuf, sizeof(linebuf), true);
+ *
+ * example output buffer:
+ * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f  @ABCDEFGHIJKLMNO
+ *
+ * Return:
+ * The amount of bytes placed in the buffer without terminating NUL. If the
+ * output was truncated, then the return value is the number of bytes
+ * (excluding the terminating NUL) which would have been written to the final
+ * string if enough space had been available.
+ */
+int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
+		       char *linebuf, size_t linebuflen, int ascii)
+{
+	const u8 *ptr = buf;
+	int ngroups;
+	u8 ch;
+	int j, lx = 0;
+	int ascii_column;
+	int ret;
+
+	if (rowsize != 16 && rowsize != 32)
+		rowsize = 16;
+
+	if (len > rowsize)		/* limit to one line at a time */
+		len = rowsize;
+	if (!is_power_of_2(groupsize) || groupsize > 8)
+		groupsize = 1;
+	if ((len % groupsize) != 0)	/* no mixed size output */
+		groupsize = 1;
+
+	ngroups = len / groupsize;
+	ascii_column = rowsize * 2 + rowsize / groupsize + 1;
+
+	if (!linebuflen)
+		goto overflow1;
+
+	if (!len)
+		goto nil;
+
+	if (groupsize == 8) {
+		const u64 *ptr8 = buf;
+
+		for (j = 0; j < ngroups; j++) {
+			ret = snprintf(linebuf + lx, linebuflen - lx,
+				       "%s%16.16llx", j ? " " : "",
+				       (unsigned long long)*(ptr8 + j));
+			if (ret >= linebuflen - lx)
+				goto overflow1;
+			lx += ret;
+		}
+	} else if (groupsize == 4) {
+		const u32 *ptr4 = buf;
+
+		for (j = 0; j < ngroups; j++) {
+			ret = snprintf(linebuf + lx, linebuflen - lx,
+				       "%s%8.8x", j ? " " : "",
+				       *(ptr4 + j));
+			if (ret >= linebuflen - lx)
+				goto overflow1;
+			lx += ret;
+		}
+	} else if (groupsize == 2) {
+		const u16 *ptr2 = buf;
+
+		for (j = 0; j < ngroups; j++) {
+			ret = snprintf(linebuf + lx, linebuflen - lx,
+				       "%s%4.4x", j ? " " : "",
+				       *(ptr2 + j));
+			if (ret >= linebuflen - lx)
+				goto overflow1;
+			lx += ret;
+		}
+	} else {
+		for (j = 0; j < len; j++) {
+			if (linebuflen < lx + 3)
+				goto overflow2;
+			ch = ptr[j];
+			linebuf[lx++] = hex_asc_hi(ch);
+			linebuf[lx++] = hex_asc_lo(ch);
+			linebuf[lx++] = ' ';
+		}
+		if (j)
+			lx--;
+	}
+	if (!ascii)
+		goto nil;
+
+	while (lx < ascii_column) {
+		if (linebuflen < lx + 2)
+			goto overflow2;
+		linebuf[lx++] = ' ';
+	}
+	for (j = 0; j < len; j++) {
+		if (linebuflen < lx + 2)
+			goto overflow2;
+		ch = ptr[j];
+		linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.';
+	}
+nil:
+	linebuf[lx] = '\0';
+	return lx;
+overflow2:
+	linebuf[lx++] = '\0';
+overflow1:
+	return ascii ? ascii_column + len : (groupsize * 2 + 1) * ngroups - 1;
+}
+
+/**
+ * print_hex_dump - print a text hex dump to syslog for a binary blob of data
+ * @prefix_str: string to prefix each line with;
+ *  caller supplies trailing spaces for alignment if desired
+ * @prefix_type: controls whether prefix of an offset, address, or none
+ *  is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
+ * @rowsize: number of bytes to print per line; must be 16 or 32
+ * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ * @ascii: include ASCII after the hex output
+ *
+ * Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
+ * to the kernel log at the specified kernel log level, with an optional
+ * leading prefix.
+ *
+ * print_hex_dump() works on one "line" of output at a time, i.e.,
+ * 16 or 32 bytes of input data converted to hex + ASCII output.
+ * print_hex_dump() iterates over the entire input @buf, breaking it into
+ * "line size" chunks to format and print.
+ *
+ * E.g.:
+ *   print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS,
+ *		    16, 1, frame->data, frame->len, true);
+ *
+ * Example output using %DUMP_PREFIX_OFFSET and 1-byte mode:
+ * 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f  @ABCDEFGHIJKLMNO
+ * Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode:
+ * ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c  pqrstuvwxyz{|}~.
+ */
+void print_hex_dump(const char *prefix_str, int prefix_type,
+		    int rowsize, int groupsize,
+		    const void *buf, size_t len, int ascii)
+{
+	const u8 *ptr = buf;
+	int i, linelen, remaining = len;
+	char linebuf[32 * 3 + 2 + 32 + 1];
+
+	if (rowsize != 16 && rowsize != 32)
+		rowsize = 16;
+
+	for (i = 0; i < len; i += rowsize) {
+		linelen = min(remaining, rowsize);
+		remaining -= rowsize;
+
+		hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
+				   linebuf, sizeof(linebuf), ascii);
+
+		switch (prefix_type) {
+		case DUMP_PREFIX_ADDRESS:
+			printf("%s%p: %s\n",
+			       prefix_str, ptr + i, linebuf);
+			break;
+		case DUMP_PREFIX_OFFSET:
+			printf("%s%.8x: %s\n", prefix_str, i, linebuf);
+			break;
+		default:
+			printf("%s%s\n", prefix_str, linebuf);
+			break;
+		}
+	}
+}
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 26/38] ubifs: ubifs_dump: dump data in hex format
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (24 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 25/38] ubifs: introduce hexdump lib Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 27/38] gitignore: add ubifs_dump to gitignore Dongsheng Yang
                   ` (11 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

When we dump data node, we can dump the data in it
in hex format.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 Makefile                            |  2 +-
 ubifs-utils/ubifs_dump/ubifs_dump.c | 42 ++++++++++++++++++++-----------------
 2 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/Makefile b/Makefile
index 0be4772..c9dbc58 100644
--- a/Makefile
+++ b/Makefile
@@ -130,7 +130,7 @@ $(foreach v,$(UBI_BINS),$(eval $(call mkdep,ubi-utils/,$(v),libubi.a ubiutils-co
 $(foreach v,crc16.o lpt.o compr.o devtable.o io.o hashtable.o hashtable_itr.o,$(eval UBIFS_LIBS += ../lib/$(v)))
 
 obj-ubifs_dump = $(UBIFS_LIBS)
-obj-ubifs_dump += ../lib/scan.o ../lib/lprops.o
+obj-ubifs_dump += ../lib/scan.o ../lib/lprops.o ../lib/hexdump.o
 LDFLAGS_ubifs_dump = $(ZLIBLDFLAGS) $(LZOLDFLAGS) $(UUIDLDFLAGS)
 LDLIBS_ubifs_dump = -lz -llzo2 -lm -luuid
 $(call mkdep,ubifs-utils/ubifs_dump/,ubifs_dump,,ubi-utils/libubi.a)
diff --git a/ubifs-utils/ubifs_dump/ubifs_dump.c b/ubifs-utils/ubifs_dump/ubifs_dump.c
index e72b8dd..47b0c89 100644
--- a/ubifs-utils/ubifs_dump/ubifs_dump.c
+++ b/ubifs-utils/ubifs_dump/ubifs_dump.c
@@ -7,6 +7,7 @@
 #include "key.h"
 #include "lpt.h"
 #include "scan.h"
+#include "hexdump.h"
 
 #define DBG_KEY_BUF_LEN		48
 
@@ -252,26 +253,26 @@ void dump_node(const struct ubifs_info *c, const void *node)
 		const struct ubifs_ino_node *ino = node;
 
 		key_read(c, &ino->key, &key);
-		printf("\t\tkey \t\t\t%s\n",
+		printf("\t\tkey \t\t\t\t%s\n",
 		       dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
 		printf("\t\tcreat_sqnum \t\t\t%llu\n",
 		       (unsigned long long)le64_to_cpu(ino->creat_sqnum));
-		printf("\t\tsize \t\t\t%llu\n",
+		printf("\t\tsize \t\t\t\t%llu\n",
 		       (unsigned long long)le64_to_cpu(ino->size));
-		printf("\t\tnlink \t\t\t%u\n", le32_to_cpu(ino->nlink));
-		printf("\t\tatime \t\t\t%lld.%u\n",
+		printf("\t\tnlink \t\t\t\t%u\n", le32_to_cpu(ino->nlink));
+		printf("\t\tatime \t\t\t\t%lld.%u\n",
 		       (long long)le64_to_cpu(ino->atime_sec),
 		       le32_to_cpu(ino->atime_nsec));
-		printf("\t\tmtime \t\t\t%lld.%u\n",
+		printf("\t\tmtime \t\t\t\t%lld.%u\n",
 		       (long long)le64_to_cpu(ino->mtime_sec),
 		       le32_to_cpu(ino->mtime_nsec));
-		printf("\t\tctime \t\t\t%lld.%u\n",
+		printf("\t\tctime \t\t\t\t%lld.%u\n",
 		       (long long)le64_to_cpu(ino->ctime_sec),
 		       le32_to_cpu(ino->ctime_nsec));
-		printf("\t\tuid \t\t\t%u\n", le32_to_cpu(ino->uid));
-		printf("\t\tgid \t\t\t%u\n", le32_to_cpu(ino->gid));
-		printf("\t\tmode \t\t\t%u\n", le32_to_cpu(ino->mode));
-		printf("\t\tflags \t\t\t%#x\n", le32_to_cpu(ino->flags));
+		printf("\t\tuid \t\t\t\t%u\n", le32_to_cpu(ino->uid));
+		printf("\t\tgid \t\t\t\t%u\n", le32_to_cpu(ino->gid));
+		printf("\t\tmode \t\t\t\t%u\n", le32_to_cpu(ino->mode));
+		printf("\t\tflags \t\t\t\t%#x\n", le32_to_cpu(ino->flags));
 		printf("\t\txattr_cnt \t\t\t%u\n", le32_to_cpu(ino->xattr_cnt));
 		printf("\t\txattr_size \t\t\t%u\n", le32_to_cpu(ino->xattr_size));
 		printf("\t\txattr_names \t\t\t%u\n", le32_to_cpu(ino->xattr_names));
@@ -287,13 +288,13 @@ void dump_node(const struct ubifs_info *c, const void *node)
 		int nlen = le16_to_cpu(dent->nlen);
 
 		key_read(c, &dent->key, &key);
-		printf("\t\tkey \t\t\t%s\n",
+		printf("\t\tkey \t\t\t\t%s\n",
 		       dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
-		printf("\t\tinum \t\t\t%llu\n",
+		printf("\t\tinum \t\t\t\t%llu\n",
 		       (unsigned long long)le64_to_cpu(dent->inum));
-		printf("\t\ttype \t\t\t%d\n", (int)dent->type);
-		printf("\t\tnlen \t\t\t%d\n", nlen);
-		printf("\t\tname           ");
+		printf("\t\ttype \t\t\t\t%d\n", (int)dent->type);
+		printf("\t\tnlen \t\t\t\t%d\n", nlen);
+		printf("\t\tname \t\t\t\t");
 
 		if (nlen > UBIFS_MAX_NLEN)
 			printf("(bad name length, not printing, bad or corrupted node)");
@@ -311,12 +312,15 @@ void dump_node(const struct ubifs_info *c, const void *node)
 		int dlen = le32_to_cpu(ch->len) - UBIFS_DATA_NODE_SZ;
 
 		key_read(c, &dn->key, &key);
-		printf("\t\tkey \t\t\t%s\n",
+		printf("\t\tkey \t\t\t\t%s\n",
 		       dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
-		printf("\t\tsize \t\t\t%u\n", le32_to_cpu(dn->size));
+		printf("\t\tsize \t\t\t\t%u\n", le32_to_cpu(dn->size));
 		printf("\t\tcompr_typ \t\t\t%d\n",
 		       (int)le16_to_cpu(dn->compr_type));
 		printf("\t\tdata size \t\t\t%d\n", dlen);
+		printf("\t\tdata:\n");
+		print_hex_dump("\t\t", DUMP_PREFIX_OFFSET, 32, 1,
+			       (void *)&dn->data, dlen, 0);
 		break;
 	}
 	case UBIFS_TRUN_NODE:
@@ -335,8 +339,8 @@ void dump_node(const struct ubifs_info *c, const void *node)
 		const struct ubifs_idx_node *idx = node;
 
 		n = le16_to_cpu(idx->child_cnt);
-		printf("\t\tchild_cnt \t\t%d\n", n);
-		printf("\t\tlevel \t\t\t%d\n", (int)le16_to_cpu(idx->level));
+		printf("\t\tchild_cnt \t\t\t%d\n", n);
+		printf("\t\tlevel \t\t\t\t%d\n", (int)le16_to_cpu(idx->level));
 		printf("\t\tBranches:\n");
 
 		for (i = 0; i < n && i < c->fanout - 1; i++) {
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 27/38] gitignore: add ubifs_dump to gitignore.
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (25 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 26/38] ubifs: ubifs_dump: dump data in hex format Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 28/38] ubifs: add complete version of list.h Dongsheng Yang
                   ` (10 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index 2aac52c..6bcac39 100644
--- a/.gitignore
+++ b/.gitignore
@@ -45,6 +45,7 @@
 /nor-utils/rfdformat
 /misc-utils/serve_image
 /jffsX-utils/sumtool
+/ubifs-utils/ubifs_dump/ubifs_dump
 
 #
 # Top-level generic files
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 28/38] ubifs: add complete version of list.h
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (26 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 27/38] gitignore: add ubifs_dump to gitignore Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 29/38] ubifs: fix typo in ubifs_read Dongsheng Yang
                   ` (9 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd

From: Richard Weinberger <richard@nod.at>

See http://lists.infradead.org/pipermail/linux-mtd/2015-October/062421.html

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 ubifs-utils/include/list.h | 305 +++++++++++++++++++++++++++++++--------------
 1 file changed, 213 insertions(+), 92 deletions(-)

diff --git a/ubifs-utils/include/list.h b/ubifs-utils/include/list.h
index 0cffa33..080ea39 100644
--- a/ubifs-utils/include/list.h
+++ b/ubifs-utils/include/list.h
@@ -17,6 +17,10 @@
 #ifndef _LINUX_LIST_H
 #define _LINUX_LIST_H
 
+struct list_head {
+	struct list_head *next, *prev;
+};
+
 #define LIST_POISON1  ((struct list_head *) 0x00100100)
 #define LIST_POISON2  ((struct list_head *) 0x00200200)
 
@@ -30,10 +34,6 @@
  * using the generic single-entry routines.
  */
 
-struct list_head {
-	struct list_head *next, *prev;
-};
-
 #define LIST_HEAD_INIT(name) { &(name), &(name) }
 
 #define LIST_HEAD(name) \
@@ -52,17 +52,17 @@ static inline void INIT_LIST_HEAD(struct list_head *list)
  * the prev/next entries already!
  */
 #ifndef CONFIG_DEBUG_LIST
-static inline void __list_add(struct list_head *xnew,
+static inline void __list_add(struct list_head *new,
 			      struct list_head *prev,
 			      struct list_head *next)
 {
-	next->prev = xnew;
-	xnew->next = next;
-	xnew->prev = prev;
-	prev->next = xnew;
+	next->prev = new;
+	new->next = next;
+	new->prev = prev;
+	prev->next = new;
 }
 #else
-extern void __list_add(struct list_head *xnew,
+extern void __list_add(struct list_head *new,
 			      struct list_head *prev,
 			      struct list_head *next);
 #endif
@@ -75,14 +75,10 @@ extern void __list_add(struct list_head *xnew,
  * Insert a new entry after the specified head.
  * This is good for implementing stacks.
  */
-#ifndef CONFIG_DEBUG_LIST
-static inline void list_add(struct list_head *xnew, struct list_head *head)
+static inline void list_add(struct list_head *new, struct list_head *head)
 {
-	__list_add(xnew, head, head->next);
+	__list_add(new, head, head->next);
 }
-#else
-extern void list_add(struct list_head *xnew, struct list_head *head);
-#endif
 
 
 /**
@@ -93,9 +89,9 @@ extern void list_add(struct list_head *xnew, struct list_head *head);
  * Insert a new entry before the specified head.
  * This is useful for implementing queues.
  */
-static inline void list_add_tail(struct list_head *xnew, struct list_head *head)
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
 {
-	__list_add(xnew, head->prev, head);
+	__list_add(new, head->prev, head);
 }
 
 /*
@@ -114,10 +110,15 @@ static inline void __list_del(struct list_head * prev, struct list_head * next)
 /**
  * list_del - deletes entry from list.
  * @entry: the element to delete from the list.
- * Note: list_empty on entry does not return true after this, the entry is
+ * Note: list_empty() on entry does not return true after this, the entry is
  * in an undefined state.
  */
 #ifndef CONFIG_DEBUG_LIST
+static inline void __list_del_entry(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+}
+
 static inline void list_del(struct list_head *entry)
 {
 	__list_del(entry->prev, entry->next);
@@ -125,6 +126,7 @@ static inline void list_del(struct list_head *entry)
 	entry->prev = LIST_POISON2;
 }
 #else
+extern void __list_del_entry(struct list_head *entry);
 extern void list_del(struct list_head *entry);
 #endif
 
@@ -132,30 +134,32 @@ extern void list_del(struct list_head *entry);
  * list_replace - replace old entry by new one
  * @old : the element to be replaced
  * @new : the new element to insert
- * Note: if 'old' was empty, it will be overwritten.
+ *
+ * If @old was empty, it will be overwritten.
  */
 static inline void list_replace(struct list_head *old,
-				struct list_head *xnew)
+				struct list_head *new)
 {
-	xnew->next = old->next;
-	xnew->next->prev = xnew;
-	xnew->prev = old->prev;
-	xnew->prev->next = xnew;
+	new->next = old->next;
+	new->next->prev = new;
+	new->prev = old->prev;
+	new->prev->next = new;
 }
 
 static inline void list_replace_init(struct list_head *old,
-					struct list_head *xnew)
+					struct list_head *new)
 {
-	list_replace(old, xnew);
+	list_replace(old, new);
 	INIT_LIST_HEAD(old);
 }
+
 /**
  * list_del_init - deletes entry from list and reinitialize it.
  * @entry: the element to delete from the list.
  */
 static inline void list_del_init(struct list_head *entry)
 {
-	__list_del(entry->prev, entry->next);
+	__list_del_entry(entry);
 	INIT_LIST_HEAD(entry);
 }
 
@@ -166,8 +170,8 @@ static inline void list_del_init(struct list_head *entry)
  */
 static inline void list_move(struct list_head *list, struct list_head *head)
 {
-        __list_del(list->prev, list->next);
-        list_add(list, head);
+	__list_del_entry(list);
+	list_add(list, head);
 }
 
 /**
@@ -178,8 +182,8 @@ static inline void list_move(struct list_head *list, struct list_head *head)
 static inline void list_move_tail(struct list_head *list,
 				  struct list_head *head)
 {
-        __list_del(list->prev, list->next);
-        list_add_tail(list, head);
+	__list_del_entry(list);
+	list_add_tail(list, head);
 }
 
 /**
@@ -221,6 +225,69 @@ static inline int list_empty_careful(const struct list_head *head)
 	return (next == head) && (next == head->prev);
 }
 
+/**
+ * list_rotate_left - rotate the list to the left
+ * @head: the head of the list
+ */
+static inline void list_rotate_left(struct list_head *head)
+{
+	struct list_head *first;
+
+	if (!list_empty(head)) {
+		first = head->next;
+		list_move_tail(first, head);
+	}
+}
+
+/**
+ * list_is_singular - tests whether a list has just one entry.
+ * @head: the list to test.
+ */
+static inline int list_is_singular(const struct list_head *head)
+{
+	return !list_empty(head) && (head->next == head->prev);
+}
+
+static inline void __list_cut_position(struct list_head *list,
+		struct list_head *head, struct list_head *entry)
+{
+	struct list_head *new_first = entry->next;
+	list->next = head->next;
+	list->next->prev = list;
+	list->prev = entry;
+	entry->next = list;
+	head->next = new_first;
+	new_first->prev = head;
+}
+
+/**
+ * list_cut_position - cut a list into two
+ * @list: a new list to add all removed entries
+ * @head: a list with entries
+ * @entry: an entry within head, could be the head itself
+ *	and if so we won't cut the list
+ *
+ * This helper moves the initial part of @head, up to and
+ * including @entry, from @head to @list. You should
+ * pass on @entry an element you know is on @head. @list
+ * should be an empty list or a list you do not care about
+ * losing its data.
+ *
+ */
+static inline void list_cut_position(struct list_head *list,
+		struct list_head *head, struct list_head *entry)
+{
+	if (list_empty(head))
+		return;
+	if (list_is_singular(head) &&
+		(head->next != entry && head != entry))
+		return;
+	if (entry == head)
+		INIT_LIST_HEAD(list);
+	else
+		__list_cut_position(list, head, entry);
+}
+
 static inline void __list_splice(const struct list_head *list,
 				 struct list_head *prev,
 				 struct list_head *next)
@@ -236,11 +303,12 @@ static inline void __list_splice(const struct list_head *list,
 }
 
 /**
- * list_splice - join two lists
+ * list_splice - join two lists, this is designed for stacks
  * @list: the new list to add.
  * @head: the place to add it in the first list.
  */
-static inline void list_splice(struct list_head *list, struct list_head *head)
+static inline void list_splice(const struct list_head *list,
+				struct list_head *head)
 {
 	if (!list_empty(list))
 		__list_splice(list, head, head->next);
@@ -295,7 +363,7 @@ static inline void list_splice_tail_init(struct list_head *list,
  * list_entry - get the struct for this entry
  * @ptr:	the &struct list_head pointer.
  * @type:	the type of the struct this is embedded in.
- * @member:	the name of the list_struct within the struct.
+ * @member:	the name of the list_head within the struct.
  */
 #define list_entry(ptr, type, member) \
 	container_of(ptr, type, member)
@@ -304,7 +372,7 @@ static inline void list_splice_tail_init(struct list_head *list,
  * list_first_entry - get the first element from a list
  * @ptr:	the list head to take the element from.
  * @type:	the type of the struct this is embedded in.
- * @member:	the name of the list_struct within the struct.
+ * @member:	the name of the list_head within the struct.
  *
  * Note, that list is expected to be not empty.
  */
@@ -312,35 +380,49 @@ static inline void list_splice_tail_init(struct list_head *list,
 	list_entry((ptr)->next, type, member)
 
 /**
- * list_next_entry - get the next element from a list
+ * list_last_entry - get the last element from a list
  * @ptr:	the list head to take the element from.
- * @member:	the name of the list_struct within the struct.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the list_head within the struct.
  *
- * Note, that next is expected to be not null.
+ * Note, that list is expected to be not empty.
  */
-#define list_next_entry(ptr, member) \
-	list_entry((ptr)->member.next, typeof(*ptr), member)
+#define list_last_entry(ptr, type, member) \
+	list_entry((ptr)->prev, type, member)
 
 /**
- * list_for_each	-	iterate over a list
- * @pos:	the &struct list_head to use as a loop cursor.
- * @head:	the head for your list.
+ * list_first_entry_or_null - get the first element from a list
+ * @ptr:	the list head to take the element from.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the list_head within the struct.
+ *
+ * Note that if the list is empty, it returns NULL.
  */
-#define list_for_each(pos, head) \
-	for (pos = (head)->next; pos != (head); \
-        	pos = pos->next)
+#define list_first_entry_or_null(ptr, type, member) \
+	(!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
+
+/**
+ * list_next_entry - get the next element in list
+ * @pos:	the type * to cursor
+ * @member:	the name of the list_head within the struct.
+ */
+#define list_next_entry(pos, member) \
+	list_entry((pos)->member.next, typeof(*(pos)), member)
 
 /**
- * __list_for_each	-	iterate over a list
+ * list_prev_entry - get the prev element in list
+ * @pos:	the type * to cursor
+ * @member:	the name of the list_head within the struct.
+ */
+#define list_prev_entry(pos, member) \
+	list_entry((pos)->member.prev, typeof(*(pos)), member)
+
+/**
+ * list_for_each	-	iterate over a list
  * @pos:	the &struct list_head to use as a loop cursor.
  * @head:	the head for your list.
- *
- * This variant differs from list_for_each() in that it's the
- * simplest possible list iteration code, no prefetching is done.
- * Use this for code that knows the list to be very short (empty
- * or 1 entry) most of the time.
  */
-#define __list_for_each(pos, head) \
+#define list_for_each(pos, head) \
 	for (pos = (head)->next; pos != (head); pos = pos->next)
 
 /**
@@ -349,8 +431,7 @@ static inline void list_splice_tail_init(struct list_head *list,
  * @head:	the head for your list.
  */
 #define list_for_each_prev(pos, head) \
-	for (pos = (head)->prev; pos != (head); \
-        	pos = pos->prev)
+	for (pos = (head)->prev; pos != (head); pos = pos->prev)
 
 /**
  * list_for_each_safe - iterate over a list safe against removal of list entry
@@ -363,34 +444,45 @@ static inline void list_splice_tail_init(struct list_head *list,
 		pos = n, n = pos->next)
 
 /**
+ * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
+ * @pos:	the &struct list_head to use as a loop cursor.
+ * @n:		another &struct list_head to use as temporary storage
+ * @head:	the head for your list.
+ */
+#define list_for_each_prev_safe(pos, n, head) \
+	for (pos = (head)->prev, n = pos->prev; \
+	     pos != (head); \
+	     pos = n, n = pos->prev)
+
+/**
  * list_for_each_entry	-	iterate over list of given type
  * @pos:	the type * to use as a loop cursor.
  * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
+ * @member:	the name of the list_head within the struct.
  */
 #define list_for_each_entry(pos, head, member)				\
-	for (pos = list_entry((head)->next, typeof(*pos), member);	\
-	     &pos->member != (head); 	\
-	     pos = list_entry(pos->member.next, typeof(*pos), member))
+	for (pos = list_first_entry(head, typeof(*pos), member);	\
+	     &pos->member != (head);					\
+	     pos = list_next_entry(pos, member))
 
 /**
  * list_for_each_entry_reverse - iterate backwards over list of given type.
  * @pos:	the type * to use as a loop cursor.
  * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
+ * @member:	the name of the list_head within the struct.
  */
 #define list_for_each_entry_reverse(pos, head, member)			\
-	for (pos = list_entry((head)->prev, typeof(*pos), member);	\
-	     &pos->member != (head); 	\
-	     pos = list_entry(pos->member.prev, typeof(*pos), member))
+	for (pos = list_last_entry(head, typeof(*pos), member);		\
+	     &pos->member != (head); 					\
+	     pos = list_prev_entry(pos, member))
 
 /**
- * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue
+ * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
  * @pos:	the type * to use as a start point
  * @head:	the head of the list
- * @member:	the name of the list_struct within the struct.
+ * @member:	the name of the list_head within the struct.
  *
- * Prepares a pos entry for use as a start point in list_for_each_entry_continue.
+ * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
  */
 #define list_prepare_entry(pos, head, member) \
 	((pos) ? : list_entry(head, typeof(*pos), member))
@@ -399,86 +491,115 @@ static inline void list_splice_tail_init(struct list_head *list,
  * list_for_each_entry_continue - continue iteration over list of given type
  * @pos:	the type * to use as a loop cursor.
  * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
+ * @member:	the name of the list_head within the struct.
  *
  * Continue to iterate over list of given type, continuing after
  * the current position.
  */
 #define list_for_each_entry_continue(pos, head, member) 		\
-	for (pos = list_entry(pos->member.next, typeof(*pos), member);	\
-	     &pos->member != (head);	\
-	     pos = list_entry(pos->member.next, typeof(*pos), member))
+	for (pos = list_next_entry(pos, member);			\
+	     &pos->member != (head);					\
+	     pos = list_next_entry(pos, member))
+
+/**
+ * list_for_each_entry_continue_reverse - iterate backwards from the given point
+ * @pos:	the type * to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the list_head within the struct.
+ *
+ * Start to iterate over list of given type backwards, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue_reverse(pos, head, member)		\
+	for (pos = list_prev_entry(pos, member);			\
+	     &pos->member != (head);					\
+	     pos = list_prev_entry(pos, member))
 
 /**
  * list_for_each_entry_from - iterate over list of given type from the current point
  * @pos:	the type * to use as a loop cursor.
  * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
+ * @member:	the name of the list_head within the struct.
  *
  * Iterate over list of given type, continuing from current position.
  */
 #define list_for_each_entry_from(pos, head, member) 			\
-	for (; &pos->member != (head);	\
-	     pos = list_entry(pos->member.next, typeof(*pos), member))
+	for (; &pos->member != (head);					\
+	     pos = list_next_entry(pos, member))
 
 /**
  * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
  * @pos:	the type * to use as a loop cursor.
  * @n:		another type * to use as temporary storage
  * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
+ * @member:	the name of the list_head within the struct.
  */
 #define list_for_each_entry_safe(pos, n, head, member)			\
-	for (pos = list_entry((head)->next, typeof(*pos), member),	\
-		n = list_entry(pos->member.next, typeof(*pos), member);	\
+	for (pos = list_first_entry(head, typeof(*pos), member),	\
+		n = list_next_entry(pos, member);			\
 	     &pos->member != (head); 					\
-	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
+	     pos = n, n = list_next_entry(n, member))
 
 /**
- * list_for_each_entry_safe_continue
+ * list_for_each_entry_safe_continue - continue list iteration safe against removal
  * @pos:	the type * to use as a loop cursor.
  * @n:		another type * to use as temporary storage
  * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
+ * @member:	the name of the list_head within the struct.
  *
  * Iterate over list of given type, continuing after current point,
  * safe against removal of list entry.
  */
 #define list_for_each_entry_safe_continue(pos, n, head, member) 		\
-	for (pos = list_entry(pos->member.next, typeof(*pos), member), 		\
-		n = list_entry(pos->member.next, typeof(*pos), member);		\
+	for (pos = list_next_entry(pos, member), 				\
+		n = list_next_entry(pos, member);				\
 	     &pos->member != (head);						\
-	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
+	     pos = n, n = list_next_entry(n, member))
 
 /**
- * list_for_each_entry_safe_from
+ * list_for_each_entry_safe_from - iterate over list from current point safe against removal
  * @pos:	the type * to use as a loop cursor.
  * @n:		another type * to use as temporary storage
  * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
+ * @member:	the name of the list_head within the struct.
  *
  * Iterate over list of given type from current point, safe against
  * removal of list entry.
  */
 #define list_for_each_entry_safe_from(pos, n, head, member) 			\
-	for (n = list_entry(pos->member.next, typeof(*pos), member);		\
+	for (n = list_next_entry(pos, member);					\
 	     &pos->member != (head);						\
-	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
+	     pos = n, n = list_next_entry(n, member))
 
 /**
- * list_for_each_entry_safe_reverse
+ * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
  * @pos:	the type * to use as a loop cursor.
  * @n:		another type * to use as temporary storage
  * @head:	the head for your list.
- * @member:	the name of the list_struct within the struct.
+ * @member:	the name of the list_head within the struct.
  *
  * Iterate backwards over list of given type, safe against removal
  * of list entry.
  */
 #define list_for_each_entry_safe_reverse(pos, n, head, member)		\
-	for (pos = list_entry((head)->prev, typeof(*pos), member),	\
-		n = list_entry(pos->member.prev, typeof(*pos), member);	\
+	for (pos = list_last_entry(head, typeof(*pos), member),		\
+		n = list_prev_entry(pos, member);			\
 	     &pos->member != (head); 					\
-	     pos = n, n = list_entry(n->member.prev, typeof(*n), member))
+	     pos = n, n = list_prev_entry(n, member))
+
+/**
+ * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
+ * @pos:	the loop cursor used in the list_for_each_entry_safe loop
+ * @n:		temporary storage used in list_for_each_entry_safe
+ * @member:	the name of the list_head within the struct.
+ *
+ * list_safe_reset_next is not safe to use in general if the list may be
+ * modified concurrently (eg. the lock is dropped in the loop body). An
+ * exception to this is if the cursor element (pos) is pinned in the list,
+ * and list_safe_reset_next is called after re-taking the lock and before
+ * completing the current iteration of the loop body.
+ */
+#define list_safe_reset_next(pos, n, member)				\
+	n = list_next_entry(pos, member)
 
 #endif
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 29/38] ubifs: fix typo in ubifs_read
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (27 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 28/38] ubifs: add complete version of list.h Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 30/38] Make cli byte parsing from ubi-utils available for all tools Dongsheng Yang
                   ` (8 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd

From: David Gstir <david@sigma-star.at>

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 ubifs-utils/lib/io.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ubifs-utils/lib/io.c b/ubifs-utils/lib/io.c
index d05cf86..c2e0d63 100644
--- a/ubifs-utils/lib/io.c
+++ b/ubifs-utils/lib/io.c
@@ -145,7 +145,7 @@ int ubifs_read(loff_t offset, int len, void *buf)
 		return sys_err_msg("lseek failed seeking %"PRIdoff_t, offset);
 
 	if (read(out_fd, buf, len) != len)
-		return sys_err_msg("write failed writing %d bytes at pos %"PRIdoff_t,
+		return sys_err_msg("read failed reading %d bytes at pos %"PRIdoff_t,
 				   len, offset);
 
 	return 0;
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 30/38] Make cli byte parsing from ubi-utils available for all tools
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (28 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 29/38] ubifs: fix typo in ubifs_read Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 31/38] ubifs: add decompression functions Dongsheng Yang
                   ` (7 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd

From: David Gstir <david@sigma-star.at>

ubiutils_get_bytes(str) parses strings like "12MiB" and returns the value in
bytes. We want this function to be available to all tools not just ubi specific
ones. The function is now simply named parse_bytes

ubiutils_print_bytes() performs the reverse and is now named print_bytes.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 include/common.h                    | 90 +++++++++++++++++++++++++++++++++++
 ubi-utils/include/ubiutils-common.h |  2 -
 ubi-utils/mtdinfo.c                 |  6 +--
 ubi-utils/ubiattach.c               |  6 +--
 ubi-utils/ubiformat.c               |  8 ++--
 ubi-utils/ubimkvol.c                |  6 +--
 ubi-utils/ubinfo.c                  | 10 ++--
 ubi-utils/ubinize.c                 | 10 ++--
 ubi-utils/ubirsvol.c                |  2 +-
 ubi-utils/ubiutils-common.c         | 93 -------------------------------------
 ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 66 ++------------------------
 11 files changed, 119 insertions(+), 180 deletions(-)

diff --git a/include/common.h b/include/common.h
index fb0ca83..460d2aa 100644
--- a/include/common.h
+++ b/include/common.h
@@ -213,6 +213,96 @@ do { \
 	printf("%s %s\n", PROGRAM_NAME, VERSION); \
 } while (0)
 
+/**
+ * get_multiplier - convert size specifier to an integer multiplier.
+ * @str: the size specifier string
+ *
+ * This function parses the @str size specifier, which may be one of
+ * 'KiB', 'MiB', or 'GiB' into an integer multiplier. Returns positive
+ * size multiplier in case of success and %-1 in case of failure.
+ */
+static inline int get_multiplier(const char *str)
+{
+	if (!str)
+		return 1;
+
+	/* Remove spaces before the specifier */
+	while (*str == ' ' || *str == '\t')
+		str += 1;
+
+	if (!strcmp(str, "KiB"))
+		return 1024;
+	if (!strcmp(str, "MiB"))
+		return 1024 * 1024;
+	if (!strcmp(str, "GiB"))
+		return 1024 * 1024 * 1024;
+
+	return -1;
+}
+
+/**
+ * parse_bytes - convert a string containing amount of bytes into an
+ * integer
+ * @str: string to convert
+ *
+ * This function parses @str which may have one of 'KiB', 'MiB', or 'GiB'
+ * size specifiers. Returns positive amount of bytes in case of success and %-1
+ * in case of failure.
+ */
+static inline long long parse_bytes(const char *str)
+{
+	char *endp;
+	long long bytes = strtoull(str, &endp, 0);
+
+	if (endp == str || bytes < 0)
+		return errmsg("incorrect amount of bytes: \"%s\"\n", str);
+
+	if (*endp != '\0') {
+		int mult = get_multiplier(endp);
+
+		if (mult == -1)
+			return errmsg("bad size specifier: \"%s\" - "
+			        "should be 'KiB', 'MiB' or 'GiB'\n", endp);
+		bytes *= mult;
+	}
+
+	return bytes;
+}
+
+/**
+ * print_bytes - print bytes.
+ * @bytes: variable to print
+ * @bracket: whether brackets have to be put or not
+ *
+ * This is a helper function which prints amount of bytes in a human-readable
+ * form, i.e., it prints the exact amount of bytes following by the approximate
+ * amount of Kilobytes, Megabytes, or Gigabytes, depending on how big @bytes
+ * is.
+ */
+static inline void print_bytes(long long bytes, int bracket)
+{
+	const char *p;
+
+	if (bracket)
+		p = " (";
+	else
+		p = ", ";
+
+	printf("%lld bytes", bytes);
+
+	if (bytes > 1024 * 1024 * 1024)
+		printf("%s%.1f GiB", p, (double)bytes / (1024 * 1024 * 1024));
+	else if (bytes > 1024 * 1024)
+		printf("%s%.1f MiB", p, (double)bytes / (1024 * 1024));
+	else if (bytes > 1024 && bytes != 0)
+		printf("%s%.1f KiB", p, (double)bytes / 1024);
+	else
+		return;
+
+	if (bracket)
+		printf(")");
+}
+
 #include "xalloc.h"
 
 #ifdef __cplusplus
diff --git a/ubi-utils/include/ubiutils-common.h b/ubi-utils/include/ubiutils-common.h
index 9762837..a86ca2f 100644
--- a/ubi-utils/include/ubiutils-common.h
+++ b/ubi-utils/include/ubiutils-common.h
@@ -23,8 +23,6 @@
 extern "C" {
 #endif
 
-long long ubiutils_get_bytes(const char *str);
-void ubiutils_print_bytes(long long bytes, int bracket);
 void ubiutils_print_text(FILE *stream, const char *txt, int len);
 int ubiutils_srand(void);
 
diff --git a/ubi-utils/mtdinfo.c b/ubi-utils/mtdinfo.c
index a86abd1..e360fcd 100644
--- a/ubi-utils/mtdinfo.c
+++ b/ubi-utils/mtdinfo.c
@@ -172,7 +172,7 @@ static void print_ubi_info(const struct mtd_info *mtd_info,
 	printf("Default UBI VID header offset:  %d\n", ui.vid_hdr_offs);
 	printf("Default UBI data offset:        %d\n", ui.data_offs);
 	printf("Default UBI LEB size:           ");
-	ubiutils_print_bytes(ui.leb_size, 0);
+	print_bytes(ui.leb_size, 0);
 	printf("\n");
 	printf("Maximum UBI volumes count:      %d\n", ui.max_volumes);
 }
@@ -306,10 +306,10 @@ static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int
 	printf("Name:                           %s\n", mtd.name);
 	printf("Type:                           %s\n", mtd.type_str);
 	printf("Eraseblock size:                ");
-	ubiutils_print_bytes(mtd.eb_size, 0);
+	print_bytes(mtd.eb_size, 0);
 	printf("\n");
 	printf("Amount of eraseblocks:          %d (", mtd.eb_cnt);
-	ubiutils_print_bytes(mtd.size, 0);
+	print_bytes(mtd.size, 0);
 	printf(")\n");
 	printf("Minimum input/output unit size: %d %s\n",
 	       mtd.min_io_size, mtd.min_io_size > 1 ? "bytes" : "byte");
diff --git a/ubi-utils/ubiattach.c b/ubi-utils/ubiattach.c
index a7c62d0..a4844fa 100644
--- a/ubi-utils/ubiattach.c
+++ b/ubi-utils/ubiattach.c
@@ -238,11 +238,11 @@ int main(int argc, char * const argv[])
 	}
 
 	printf("UBI device number %d, total %d LEBs (", dev_info.dev_num, dev_info.total_lebs);
-	ubiutils_print_bytes(dev_info.total_bytes, 0);
+	print_bytes(dev_info.total_bytes, 0);
 	printf("), available %d LEBs (", dev_info.avail_lebs);
-	ubiutils_print_bytes(dev_info.avail_bytes, 0);
+	print_bytes(dev_info.avail_bytes, 0);
 	printf("), LEB size ");
-	ubiutils_print_bytes(dev_info.leb_size, 1);
+	print_bytes(dev_info.leb_size, 1);
 	printf("\n");
 
 	libubi_close(libubi);
diff --git a/ubi-utils/ubiformat.c b/ubi-utils/ubiformat.c
index 21409ca..4064da0 100644
--- a/ubi-utils/ubiformat.c
+++ b/ubi-utils/ubiformat.c
@@ -143,7 +143,7 @@ static int parse_opt(int argc, char * const argv[])
 
 		switch (key) {
 		case 's':
-			args.subpage_size = ubiutils_get_bytes(optarg);
+			args.subpage_size = parse_bytes(optarg);
 			if (args.subpage_size <= 0)
 				return errmsg("bad sub-page size: \"%s\"", optarg);
 			if (!is_power_of_2(args.subpage_size))
@@ -170,7 +170,7 @@ static int parse_opt(int argc, char * const argv[])
 			break;
 
 		case 'S':
-			args.image_sz = ubiutils_get_bytes(optarg);
+			args.image_sz = parse_bytes(optarg);
 			if (args.image_sz <= 0)
 				return errmsg("bad image-size: \"%s\"", optarg);
 			break;
@@ -791,9 +791,9 @@ int main(int argc, char * const argv[])
 
 	if (!args.quiet) {
 		normsg_cont("mtd%d (%s), size ", mtd.mtd_num, mtd.type_str);
-		ubiutils_print_bytes(mtd.size, 1);
+		print_bytes(mtd.size, 1);
 		printf(", %d eraseblocks of ", mtd.eb_cnt);
-		ubiutils_print_bytes(mtd.eb_size, 1);
+		print_bytes(mtd.eb_size, 1);
 		printf(", min. I/O size %d bytes\n", mtd.min_io_size);
 	}
 
diff --git a/ubi-utils/ubimkvol.c b/ubi-utils/ubimkvol.c
index 7c2a234..84cb65a 100644
--- a/ubi-utils/ubimkvol.c
+++ b/ubi-utils/ubimkvol.c
@@ -137,7 +137,7 @@ static int parse_opt(int argc, char * const argv[])
 			break;
 
 		case 's':
-			args.bytes = ubiutils_get_bytes(optarg);
+			args.bytes = parse_bytes(optarg);
 			if (args.bytes <= 0)
 				return errmsg("bad volume size: \"%s\"", optarg);
 			break;
@@ -278,9 +278,9 @@ int main(int argc, char * const argv[])
 	}
 
 	printf("Volume ID %d, size %d LEBs (", vol_info.vol_id, vol_info.rsvd_lebs);
-	ubiutils_print_bytes(vol_info.rsvd_bytes, 0);
+	print_bytes(vol_info.rsvd_bytes, 0);
 	printf("), LEB size ");
-	ubiutils_print_bytes(vol_info.leb_size, 1);
+	print_bytes(vol_info.leb_size, 1);
 	printf(", %s, name \"%s\", alignment %d\n",
 	       req.vol_type == UBI_DYNAMIC_VOLUME ? "dynamic" : "static",
 	       vol_info.name, vol_info.alignment);
diff --git a/ubi-utils/ubinfo.c b/ubi-utils/ubinfo.c
index cb88f53..bd97198 100644
--- a/ubi-utils/ubinfo.c
+++ b/ubi-utils/ubinfo.c
@@ -211,12 +211,12 @@ static int print_vol_info(libubi_t libubi, int dev_num, int vol_id)
 	printf("Alignment:   %d\n", vol_info.alignment);
 
 	printf("Size:        %d LEBs (", vol_info.rsvd_lebs);
-	ubiutils_print_bytes(vol_info.rsvd_bytes, 0);
+	print_bytes(vol_info.rsvd_bytes, 0);
 	printf(")\n");
 
 	if (vol_info.type == UBI_STATIC_VOLUME) {
 		printf("Data bytes:  ");
-		ubiutils_print_bytes(vol_info.data_bytes, 1);
+		print_bytes(vol_info.data_bytes, 1);
 		printf("\n");
 	}
 	printf("State:       %s\n", vol_info.corrupted ? "corrupted" : "OK");
@@ -240,15 +240,15 @@ static int print_dev_info(libubi_t libubi, int dev_num, int all)
 	printf("ubi%d\n", dev_info.dev_num);
 	printf("Volumes count:                           %d\n", dev_info.vol_count);
 	printf("Logical eraseblock size:                 ");
-	ubiutils_print_bytes(dev_info.leb_size, 0);
+	print_bytes(dev_info.leb_size, 0);
 	printf("\n");
 
 	printf("Total amount of logical eraseblocks:     %d (", dev_info.total_lebs);
-	ubiutils_print_bytes(dev_info.total_bytes, 0);
+	print_bytes(dev_info.total_bytes, 0);
 	printf(")\n");
 
 	printf("Amount of available logical eraseblocks: %d (", dev_info.avail_lebs);
-	ubiutils_print_bytes(dev_info.avail_bytes, 0);
+	print_bytes(dev_info.avail_bytes, 0);
 	printf(")\n");
 
 	printf("Maximum count of volumes                 %d\n", dev_info.max_vol_count);
diff --git a/ubi-utils/ubinize.c b/ubi-utils/ubinize.c
index 60bbd9a..d306f26 100644
--- a/ubi-utils/ubinize.c
+++ b/ubi-utils/ubinize.c
@@ -176,13 +176,13 @@ static int parse_opt(int argc, char * const argv[])
 			break;
 
 		case 'p':
-			args.peb_size = ubiutils_get_bytes(optarg);
+			args.peb_size = parse_bytes(optarg);
 			if (args.peb_size <= 0)
 				return errmsg("bad physical eraseblock size: \"%s\"", optarg);
 			break;
 
 		case 'm':
-			args.min_io_size = ubiutils_get_bytes(optarg);
+			args.min_io_size = parse_bytes(optarg);
 			if (args.min_io_size <= 0)
 				return errmsg("bad min. I/O unit size: \"%s\"", optarg);
 			if (!is_power_of_2(args.min_io_size))
@@ -190,7 +190,7 @@ static int parse_opt(int argc, char * const argv[])
 			break;
 
 		case 's':
-			args.subpage_size = ubiutils_get_bytes(optarg);
+			args.subpage_size = parse_bytes(optarg);
 			if (args.subpage_size <= 0)
 				return errmsg("bad sub-page size: \"%s\"", optarg);
 			if (!is_power_of_2(args.subpage_size))
@@ -368,7 +368,7 @@ static int read_section(const struct ubigen_info *ui, const char *sname,
 	sprintf(buf, "%s:vol_size", sname);
 	p = iniparser_getstring(args.dict, buf, NULL);
 	if (p) {
-		vi->bytes = ubiutils_get_bytes(p);
+		vi->bytes = parse_bytes(p);
 		if (vi->bytes <= 0)
 			return errmsg("bad \"vol_size\" key value \"%s\" (section \"%s\")",
 				      p, sname);
@@ -397,7 +397,7 @@ static int read_section(const struct ubigen_info *ui, const char *sname,
 
 		normsg_cont("volume size was not specified in section \"%s\", assume"
 			    " minimum to fit image \"%s\"", sname, *img);
-		ubiutils_print_bytes(vi->bytes, 1);
+		print_bytes(vi->bytes, 1);
 		printf("\n");
 	}
 
diff --git a/ubi-utils/ubirsvol.c b/ubi-utils/ubirsvol.c
index c469060..d60cf49 100644
--- a/ubi-utils/ubirsvol.c
+++ b/ubi-utils/ubirsvol.c
@@ -114,7 +114,7 @@ static int parse_opt(int argc, char * const argv[])
 
 		switch (key) {
 		case 's':
-			args.bytes = ubiutils_get_bytes(optarg);
+			args.bytes = parse_bytes(optarg);
 			if (args.bytes <= 0)
 				return errmsg("bad volume size: \"%s\"", optarg);
 			break;
diff --git a/ubi-utils/ubiutils-common.c b/ubi-utils/ubiutils-common.c
index 6609a6b..d9ea3b7 100644
--- a/ubi-utils/ubiutils-common.c
+++ b/ubi-utils/ubiutils-common.c
@@ -34,99 +34,6 @@
 #include <unistd.h>
 #include "common.h"
 
-/**
- * get_multiplier - convert size specifier to an integer multiplier.
- * @str: the size specifier string
- *
- * This function parses the @str size specifier, which may be one of
- * 'KiB', 'MiB', or 'GiB' into an integer multiplier. Returns positive
- * size multiplier in case of success and %-1 in case of failure.
- */
-static int get_multiplier(const char *str)
-{
-	if (!str)
-		return 1;
-
-	/* Remove spaces before the specifier */
-	while (*str == ' ' || *str == '\t')
-		str += 1;
-
-	if (!strcmp(str, "KiB"))
-		return 1024;
-	if (!strcmp(str, "MiB"))
-		return 1024 * 1024;
-	if (!strcmp(str, "GiB"))
-		return 1024 * 1024 * 1024;
-
-	return -1;
-}
-
-/**
- * ubiutils_get_bytes - convert a string containing amount of bytes into an
- * integer
- * @str: string to convert
- *
- * This function parses @str which may have one of 'KiB', 'MiB', or 'GiB'
- * size specifiers. Returns positive amount of bytes in case of success and %-1
- * in case of failure.
- */
-long long ubiutils_get_bytes(const char *str)
-{
-	char *endp;
-	long long bytes = strtoull(str, &endp, 0);
-
-	if (endp == str || bytes < 0) {
-		fprintf(stderr, "incorrect amount of bytes: \"%s\"\n", str);
-		return -1;
-	}
-
-	if (*endp != '\0') {
-		int mult = get_multiplier(endp);
-
-		if (mult == -1) {
-			fprintf(stderr, "bad size specifier: \"%s\" - "
-			        "should be 'KiB', 'MiB' or 'GiB'\n", endp);
-			return -1;
-		}
-		bytes *= mult;
-	}
-
-	return bytes;
-}
-
-/**
- * ubiutils_print_bytes - print bytes.
- * @bytes: variable to print
- * @bracket: whether brackets have to be put or not
- *
- * This is a helper function which prints amount of bytes in a human-readable
- * form, i.e., it prints the exact amount of bytes following by the approximate
- * amount of Kilobytes, Megabytes, or Gigabytes, depending on how big @bytes
- * is.
- */
-void ubiutils_print_bytes(long long bytes, int bracket)
-{
-	const char *p;
-
-	if (bracket)
-		p = " (";
-	else
-		p = ", ";
-
-	printf("%lld bytes", bytes);
-
-	if (bytes > 1024 * 1024 * 1024)
-		printf("%s%.1f GiB", p, (double)bytes / (1024 * 1024 * 1024));
-	else if (bytes > 1024 * 1024)
-		printf("%s%.1f MiB", p, (double)bytes / (1024 * 1024));
-	else if (bytes > 1024 && bytes != 0)
-		printf("%s%.1f KiB", p, (double)bytes / 1024);
-	else
-		return;
-
-	if (bracket)
-		printf(")");
-}
 
 /**
  * ubiutils_print_text - print text and fold it.
diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 8ac09f2..f4bfe0b 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -390,62 +390,6 @@ static int validate_options(void)
 	return 0;
 }
 
-/**
- * get_multiplier - convert size specifier to an integer multiplier.
- * @str: the size specifier string
- *
- * This function parses the @str size specifier, which may be one of
- * 'KiB', 'MiB', or 'GiB' into an integer multiplier. Returns positive
- * size multiplier in case of success and %-1 in case of failure.
- */
-static int get_multiplier(const char *str)
-{
-	if (!str)
-		return 1;
-
-	/* Remove spaces before the specifier */
-	while (*str == ' ' || *str == '\t')
-		str += 1;
-
-	if (!strcmp(str, "KiB"))
-		return 1024;
-	if (!strcmp(str, "MiB"))
-		return 1024 * 1024;
-	if (!strcmp(str, "GiB"))
-		return 1024 * 1024 * 1024;
-
-	return -1;
-}
-
-/**
- * get_bytes - convert a string containing amount of bytes into an
- *             integer.
- * @str: string to convert
- *
- * This function parses @str which may have one of 'KiB', 'MiB', or 'GiB' size
- * specifiers. Returns positive amount of bytes in case of success and %-1 in
- * case of failure.
- */
-static long long get_bytes(const char *str)
-{
-	char *endp;
-	long long bytes = strtoull(str, &endp, 0);
-
-	if (endp == str || bytes < 0)
-		return err_msg("incorrect amount of bytes: \"%s\"", str);
-
-	if (*endp != '\0') {
-		int mult = get_multiplier(endp);
-
-		if (mult == -1)
-			return err_msg("bad size specifier: \"%s\" - "
-				       "should be 'KiB', 'MiB' or 'GiB'", endp);
-		bytes *= mult;
-	}
-
-	return bytes;
-}
-
 static int get_options(int argc, char**argv)
 {
 	int opt, i;
@@ -495,17 +439,17 @@ static int get_options(int argc, char**argv)
 						   root);
 			break;
 		case 'm':
-			c->min_io_size = get_bytes(optarg);
+			c->min_io_size = parse_bytes(optarg);
 			if (c->min_io_size <= 0)
 				return err_msg("bad min. I/O size");
 			break;
 		case 'e':
-			c->leb_size = get_bytes(optarg);
+			c->leb_size = parse_bytes(optarg);
 			if (c->leb_size <= 0)
 				return err_msg("bad LEB size");
 			break;
 		case 'c':
-			c->max_leb_cnt = get_bytes(optarg);
+			c->max_leb_cnt = parse_bytes(optarg);
 			if (c->max_leb_cnt <= 0)
 				return err_msg("bad maximum LEB count");
 			break;
@@ -595,12 +539,12 @@ static int get_options(int argc, char**argv)
 #endif
 			break;
 		case 'j':
-			c->max_bud_bytes = get_bytes(optarg);
+			c->max_bud_bytes = parse_bytes(optarg);
 			if (c->max_bud_bytes <= 0)
 				return err_msg("bad maximum amount of buds");
 			break;
 		case 'R':
-			c->rp_size = get_bytes(optarg);
+			c->rp_size = parse_bytes(optarg);
 			if (c->rp_size < 0)
 				return err_msg("bad reserved bytes count");
 			break;
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 31/38] ubifs: add decompression functions
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (29 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 30/38] Make cli byte parsing from ubi-utils available for all tools Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 32/38] ubifs: remove ununsed ubifs context from key helpers Dongsheng Yang
                   ` (6 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

From: David Gstir <david@sigma-star.at>

This enables decompression of lzo and zlib compressed data in addition to the
existin compression functions.

Signed-off-by: David Gstir <david@sigma-star.at>
Signed-off-by: Richard Weinberger <richard@nod.at>

Fix WITHOUT_LZO problem

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 ubifs-utils/include/compr.h |  1 +
 ubifs-utils/lib/compr.c     | 77 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+)

diff --git a/ubifs-utils/include/compr.h b/ubifs-utils/include/compr.h
index d44a2ba..9f6a173 100644
--- a/ubifs-utils/include/compr.h
+++ b/ubifs-utils/include/compr.h
@@ -39,6 +39,7 @@ enum compression_type
 };
 
 int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len, int type, int lzo_percent);
+int decompress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len, int type);
 int init_compression(void);
 void destroy_compression(void);
 
diff --git a/ubifs-utils/lib/compr.c b/ubifs-utils/lib/compr.c
index 54604d4..5c4997e 100644
--- a/ubifs-utils/lib/compr.c
+++ b/ubifs-utils/lib/compr.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2008 Nokia Corporation.
  * Copyright (C) 2008 University of Szeged, Hungary
+ * Copyright (C) 2015 sigma star gmbh
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 as published by
@@ -18,6 +19,8 @@
  * Authors: Artem Bityutskiy
  *          Adrian Hunter
  *          Zoltan Sogor
+ *          Richard Weinberger
+ *          David Gstir
  */
 
 #include "ubifs_common.h"
@@ -81,6 +84,47 @@ static int zlib_deflate(void *in_buf, size_t in_len, void *out_buf,
 	return 0;
 }
 
+static int zlib_inflate(void *in_buf, size_t in_len, void *out_buf,
+			size_t *out_len)
+{
+	z_stream strm;
+
+	strm.zalloc = NULL;
+	strm.zfree = NULL;
+
+	/*
+	 * Match exactly the zlib parameters used by the Linux kernel crypto
+	 * API.
+	 */
+        if (inflateInit2(&strm, -DEFLATE_DEF_WINBITS)) {
+		errcnt += 1;
+		return -1;
+	}
+
+	strm.next_in = in_buf;
+	strm.avail_in = in_len;
+	strm.total_in = 0;
+
+	strm.next_out = out_buf;
+	strm.avail_out = *out_len;
+	strm.total_out = 0;
+
+	if (inflate(&strm, Z_FINISH) != Z_STREAM_END) {
+		inflateEnd(&strm);
+		errcnt += 1;
+		return -1;
+	}
+
+	if (inflateEnd(&strm) != Z_OK) {
+		errcnt += 1;
+		return -1;
+	}
+
+	*out_len = strm.total_out;
+
+	return 0;
+}
+
 #ifndef WITHOUT_LZO
 static int lzo_compress(void *in_buf, size_t in_len, void *out_buf,
 			size_t *out_len)
@@ -200,6 +244,39 @@ int compress_data(void *in_buf, size_t in_len, void *out_buf,
 	return type;
 }
 
+int decompress_data(void *in_buf, size_t in_len, void *out_buf,
+		    size_t *out_len, int type)
+{
+	int err = 0;
+
+	switch (type) {
+	case UBIFS_COMPR_NONE:
+		if (*out_len < in_len) {
+			err = -1;
+			goto out;
+		}
+		memcpy(out_buf, in_buf, in_len);
+		*out_len = in_len;
+		break;
+#ifndef WITHOUT_LZO
+	case UBIFS_COMPR_LZO:
+		err = lzo1x_decompress_safe(in_buf, in_len, (unsigned char *)out_buf, out_len, NULL);
+		err = (err == LZO_E_OK) ? 0 : -1;
+		break;
+#endif
+	case UBIFS_COMPR_ZLIB:
+		err = zlib_inflate(in_buf, in_len, out_buf, out_len);
+		break;
+	default:
+		errcnt += 1;
+		err = 1;
+		break;
+	}
+
+out:
+	return err;
+}
+
 int init_compression(void)
 {
 #ifdef WITHOUT_LZO
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 32/38] ubifs: remove ununsed ubifs context from key helpers
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (30 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 31/38] ubifs: add decompression functions Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 33/38] ubifs: keep scan buffer in ubifs_info Dongsheng Yang
                   ` (5 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd

From: David Gstir <david@sigma-star.at>

Various key helper functions in ubifs-utils/include/key.h require the
ubifs_info context. Since this context is never used, so we can remove it.

Signed-off-by: David Gstir <david@sigma-star.at>
Signed-off-by: Richard Weinberger <richard@nod.at>
---
 ubifs-utils/include/key.h           | 24 ++++++------------------
 ubifs-utils/lib/scan.c              | 10 ++++------
 ubifs-utils/ubifs_dump/ubifs_dump.c | 22 +++++++++++-----------
 3 files changed, 21 insertions(+), 35 deletions(-)

diff --git a/ubifs-utils/include/key.h b/ubifs-utils/include/key.h
index 1b61928..ebcf79c 100644
--- a/ubifs-utils/include/key.h
+++ b/ubifs-utils/include/key.h
@@ -92,7 +92,6 @@ static inline uint32_t key_test_hash(const char *str, int len)
 
 /**
  * ino_key_init - initialize inode key.
- * @c: UBIFS file-system description object
  * @key: key to initialize
  * @inum: inode number
  */
@@ -208,12 +207,10 @@ static inline int keys_cmp(const union ubifs_key *key1,
 
 /**
  * key_read - transform a key to in-memory format.
- * @c: UBIFS file-system description object
  * @from: the key to transform
  * @to: the key to store the result
  */
-static inline void key_read(const struct ubifs_info *c __attribute__((unused)), const void *from,
-			    union ubifs_key *to)
+static inline void key_read(const void *from, union ubifs_key *to)
 {
 	const union ubifs_key *f = from;
 
@@ -223,45 +220,38 @@ static inline void key_read(const struct ubifs_info *c __attribute__((unused)),
 
 /**
  * invalid_key_init - initialize invalid node key.
- * @c: UBIFS file-system description object
  * @key: key to initialize
  *
  * This is a helper function which marks a @key object as invalid.
  */
-static inline void invalid_key_init(const struct ubifs_info *c __attribute__((unused)),
-				    union ubifs_key *key)
+static inline void invalid_key_init(union ubifs_key *key)
 {
 	key->u32[0] = 0xDEADBEAF;
 	key->u32[1] = UBIFS_INVALID_KEY;
 }
 /**
  * key_type - get key type.
- * @c: UBIFS file-system description object
  * @key: key to get type of
  */
-static inline int key_type(const struct ubifs_info *c __attribute__((unused)),
-			   const union ubifs_key *key)
+static inline int key_type(const union ubifs_key *key)
 {
 	return key->u32[1] >> UBIFS_S_KEY_BLOCK_BITS;
 }
 
 /*
  * key_hash - get directory entry hash.
- * @c: UBIFS file-system description object
  * @key: the key to get hash from
  */
-static inline uint32_t key_hash(const struct ubifs_info *c __attribute__((unused)),
-				const union ubifs_key *key)
+static inline uint32_t key_hash(const union ubifs_key *key)
 {
 	return key->u32[1] & UBIFS_S_KEY_HASH_MASK;
 }
 
 /**
  * key_inum - fetch inode number from key.
- * @c: UBIFS file-system description object
  * @k: key to fetch inode number from
  */
-static inline ino_t key_inum(const struct ubifs_info *c __attribute__((unused)), const void *k)
+static inline ino_t key_inum(const void *k)
 {
 	const union ubifs_key *key = k;
 
@@ -270,11 +260,9 @@ static inline ino_t key_inum(const struct ubifs_info *c __attribute__((unused)),
 
 /**
  * key_block - get data block number.
- * @c: UBIFS file-system description object
  * @key: the key to get the block number from
  */
-static inline unsigned int key_block(const struct ubifs_info *c __attribute__((unused)),
-				     const union ubifs_key *key)
+static inline unsigned int key_block(const union ubifs_key *key)
 {
 	return key->u32[1] & UBIFS_S_KEY_BLOCK_MASK;
 }
diff --git a/ubifs-utils/lib/scan.c b/ubifs-utils/lib/scan.c
index 69c84d1..3c5be2c 100644
--- a/ubifs-utils/lib/scan.c
+++ b/ubifs-utils/lib/scan.c
@@ -162,15 +162,13 @@ void ubifs_end_scan(const struct ubifs_info *c, struct ubifs_scan_leb *sleb,
 
 /**
  * ubifs_add_snod - add a scanned node to LEB scanning information.
- * @c: UBIFS file-system description object
  * @sleb: scanning information
  * @buf: buffer containing node
  * @offs: offset of node on flash
  *
  * This function returns %0 on success and a negative error code on failure.
  */
-int ubifs_add_snod(const struct ubifs_info *c, struct ubifs_scan_leb *sleb,
-		   void *buf, int offs)
+int ubifs_add_snod(struct ubifs_scan_leb *sleb, void *buf, int offs)
 {
 	struct ubifs_ch *ch = buf;
 	struct ubifs_ino_node *ino = buf;
@@ -195,10 +193,10 @@ int ubifs_add_snod(const struct ubifs_info *c, struct ubifs_scan_leb *sleb,
 		 * The key is in the same place in all keyed
 		 * nodes.
 		 */
-		key_read(c, &ino->key, &snod->key);
+		key_read(&ino->key, &snod->key);
 		break;
 	default:
-		invalid_key_init(c, &snod->key);
+		invalid_key_init(&snod->key);
 		break;
 	}
 	list_add_tail(&snod->list, &sleb->nodes);
@@ -267,7 +265,7 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
 			goto error;
 		}
 
-		err = ubifs_add_snod(c, sleb, buf, offs);
+		err = ubifs_add_snod(sleb, buf, offs);
 		if (err)
 			goto error;
 
diff --git a/ubifs-utils/ubifs_dump/ubifs_dump.c b/ubifs-utils/ubifs_dump/ubifs_dump.c
index 47b0c89..fe2aaf4 100644
--- a/ubifs-utils/ubifs_dump/ubifs_dump.c
+++ b/ubifs-utils/ubifs_dump/ubifs_dump.c
@@ -91,30 +91,30 @@ const char *dbg_snprintf_key(const struct ubifs_info *c,
 			     const union ubifs_key *key, char *buffer, int len)
 {
 	char *p = buffer;
-	int type = key_type(c, key);
+	int type = key_type(key);
 
 	if (c->key_fmt == UBIFS_SIMPLE_KEY_FMT) {
 		switch (type) {
 
 		case UBIFS_INO_KEY:
 			len -= snprintf(p, len, "(%lu, %s)",
-					(unsigned long)key_inum(c, key),
+					(unsigned long)key_inum(key),
 					get_key_type(type));
 			break;
 		case UBIFS_DENT_KEY:
 		case UBIFS_XENT_KEY:
 			len -= snprintf(p, len, "(%lu, %s, %#08x)",
-					(unsigned long)key_inum(c, key),
-					get_key_type(type), key_hash(c, key));
+					(unsigned long)key_inum(key),
+					get_key_type(type), key_hash(key));
 			break;
 		case UBIFS_DATA_KEY:
 			len -= snprintf(p, len, "(%lu, %s, %u)",
-					(unsigned long)key_inum(c, key),
-					get_key_type(type), key_block(c, key));
+					(unsigned long)key_inum(key),
+					get_key_type(type), key_block(key));
 			break;
 		case UBIFS_TRUN_KEY:
 			len -= snprintf(p, len, "(%lu, %s)",
-					(unsigned long)key_inum(c, key),
+					(unsigned long)key_inum(key),
 					get_key_type(type));
 			break;
 		default:
@@ -252,7 +252,7 @@ void dump_node(const struct ubifs_info *c, const void *node)
 	{
 		const struct ubifs_ino_node *ino = node;
 
-		key_read(c, &ino->key, &key);
+		key_read(&ino->key, &key);
 		printf("\t\tkey \t\t\t\t%s\n",
 		       dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
 		printf("\t\tcreat_sqnum \t\t\t%llu\n",
@@ -287,7 +287,7 @@ void dump_node(const struct ubifs_info *c, const void *node)
 		const struct ubifs_dent_node *dent = node;
 		int nlen = le16_to_cpu(dent->nlen);
 
-		key_read(c, &dent->key, &key);
+		key_read(&dent->key, &key);
 		printf("\t\tkey \t\t\t\t%s\n",
 		       dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
 		printf("\t\tinum \t\t\t\t%llu\n",
@@ -311,7 +311,7 @@ void dump_node(const struct ubifs_info *c, const void *node)
 		const struct ubifs_data_node *dn = node;
 		int dlen = le32_to_cpu(ch->len) - UBIFS_DATA_NODE_SZ;
 
-		key_read(c, &dn->key, &key);
+		key_read(&dn->key, &key);
 		printf("\t\tkey \t\t\t\t%s\n",
 		       dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
 		printf("\t\tsize \t\t\t\t%u\n", le32_to_cpu(dn->size));
@@ -347,7 +347,7 @@ void dump_node(const struct ubifs_info *c, const void *node)
 			const struct ubifs_branch *br;
 
 			br = ubifs_idx_branch(c, idx, i);
-			key_read(c, &br->key, &key);
+			key_read(&br->key, &key);
 			printf("\t\t%d: LEB %d:%d len %d key %s\n",
 			       i, le32_to_cpu(br->lnum), le32_to_cpu(br->offs),
 			       le32_to_cpu(br->len),
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 33/38] ubifs: keep scan buffer in ubifs_info
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (31 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 32/38] ubifs: remove ununsed ubifs context from key helpers Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 34/38] ubifs: extend master scanning code Dongsheng Yang
                   ` (4 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd

From: David Gstir <david@sigma-star.at>

Like in der kernel's UBIFS code, we keep a single scan buffer in the ubifs_info
struct for all scan-related functions to use.

Signed-off-by: David Gstir <david@sigma-star.at>
Signed-off-by: Richard Weinberger <richard@nod.at>
---
 ubifs-utils/include/ubifs.h         | 2 ++
 ubifs-utils/ubifs_dump/ubifs_dump.c | 1 +
 2 files changed, 3 insertions(+)

diff --git a/ubifs-utils/include/ubifs.h b/ubifs-utils/include/ubifs.h
index 1678663..4a3212f 100644
--- a/ubifs-utils/include/ubifs.h
+++ b/ubifs-utils/include/ubifs.h
@@ -329,6 +329,7 @@ enum {
  * @vi: UBI volume information
  *
  * @gc_lnum: LEB number used for garbage collection
+ * @sbuf: a buffer of LEB size used by GC and replay for scanning
  * @rp_size: reserved pool size
  *
  * @space_bits: number of bits needed to record free or dirty space
@@ -407,6 +408,7 @@ struct ubifs_info
 	struct ubi_vol_info vi;
 
 	int gc_lnum;
+	void *sbuf;
 	long long rp_size;
 
 	int space_bits;
diff --git a/ubifs-utils/ubifs_dump/ubifs_dump.c b/ubifs-utils/ubifs_dump/ubifs_dump.c
index fe2aaf4..4cbf755 100644
--- a/ubifs-utils/ubifs_dump/ubifs_dump.c
+++ b/ubifs-utils/ubifs_dump/ubifs_dump.c
@@ -991,6 +991,7 @@ static int dump()
 		err = -ENOMEM;
 		goto out;
 	}
+	c->sbuf = leb_buf;
 
 	err = dump_master();
 	if (err)
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 34/38] ubifs: extend master scanning code
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (32 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 33/38] ubifs: keep scan buffer in ubifs_info Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 35/38] ubifs: add missing include to defs.h Dongsheng Yang
                   ` (3 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

From: David Gstir <david@sigma-star.at>

Move to dedicated file and add master node validation

Signed-off-by: David Gstir <david@sigma-star.at>
Signed-off-by: Richard Weinberger <richard@nod.at>
Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 Makefile                            |   2 +-
 ubifs-utils/include/master.h        |   7 +
 ubifs-utils/include/ubifs.h         |  22 +++
 ubifs-utils/lib/master.c            | 311 ++++++++++++++++++++++++++++++++++++
 ubifs-utils/ubifs_dump/ubifs_dump.c |  64 +-------
 5 files changed, 342 insertions(+), 64 deletions(-)
 create mode 100644 ubifs-utils/include/master.h
 create mode 100644 ubifs-utils/lib/master.c

diff --git a/Makefile b/Makefile
index c9dbc58..c892787 100644
--- a/Makefile
+++ b/Makefile
@@ -130,7 +130,7 @@ $(foreach v,$(UBI_BINS),$(eval $(call mkdep,ubi-utils/,$(v),libubi.a ubiutils-co
 $(foreach v,crc16.o lpt.o compr.o devtable.o io.o hashtable.o hashtable_itr.o,$(eval UBIFS_LIBS += ../lib/$(v)))
 
 obj-ubifs_dump = $(UBIFS_LIBS)
-obj-ubifs_dump += ../lib/scan.o ../lib/lprops.o ../lib/hexdump.o
+obj-ubifs_dump += ../lib/scan.o ../lib/master.o ../lib/lprops.o ../lib/hexdump.o
 LDFLAGS_ubifs_dump = $(ZLIBLDFLAGS) $(LZOLDFLAGS) $(UUIDLDFLAGS)
 LDLIBS_ubifs_dump = -lz -llzo2 -lm -luuid
 $(call mkdep,ubifs-utils/ubifs_dump/,ubifs_dump,,ubi-utils/libubi.a)
diff --git a/ubifs-utils/include/master.h b/ubifs-utils/include/master.h
new file mode 100644
index 0000000..0e51455
--- /dev/null
+++ b/ubifs-utils/include/master.h
@@ -0,0 +1,7 @@
+#ifndef __UBIFS_MASTER_H__
+#define __UBIFS_MASTER_H__
+
+int scan_for_master(struct ubifs_info *c, struct ubifs_mst_node *mst_node);
+int ubifs_read_master(struct ubifs_info *c);
+
+#endif
diff --git a/ubifs-utils/include/ubifs.h b/ubifs-utils/include/ubifs.h
index 4a3212f..54ca865 100644
--- a/ubifs-utils/include/ubifs.h
+++ b/ubifs-utils/include/ubifs.h
@@ -32,9 +32,22 @@
 /* Maximum logical eraseblock size in bytes */
 #define UBIFS_MAX_LEB_SZ (2*1024*1024)
 
+/* "File system end of life" sequence number watermark */
+#define SQNUM_WARN_WATERMARK 0xFFFFFFFF00000000ULL
+#define SQNUM_WATERMARK      0xFFFFFFFFFF000000ULL
+
 /* Minimum amount of data UBIFS writes to the flash */
 #define MIN_WRITE_SZ (UBIFS_DATA_NODE_SZ + 8)
 
+/*
+ * Currently we do not support inode number overlapping and re-using, so this
+ * watermark defines dangerous inode number level. This should be fixed later,
+ * although it is difficult to exceed current limit. Another option is to use
+ * 64-bit inode numbers, but this means more overhead.
+ */
+#define INUM_WARN_WATERMARK 0xFFF00000
+#define INUM_WATERMARK      0xFFFFFF00
+
 /* Largest key size supported in this implementation */
 #define CUR_MAX_KEY_LEN UBIFS_SK_LEN
 
@@ -291,6 +304,10 @@ enum {
  * @highest_inum: highest used inode number
  * @max_sqnum: current global sequence number
  *
+ * @cmt_no: commit number of the last successfully completed commit, protected
+ *          by @commit_sem
+ *
+ * @lhead_lnum: log head logical eraseblock number
  * @jhead_cnt: count of journal heads
  * @max_bud_bytes: maximum number of bytes allowed in buds
  *
@@ -363,11 +380,15 @@ enum {
  * @lsave_offs: offset of LPT's save table
  * @lsave: LPT's save table
  * @lscan_lnum: LEB number of last LPT scan
+ * @verbose: verbose mode enabled
  */
 struct ubifs_info
 {
 	ino_t highest_inum;
 	unsigned long long max_sqnum;
+	unsigned long long cmt_no;
+
+	int lhead_lnum;
 
 	int jhead_cnt;
 	long long max_bud_bytes;
@@ -451,6 +472,7 @@ struct ubifs_info
 	int max_idx_node_sz;
 
 	int max_znode_sz;
+	int verbose;
 };
 /**
  * struct ubifs_scan_node - UBIFS scanned node information.
diff --git a/ubifs-utils/lib/master.c b/ubifs-utils/lib/master.c
new file mode 100644
index 0000000..ee640c7
--- /dev/null
+++ b/ubifs-utils/lib/master.c
@@ -0,0 +1,311 @@
+/*
+ * This file is part of UBIFS.
+ *
+ * Copyright (C) 2006-2008 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Artem Bityutskiy (Битюцкий Артём)
+ *          Adrian Hunter
+ */
+/*
+ * Modifications for mtd-utils.
+ *
+ * Copyright (C) 2015 sigma star gmbh
+ *
+ * Authors: Richard Weinberger
+ *          David Gstir
+ */
+
+/* This file implements reading and writing the master node */
+
+#define PROGRAM_NAME "master"
+
+#include "ubifs_common.h"
+#include "common.h"
+#include "ubifs.h"
+#include "scan.h"
+#include "master.h"
+
+
+/**
+ * scan_for_master - search the valid master node.
+ * @c: UBIFS file-system description object
+ * @mst_node: output master node
+ *
+ * This function scans the master node LEBs and search for the latest master
+ * node. Returns zero in case of success, %-EUCLEAN if there master area is
+ * corrupted and requires recovery, and a negative error code in case of
+ * failure.
+ */
+int scan_for_master(struct ubifs_info *c, struct ubifs_mst_node *mst_node)
+{
+	struct ubifs_scan_leb *sleb;
+	struct ubifs_scan_node *snod;
+	int lnum, offs = 0, nodes_cnt;
+	int err = -EUCLEAN;
+
+	lnum = UBIFS_MST_LNUM;
+
+	sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1);
+	if (IS_ERR(sleb)) {
+		err = PTR_ERR(sleb);
+		goto out;
+	}
+	nodes_cnt = sleb->nodes_cnt;
+	if (nodes_cnt > 0) {
+		snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node,
+				  list);
+		if (snod->type != UBIFS_MST_NODE)
+			goto out_dump;
+		memcpy(mst_node, snod->node, snod->len);
+		offs = snod->offs;
+	}
+	ubifs_scan_destroy(sleb);
+
+	lnum += 1;
+
+	sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1);
+	if (IS_ERR(sleb)) {
+		err = PTR_ERR(sleb);
+		goto out;
+	}
+	if (sleb->nodes_cnt != nodes_cnt)
+		goto out_destroy;
+	if (!sleb->nodes_cnt)
+		goto out_destroy;
+	snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, list);
+	if (snod->type != UBIFS_MST_NODE)
+		goto out_dump;
+	if (snod->offs != offs)
+		goto out_destroy;
+	if (memcmp((void *)mst_node + UBIFS_CH_SZ,
+		   (void *)snod->node + UBIFS_CH_SZ,
+		   UBIFS_MST_NODE_SZ - UBIFS_CH_SZ))
+		goto out_destroy;
+
+	err = 0;
+
+out_destroy:
+	ubifs_scan_destroy(sleb);
+out:
+	return err;
+
+out_dump:
+	errmsg("unexpected node type %d master LEB %d:%d",
+		  snod->type, lnum, snod->offs);
+	err = -EINVAL;
+	goto out_destroy;
+}
+/**
+ * validate_master - validate master node.
+ * @c: UBIFS file-system description object
+ *
+ * This function validates data which was read from master node. Returns zero
+ * if the data is all right and %-EINVAL if not.
+ */
+static int validate_master(const struct ubifs_info *c)
+{
+	long long main_sz;
+	int err;
+
+	if (c->max_sqnum >= SQNUM_WATERMARK) {
+		err = 1;
+		goto out;
+	}
+
+	if (c->cmt_no >= c->max_sqnum) {
+		err = 2;
+		goto out;
+	}
+
+	if (c->highest_inum >= INUM_WATERMARK) {
+		err = 3;
+		goto out;
+	}
+
+	if (c->lhead_lnum < UBIFS_LOG_LNUM ||
+	    c->lhead_lnum >= UBIFS_LOG_LNUM + c->log_lebs) {
+		err = 4;
+		goto out;
+	}
+
+	if (c->zroot.lnum >= c->leb_cnt || c->zroot.lnum < c->main_first ||
+	    c->zroot.offs >= c->leb_size || c->zroot.offs & 7) {
+		err = 5;
+		goto out;
+	}
+
+	if (c->zroot.len < UBIFS_IDX_NODE_SZ + UBIFS_BRANCH_SZ ||
+	    c->zroot.len > INT_MAX) {
+		err = 6;
+		goto out;
+	}
+
+	if (c->gc_lnum >= c->leb_cnt || c->gc_lnum < c->main_first) {
+		err = 7;
+		goto out;
+	}
+
+	if (c->ihead_lnum >= c->leb_cnt || c->ihead_lnum < c->main_first ||
+	    c->ihead_offs % c->min_io_size || c->ihead_offs < 0 ||
+	    c->ihead_offs > c->leb_size || c->ihead_offs & 7) {
+		err = 8;
+		goto out;
+	}
+
+	main_sz = (long long)c->main_lebs * c->leb_size;
+
+	if (c->lpt_lnum < c->lpt_first || c->lpt_lnum > c->lpt_last ||
+	    c->lpt_offs < 0 || c->lpt_offs + c->nnode_sz > c->leb_size) {
+		err = 10;
+		goto out;
+	}
+
+	if (c->nhead_lnum < c->lpt_first || c->nhead_lnum > c->lpt_last ||
+	    c->nhead_offs < 0 || c->nhead_offs % c->min_io_size ||
+	    c->nhead_offs > c->leb_size) {
+		err = 11;
+		goto out;
+	}
+
+	if (c->ltab_lnum < c->lpt_first || c->ltab_lnum > c->lpt_last ||
+	    c->ltab_offs < 0 ||
+	    c->ltab_offs + c->ltab_sz > c->leb_size) {
+		err = 12;
+		goto out;
+	}
+
+	if (c->big_lpt && (c->lsave_lnum < c->lpt_first ||
+	    c->lsave_lnum > c->lpt_last || c->lsave_offs < 0 ||
+	    c->lsave_offs + c->lsave_sz > c->leb_size)) {
+		err = 13;
+		goto out;
+	}
+
+	if (c->lscan_lnum < c->main_first || c->lscan_lnum >= c->leb_cnt) {
+		err = 14;
+		goto out;
+	}
+
+	if (c->lst.empty_lebs < 0 || c->lst.empty_lebs > c->main_lebs - 2) {
+		err = 15;
+		goto out;
+	}
+
+	if (c->lst.idx_lebs < 0 || c->lst.idx_lebs > c->main_lebs - 1) {
+		err = 16;
+		goto out;
+	}
+
+	if (c->lst.total_free < 0 || c->lst.total_free > main_sz ||
+	    c->lst.total_free & 7) {
+		err = 17;
+		goto out;
+	}
+
+	if (c->lst.total_dirty < 0 || (c->lst.total_dirty & 7)) {
+		err = 18;
+		goto out;
+	}
+
+	if (c->lst.total_used < 0 || (c->lst.total_used & 7)) {
+		err = 19;
+		goto out;
+	}
+
+	if (c->lst.total_free + c->lst.total_dirty +
+	    c->lst.total_used > main_sz) {
+		err = 20;
+		goto out;
+	}
+
+	if (c->lst.total_dead < 0 ||
+	    c->lst.total_dead > c->lst.total_free + c->lst.total_dirty ||
+	    c->lst.total_dead & 7) {
+		err = 22;
+		goto out;
+	}
+
+	if (c->lst.total_dark < 0 ||
+	    c->lst.total_dark > c->lst.total_free + c->lst.total_dirty ||
+	    c->lst.total_dark & 7) {
+		err = 23;
+		goto out;
+	}
+
+	return 0;
+
+out:
+	errmsg("bad master node, error %d", err);
+	return -EINVAL;
+}
+
+/**
+ * ubifs_read_master - read master node.
+ * @c: UBIFS file-system description object
+ *
+ * This function finds and reads the master node during file-system mount. If
+ * the flash is empty, it creates default master node as well. Returns zero in
+ * case of success and a negative error code in case of failure.
+ */
+int ubifs_read_master(struct ubifs_info *c)
+{
+	int err;
+	struct ubifs_mst_node mst;
+
+	err = scan_for_master(c, &mst);
+	if (err) {
+		if (err == -EUCLEAN) {
+			normsg("master node requires recovery");
+			// TODO recover master node
+			// err = ubifs_recover_master_node(c);
+		} else
+			errmsg("failed to load master node");
+
+		if (err)
+			return err;
+	}
+
+	c->max_sqnum       = le64_to_cpu(mst.ch.sqnum);
+	c->highest_inum    = le64_to_cpu(mst.highest_inum);
+	c->cmt_no          = le64_to_cpu(mst.cmt_no);
+	c->zroot.lnum      = le32_to_cpu(mst.root_lnum);
+	c->zroot.offs      = le32_to_cpu(mst.root_offs);
+	c->zroot.len       = le32_to_cpu(mst.root_len);
+	c->lhead_lnum      = le32_to_cpu(mst.log_lnum);
+	c->gc_lnum         = le32_to_cpu(mst.gc_lnum);
+	c->ihead_lnum      = le32_to_cpu(mst.ihead_lnum);
+	c->ihead_offs      = le32_to_cpu(mst.ihead_offs);
+	c->lpt_lnum        = le32_to_cpu(mst.lpt_lnum);
+	c->lpt_offs        = le32_to_cpu(mst.lpt_offs);
+	c->nhead_lnum      = le32_to_cpu(mst.nhead_lnum);
+	c->nhead_offs      = le32_to_cpu(mst.nhead_offs);
+	c->ltab_lnum       = le32_to_cpu(mst.ltab_lnum);
+	c->ltab_offs       = le32_to_cpu(mst.ltab_offs);
+	c->lsave_lnum      = le32_to_cpu(mst.lsave_lnum);
+	c->lsave_offs      = le32_to_cpu(mst.lsave_offs);
+	c->lscan_lnum      = le32_to_cpu(mst.lscan_lnum);
+	c->lst.empty_lebs  = le32_to_cpu(mst.empty_lebs);
+	c->lst.idx_lebs    = le32_to_cpu(mst.idx_lebs);
+	c->lst.total_free  = le64_to_cpu(mst.total_free);
+	c->lst.total_dirty = le64_to_cpu(mst.total_dirty);
+	c->lst.total_used  = le64_to_cpu(mst.total_used);
+	c->lst.total_dead  = le64_to_cpu(mst.total_dead);
+	c->lst.total_dark  = le64_to_cpu(mst.total_dark);
+
+	verbose(c->verbose, "found master node with max sqnum %llu", c->max_sqnum);
+
+	return validate_master(c);
+}
diff --git a/ubifs-utils/ubifs_dump/ubifs_dump.c b/ubifs-utils/ubifs_dump/ubifs_dump.c
index 4cbf755..2f5ef84 100644
--- a/ubifs-utils/ubifs_dump/ubifs_dump.c
+++ b/ubifs-utils/ubifs_dump/ubifs_dump.c
@@ -8,6 +8,7 @@
 #include "lpt.h"
 #include "scan.h"
 #include "hexdump.h"
+#include "master.h"
 
 #define DBG_KEY_BUF_LEN		48
 
@@ -483,69 +484,6 @@ static int dump_super(void)
 	return init_constants_sb(c);
 }
 
-/**
- * scan_for_master - search the valid master node.
- * @c: UBIFS file-system description object
- *
- * This function scans the master node LEBs and search for the latest master
- * node. Returns zero in case of success, %-EUCLEAN if there master area is
- * corrupted and requires recovery, and a negative error code in case of
- * failure.
- */
-static int scan_for_master(struct ubifs_info *c, struct ubifs_mst_node *mst_node)
-{
-	struct ubifs_scan_leb *sleb;
-	struct ubifs_scan_node *snod;
-	int lnum, offs = 0, nodes_cnt;
-	int err = 0;
-
-	lnum = UBIFS_MST_LNUM;
-
-	sleb = ubifs_scan(c, lnum, 0, leb_buf, 1);
-	if (IS_ERR(sleb))
-		return PTR_ERR(sleb);
-	nodes_cnt = sleb->nodes_cnt;
-	if (nodes_cnt > 0) {
-		snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node,
-				  list);
-		if (snod->type != UBIFS_MST_NODE) {
-			err = -EINVAL;
-			goto out;
-		}
-		memcpy(mst_node, snod->node, snod->len);
-		offs = snod->offs;
-	}
-	ubifs_scan_destroy(sleb);
-
-	lnum += 1;
-
-	sleb = ubifs_scan(c, lnum, 0, leb_buf, 1);
-	if (IS_ERR(sleb)) {
-		return PTR_ERR(sleb);
-	}
-	err = -EUCLEAN;
-	if (sleb->nodes_cnt != nodes_cnt)
-		goto out;
-	if (!sleb->nodes_cnt)
-		goto out;
-	snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, list);
-	if (snod->type != UBIFS_MST_NODE) {
-		err = -EINVAL;
-		goto out;
-	}
-	if (snod->offs != offs)
-		goto out;
-	if (memcmp((void *)mst_node + UBIFS_CH_SZ,
-		   (void *)snod->node + UBIFS_CH_SZ,
-		   UBIFS_MST_NODE_SZ - UBIFS_CH_SZ))
-		goto out;
-	err = 0;
-
-out:
-	ubifs_scan_destroy(sleb);
-	return err;
-}
-
 static int dump_master(void)
 {
 	int err = 0;
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 35/38] ubifs: add missing include to defs.h
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (33 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 34/38] ubifs: extend master scanning code Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:41 ` [PATCH 36/38] ubifs: Add more key helper functions Dongsheng Yang
                   ` (2 subsequent siblings)
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd

From: David Gstir <david@sigma-star.at>

Signed-off-by: David Gstir <david@sigma-star.at>
Signed-off-by: Richard Weinberger <richard@nod.at>
---
 ubifs-utils/include/defs.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/ubifs-utils/include/defs.h b/ubifs-utils/include/defs.h
index 91ef175..93ff912 100644
--- a/ubifs-utils/include/defs.h
+++ b/ubifs-utils/include/defs.h
@@ -16,6 +16,7 @@
 #include <stddef.h>
 #include <linux/types.h>
 #include <stdint.h>
+#include <limits.h>
 
 #include <features.h>
 
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 36/38] ubifs: Add more key helper functions
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (34 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 35/38] ubifs: add missing include to defs.h Dongsheng Yang
@ 2015-12-21  8:41 ` Dongsheng Yang
  2015-12-21  8:42 ` [PATCH 37/38] ubifs: add emubi, a minimal UBI emulation layer Dongsheng Yang
  2015-12-21  8:42 ` [PATCH 38/38] UBIFS: introduce ubifs_unpacker tool Dongsheng Yang
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:41 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd

From: David Gstir <david@sigma-star.at>

Signed-off-by: David Gstir <david@sigma-star.at>
Signed-off-by: Richard Weinberger <richard@nod.at>
---
 ubifs-utils/include/key.h | 78 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/ubifs-utils/include/key.h b/ubifs-utils/include/key.h
index ebcf79c..3210cf2 100644
--- a/ubifs-utils/include/key.h
+++ b/ubifs-utils/include/key.h
@@ -138,6 +138,17 @@ static inline void xent_key_init(const struct ubifs_info *c,
 }
 
 /**
+ * lowest_dent_key - get the lowest possible directory entry key.
+ * @key: where to store the lowest key
+ * @inum: parent inode number
+ */
+static inline void lowest_dent_key(union ubifs_key *key, ino_t inum)
+{
+	key->u32[0] = inum;
+	key->u32[1] = UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS;
+}
+
+/**
  * data_key_init - initialize data key.
  * @c: UBIFS file-system description object
  * @key: key to initialize
@@ -182,6 +193,17 @@ static inline void key_write_idx(const union ubifs_key *from, void *to)
 }
 
 /**
+ * key_copy - copy a key.
+ * @c: UBIFS file-system description object
+ * @from: the key to copy from
+ * @to: the key to copy to
+ */
+static inline void key_copy(const union ubifs_key *from, union ubifs_key *to)
+{
+	to->u64[0] = from->u64[0];
+}
+
+/**
  * keys_cmp - compare keys.
  * @c: UBIFS file-system description object
  * @key1: the first key to compare
@@ -219,6 +241,22 @@ static inline void key_read(const void *from, union ubifs_key *to)
 }
 
 /**
+ * trun_key_init - initialize truncation node key.
+ * @c: UBIFS file-system description object
+ * @key: key to initialize
+ * @inum: inode number
+ *
+ * Note, UBIFS does not have truncation keys on the media and this function is
+ * only used for purposes of replay.
+ */
+static inline void trun_key_init(const struct ubifs_info *c __attribute__((unused)),
+				 union ubifs_key *key, ino_t inum)
+{
+	key->u32[0] = inum;
+	key->u32[1] = UBIFS_TRUN_KEY << UBIFS_S_KEY_BLOCK_BITS;
+}
+
+/**
  * invalid_key_init - initialize invalid node key.
  * @key: key to initialize
  *
@@ -238,6 +276,18 @@ static inline int key_type(const union ubifs_key *key)
 	return key->u32[1] >> UBIFS_S_KEY_BLOCK_BITS;
 }
 
+/**
+ * key_type_flash - get type of a on-flash formatted key.
+ * @c: UBIFS file-system description object
+ * @k: key to get type of
+ */
+static inline int key_type_flash(const void *k)
+{
+	const union ubifs_key *key = k;
+
+	return le32_to_cpu(key->j32[1]) >> UBIFS_S_KEY_BLOCK_BITS;
+}
+
 /*
  * key_hash - get directory entry hash.
  * @key: the key to get hash from
@@ -266,4 +316,32 @@ static inline unsigned int key_block(const union ubifs_key *key)
 {
 	return key->u32[1] & UBIFS_S_KEY_BLOCK_MASK;
 }
+
+/**
+ * is_hash_key - is a key vulnerable to hash collisions.
+ * @key: key
+ *
+ * This function returns %1 if @key is a hashed key or %0 otherwise.
+ */
+static inline int is_hash_key(const union ubifs_key *key)
+{
+	int type = key_type(key);
+
+	return type == UBIFS_DENT_KEY || type == UBIFS_XENT_KEY;
+}
+
+/**
+ * key_max_inode_size - get maximum file size allowed by current key format.
+ * @c: UBIFS file-system description object
+ */
+static inline unsigned long long key_max_inode_size(const struct ubifs_info *c)
+{
+	switch (c->key_fmt) {
+	case UBIFS_SIMPLE_KEY_FMT:
+		return (1ULL << UBIFS_S_KEY_BLOCK_BITS) * UBIFS_BLOCK_SIZE;
+	default:
+		return 0;
+	}
+}
+
 #endif /* !__UBIFS_KEY_H__ */
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 37/38] ubifs: add emubi, a minimal UBI emulation layer
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (35 preceding siblings ...)
  2015-12-21  8:41 ` [PATCH 36/38] ubifs: Add more key helper functions Dongsheng Yang
@ 2015-12-21  8:42 ` Dongsheng Yang
  2015-12-21  8:42 ` [PATCH 38/38] UBIFS: introduce ubifs_unpacker tool Dongsheng Yang
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:42 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

From: David Gstir <david@sigma-star.at>

emubi enables processing of ubi images (e.g. created using nanddump) as input
instead of using the ubi volume directly.

Signed-off-by: David Gstir <david@sigma-star.at>
Signed-off-by: Richard Weinberger <richard@nod.at>
Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 Makefile                    |   2 +-
 ubifs-utils/include/emubi.h |  81 ++++++++++
 ubifs-utils/include/io.h    |   2 +
 ubifs-utils/include/ubifs.h |   3 +
 ubifs-utils/lib/emubi.c     | 351 ++++++++++++++++++++++++++++++++++++++++++++
 ubifs-utils/lib/io.c        |  60 ++++++++
 ubifs-utils/lib/scan.c      |   2 +-
 7 files changed, 499 insertions(+), 2 deletions(-)
 create mode 100644 ubifs-utils/include/emubi.h
 create mode 100644 ubifs-utils/lib/emubi.c

diff --git a/Makefile b/Makefile
index c892787..1486791 100644
--- a/Makefile
+++ b/Makefile
@@ -127,7 +127,7 @@ $(foreach v,$(UBI_BINS),$(eval $(call mkdep,ubi-utils/,$(v),libubi.a ubiutils-co
 #
 # Utils in ubifs-utils subdir
 #
-$(foreach v,crc16.o lpt.o compr.o devtable.o io.o hashtable.o hashtable_itr.o,$(eval UBIFS_LIBS += ../lib/$(v)))
+$(foreach v,crc16.o lpt.o compr.o devtable.o emubi.o io.o hashtable.o hashtable_itr.o,$(eval UBIFS_LIBS += ../lib/$(v)))
 
 obj-ubifs_dump = $(UBIFS_LIBS)
 obj-ubifs_dump += ../lib/scan.o ../lib/master.o ../lib/lprops.o ../lib/hexdump.o
diff --git a/ubifs-utils/include/emubi.h b/ubifs-utils/include/emubi.h
new file mode 100644
index 0000000..e06ba7d
--- /dev/null
+++ b/ubifs-utils/include/emubi.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2015 sigma star gmbh
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Richard Weinberger
+ *          David Gstir
+ */
+
+#ifndef __UBIFS_EMUBI_H__
+#define __UBIFS_EMUBI_H__
+
+#include <assert.h>
+#include "list.h"
+
+enum {
+	EMUBI_MODE_FILE,
+	EMUBI_MODE_MMAP
+};
+
+/*
+ * LEB to PEB mapping.
+ * @pnum: PEB number this LEB belongs to, (for mode EMUBI_MODE_FILE)
+ * @data: pointer to start of PEB data (for mode EMUBI_MODE_MMAP)
+ */
+union emubi_eba {
+	int pnum;
+	char *data;
+};
+
+/*
+ * embui context
+ * @peb_size: PEB size in bytes
+ * @page_size: min I/O size used for UBI data (this is not the sub-page size)
+ * @vol_id: volume id
+ * @flash_fd: file descriptor of input file
+ * @mode: emubi mode
+ * @flash_mmap: mmap-ed input file when mode is set to EMUBI_MODE_MMAP
+ * @flash_size: total flash size in bytes
+ * @peb_count: total number of PEBs
+ * @leb_start: offset where LEB data starts
+ * @ff_peb: empty PEB
+ * @eba: eraseblock association table
+ * @scan_lebs: list of scanned LEBs
+ */
+struct emubi_ctx {
+	int peb_size;
+	int page_size;
+	int vol_id;
+
+	int flash_fd;
+	int mode;
+	char *flash_mmap;
+	unsigned long flash_size;
+
+	unsigned int peb_count;
+	unsigned int leb_start;
+	char *ff_peb;
+	union emubi_eba *eba;
+
+	struct list_head scan_lebs;
+};
+
+void emubi_print(struct emubi_ctx *ctx);
+int emubi_scan(struct emubi_ctx *ctx);
+int emubi_open(struct emubi_ctx *ctx, char *file);
+int emubi_leb_read(struct emubi_ctx *ctx, unsigned int lnum, unsigned int offset,
+		   char *lbuf, size_t len);
+
+#endif
diff --git a/ubifs-utils/include/io.h b/ubifs-utils/include/io.h
index 11f568c..e5c3d6c 100644
--- a/ubifs-utils/include/io.h
+++ b/ubifs-utils/include/io.h
@@ -18,4 +18,6 @@ int open_target(struct ubifs_info *c, int yes);
 int open_ubi(struct ubifs_info *c, const char *node);
 
 int ubifs_read(loff_t offset, int len, void *buf);
+int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
+		   int len);
 #endif
diff --git a/ubifs-utils/include/ubifs.h b/ubifs-utils/include/ubifs.h
index 54ca865..f03601d 100644
--- a/ubifs-utils/include/ubifs.h
+++ b/ubifs-utils/include/ubifs.h
@@ -28,6 +28,7 @@
 #include "defs.h"
 #include "list.h"
 #include "libubi.h"
+#include "emubi.h"
 
 /* Maximum logical eraseblock size in bytes */
 #define UBIFS_MAX_LEB_SZ (2*1024*1024)
@@ -380,6 +381,7 @@ enum {
  * @lsave_offs: offset of LPT's save table
  * @lsave: LPT's save table
  * @lscan_lnum: LEB number of last LPT scan
+ * @emubi: emubi context for working with image files
  * @verbose: verbose mode enabled
  */
 struct ubifs_info
@@ -472,6 +474,7 @@ struct ubifs_info
 	int max_idx_node_sz;
 
 	int max_znode_sz;
+	struct emubi_ctx *emubi;
 	int verbose;
 };
 /**
diff --git a/ubifs-utils/lib/emubi.c b/ubifs-utils/lib/emubi.c
new file mode 100644
index 0000000..1c88eea
--- /dev/null
+++ b/ubifs-utils/lib/emubi.c
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) 2015 sigma star gmbh
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Richard Weinberger
+ *          David Gstir
+ */
+
+#define PROGRAM_NAME "emubi"
+
+#include <sys/mman.h>
+
+#include "emubi.h"
+#include "common.h"
+#include "ubifs_common.h"
+#include "crc32.h"
+#include "xalloc.h"
+
+struct ubi_scan_leb {
+	struct list_head l;
+	int lnum;
+	int pnum;
+	unsigned long long sqnum;
+	unsigned int copy_flag:1;
+};
+
+static inline int get_peb(struct emubi_ctx *ctx, unsigned int pnum, char **pbuf,
+			  unsigned int offset, unsigned int len)
+{
+	off_t pos;
+
+	if (pnum >= ctx->peb_count)
+		errmsg_die("Invalid PEB number %u", pnum);
+
+	if (offset >= ctx->peb_size)
+		errmsg_die("Invalid read offset %u (PEB size %u)", offset, ctx->peb_size);
+
+	if (len > ctx->peb_size - offset)
+		return errmsg("Invalid read outside of PEB (size %u, offset %u, read len %u)",
+			      ctx->peb_size, offset, len);
+
+	pos = (pnum * ctx->peb_size) + offset;
+	switch (ctx->mode) {
+	case EMUBI_MODE_MMAP:
+		*pbuf = ctx->flash_mmap + pos;
+		break;
+	case EMUBI_MODE_FILE:
+		if (!*pbuf)
+			errmsg_die("pbuf must not be null!");
+
+		if (lseek(ctx->flash_fd, pos, SEEK_SET) != pos)
+			return errmsg("Failed to lseek input file: %m");
+
+		if (read(ctx->flash_fd, *pbuf, len) != len)
+			return errmsg("Failed to read from input file: %m");
+
+		break;
+	default:
+		return errmsg("Invalid emubi mode %d", ctx->mode);
+	}
+
+	return 0;
+}
+
+int emubi_leb_read(struct emubi_ctx *ctx, unsigned int lnum, unsigned int offset,
+		   char *lbuf, size_t len)
+{
+	char *leb;
+	int err;
+
+	if (lnum >= ctx->peb_count)
+		return errmsg("LEB number invalid %u!", lnum);
+
+	switch (ctx->mode) {
+	case EMUBI_MODE_MMAP:
+		if (ctx->eba[lnum].data)
+			leb = ctx->eba[lnum].data;
+		else
+			leb = ctx->ff_peb;
+
+		memcpy(lbuf, leb + ctx->leb_start + offset, len);
+		break;
+	case EMUBI_MODE_FILE:
+		if (ctx->eba[lnum].pnum == -1) {
+			memset(lbuf, 0xFF, len);
+		} else {
+			err = get_peb(ctx, ctx->eba[lnum].pnum, &lbuf,
+				      ctx->leb_start + offset, len);
+			if (err)
+				return errmsg("LEB read failed: %m");
+		}
+
+		break;
+	default:
+		errmsg_die("Unknown emubi mode!");
+	}
+
+	return 0;
+}
+
+static struct ubi_scan_leb *scan_leb_new(int pnum, struct ubi_vid_hdr *vh)
+{
+	struct ubi_scan_leb *sl = xmalloc(sizeof(*sl));
+
+	sl->lnum = be32toh(vh->lnum);
+	sl->sqnum = be64toh(vh->sqnum);
+	sl->pnum = pnum;
+	sl->copy_flag = !!vh->copy_flag;
+
+	return sl;
+}
+
+static int scan_leb_crc_check(struct emubi_ctx *ctx, int pnum, struct ubi_vid_hdr *vh, char *pbuf)
+{
+	int data_len;
+	uint32_t data_crc, crc;
+
+	if (!vh->copy_flag)
+		return 0;
+
+	data_len = be32toh(vh->data_size);
+	if (!data_len)
+		return 0;
+
+	assert(data_len <= ctx->peb_size - ctx->leb_start);
+
+	data_crc = be32toh(vh->data_crc);
+	crc = mtd_crc32(UBI_CRC32_INIT, pbuf + ctx->leb_start, data_len);
+
+	if (crc != data_crc) {
+		errmsg("crc mismatch in peb %i", pnum);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void scan_leb_apply(struct emubi_ctx *ctx, int pnum, struct ubi_vid_hdr *scan_vh, char *pbuf)
+{
+	struct ubi_scan_leb *tmp_sl, *sl, *dup_sl = NULL;
+	int lnum = be32toh(scan_vh->lnum);
+
+	if (scan_leb_crc_check(ctx, pnum, scan_vh, pbuf) < 0)
+		return;
+
+	list_for_each_entry(tmp_sl, &ctx->scan_lebs, l) {
+		if (tmp_sl->lnum == lnum) {
+			dup_sl = tmp_sl;
+			break;
+		}
+	}
+
+	sl = scan_leb_new(pnum, scan_vh);
+
+	if (sl->lnum >= ctx->peb_count) {
+		warnmsg("Found a LEB >= PEB count! Image truncated?");
+		return;
+	}
+
+	if (!dup_sl) {
+		list_add_tail(&sl->l, &ctx->scan_lebs);
+
+		return;
+	}
+
+	if (dup_sl->sqnum == sl->sqnum)
+		errmsg_die("Duplicate LEB with identical UBI sequence number!");
+
+	if (dup_sl->sqnum > sl->sqnum) {
+		free(sl);
+	} else {
+		list_del(&dup_sl->l);
+		free(dup_sl);
+		list_add_tail(&sl->l, &ctx->scan_lebs);
+	}
+}
+
+static int eba_from_scan(struct emubi_ctx *ctx)
+{
+	struct ubi_scan_leb *sl;
+
+	list_for_each_entry(sl, &ctx->scan_lebs, l) {
+		switch (ctx->mode) {
+		case EMUBI_MODE_MMAP:
+			ctx->eba[sl->lnum].data = ctx->flash_mmap + (sl->pnum * ctx->peb_size);
+			break;
+		case EMUBI_MODE_FILE:
+			ctx->eba[sl->lnum].pnum = sl->pnum;
+			break;
+		default:
+			return errmsg("Invalid emubi mode %d", ctx->mode);
+		}
+	}
+
+	return 0;
+}
+
+void emubi_print(struct emubi_ctx *ctx)
+{
+	normsg("flash metadata:");
+	printf("\tPEB size: ");
+	print_bytes(ctx->peb_size, 0);
+	printf("\n\tmin. I/O unit size: ");
+	print_bytes(ctx->page_size, 0);
+	printf("\n\tvolume ID: %d", ctx->vol_id);
+
+	if (ctx->flash_mmap) {
+		printf("\n\tflash size: ");
+		print_bytes(ctx->flash_size, 0);
+		printf("\n\tPEB count: %u", ctx->peb_count);
+		printf("\n\tdata offset: %u", ctx->leb_start);
+	}
+	printf("\n\temubi mode: %s\n", (ctx->mode == EMUBI_MODE_MMAP) ? "mmap" : "file");
+}
+
+static int is_empty(struct emubi_ctx *ctx, char *pbuf, size_t len)
+{
+	return memcmp(pbuf, ctx->ff_peb, len) == 0;
+}
+
+static inline void init_eba(struct emubi_ctx *ctx, int leb_start)
+{
+	int i;
+	//TODO: replace peb_count by correct value from vol table
+	ctx->eba = xcalloc(ctx->peb_count, sizeof(ctx->eba[0]));
+	ctx->leb_start = leb_start;
+
+	if (ctx->mode == EMUBI_MODE_FILE) {
+		for (i = 0; i < ctx->peb_count; i++) {
+			ctx->eba[i].pnum = -1;
+		}
+	}
+}
+
+int emubi_scan(struct emubi_ctx *ctx)
+{
+	int n, err;
+	char *pbuf = NULL;
+
+	INIT_LIST_HEAD(&ctx->scan_lebs);
+
+	if (ctx->mode == EMUBI_MODE_FILE)
+		pbuf = xmalloc(ctx->peb_size);
+
+	normsg("scanning for logical erase blocks...");
+	for (n = 0; n < ctx->peb_count; n++) {
+		err = get_peb(ctx, n, &pbuf, 0, ctx->peb_size);
+		if (err)
+			goto out;
+
+		struct ubi_ec_hdr *ec = (struct ubi_ec_hdr *)pbuf;
+		struct ubi_vid_hdr *vid;
+
+		if (be32toh(ec->magic) != UBI_EC_HDR_MAGIC) {
+			errmsg("PEB %u contains no valid EC header\n", n);
+			continue;
+		}
+
+		vid = (struct ubi_vid_hdr *)(pbuf + be32toh(ec->vid_hdr_offset));
+		if (be32toh(vid->magic) != UBI_VID_HDR_MAGIC) {
+			/* skip over pebs with empty vid header */
+			if (is_empty(ctx, (char *)vid, ctx->page_size))
+				continue;
+
+			errmsg("PEB %u contains invalid VID header\n", n);
+		}
+
+		if (!ctx->eba) {
+			init_eba(ctx, be32toh(ec->data_offset));
+		}
+
+		if (be32toh(vid->vol_id) == ctx->vol_id)
+			scan_leb_apply(ctx, n, vid, pbuf);
+	}
+
+	err = eba_from_scan(ctx);
+
+out:
+	if (ctx->mode == EMUBI_MODE_FILE)
+		free(pbuf);
+
+	return err;
+}
+
+int emubi_open(struct emubi_ctx *ctx, char *file)
+{
+	int err;
+	int fd;
+	struct stat stbuf;
+
+	normsg("opening UBI image file %s...", file);
+	fd = open(file, O_RDONLY);
+	if (fd < 0) {
+		errmsg("Unable to open %s: %m", file);
+		err = -1;
+		goto out;
+	}
+
+	memset(&stbuf, 0, sizeof(stbuf));
+	if (fstat(fd, &stbuf) != 0) {
+		errmsg("Unable to stat %s: %m", file);
+		close(fd);
+		err = -1;
+		goto out;
+	}
+	ctx->flash_size = stbuf.st_size;
+	if (ctx->flash_size % ctx->peb_size) {
+		errmsg("Image size is not a multiple of PEB size %u", ctx->peb_size);
+		close(fd);
+		err = -1;
+		goto out;
+	}
+
+	if (ctx->mode == EMUBI_MODE_MMAP) {
+		ctx->flash_mmap = mmap(NULL, ctx->flash_size, PROT_READ, MAP_PRIVATE, fd, 0);
+		if (ctx->flash_mmap == MAP_FAILED) {
+			errmsg("Unable to mmap %s: %m. Falling back to file mode", file);
+			ctx->flash_mmap = NULL;
+			ctx->mode = EMUBI_MODE_FILE;
+		} else {
+			/* we won't need that anymore */
+			close(fd);
+		}
+	}
+
+	if (ctx->mode == EMUBI_MODE_FILE) {
+		ctx->flash_mmap = NULL;
+		ctx->flash_fd = fd;
+	}
+
+	ctx->eba = NULL;
+	ctx->peb_count = ctx->flash_size / ctx->peb_size;
+	ctx->ff_peb = xmalloc(ctx->peb_size);
+	memset(ctx->ff_peb, 0xFF, ctx->peb_size);
+
+	err = 0;
+out:
+	return err;
+}
diff --git a/ubifs-utils/lib/io.c b/ubifs-utils/lib/io.c
index c2e0d63..778117f 100644
--- a/ubifs-utils/lib/io.c
+++ b/ubifs-utils/lib/io.c
@@ -1,3 +1,33 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation.
+ * Copyright (C) 2008 University of Szeged, Hungary
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Adrian Hunter
+ *          Artem Bityutskiy
+ *          Zoltan Sogor
+ */
+/*
+ * Modifications for mtd-utils.
+ *
+ * Copyright (C) 2015 sigma star gmbh
+ *
+ * Authors: Richard Weinberger
+ *          David Gstir
+ */
+
 #include "io.h"
 #define PROGRAM_NAME "ubifs-io"
 #include <common.h>
@@ -150,3 +180,33 @@ int ubifs_read(loff_t offset, int len, void *buf)
 
 	return 0;
 }
+
+
+/*
+ * ubifs_leb_read - read LEB data
+ * @c: ubifs context
+ * @lnum: LEB number
+ * @buf: output buffer
+ * @offs: offset in LEB
+ * @len: length of data to read
+ */
+
+int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
+		   int len)
+{
+	int seek_offs;
+
+	if (c->emubi) {
+		emubi_leb_read(c->emubi, lnum, offs, buf, len);
+	} else {
+		seek_offs = (lnum * c->leb_size) + offs;
+		if (lseek(out_fd, seek_offs, SEEK_SET) != seek_offs)
+			return sys_err_msg("lseek failed seeking %d", seek_offs);
+
+		if (read(out_fd, buf, len) != len)
+			return sys_err_msg("read failed reading %d bytes at pos %d",
+					   len, seek_offs);
+	}
+
+	return 0;
+}
diff --git a/ubifs-utils/lib/scan.c b/ubifs-utils/lib/scan.c
index 3c5be2c..87a9415 100644
--- a/ubifs-utils/lib/scan.c
+++ b/ubifs-utils/lib/scan.c
@@ -131,7 +131,7 @@ struct ubifs_scan_leb *ubifs_start_scan(const struct ubifs_info *c, int lnum,
 	INIT_LIST_HEAD(&sleb->nodes);
 	sleb->buf = sbuf;
 
-	err = ubifs_read(lnum * c->leb_size + offs, c->leb_size - offs, sbuf + offs);
+	err = ubifs_leb_read(c, lnum, sbuf + offs, offs, c->leb_size - offs);
 	if (err && err != -EBADMSG) {
 		kfree(sleb);
 		return ERR_PTR(err);
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 38/38] UBIFS: introduce ubifs_unpacker tool.
  2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
                   ` (36 preceding siblings ...)
  2015-12-21  8:42 ` [PATCH 37/38] ubifs: add emubi, a minimal UBI emulation layer Dongsheng Yang
@ 2015-12-21  8:42 ` Dongsheng Yang
  37 siblings, 0 replies; 39+ messages in thread
From: Dongsheng Yang @ 2015-12-21  8:42 UTC (permalink / raw)
  To: computersforpeace, richard, david; +Cc: linux-mtd, Dongsheng Yang

From: David Gstir <david@sigma-star.at>

ubifs_unpack allows unpacking of ubifs volumes. Input can be either a image
file created from nanddump or a ubi volume.

ubifs_unpack also performs necessary sanity checks and prints a detailed report
of the FS-state.

Signed-off-by: David Gstir <david@sigma-star.at>
Signed-off-by: Richard Weinberger <richard@nod.at>
Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
---
 Makefile                                |   7 +-
 ubifs-utils/include/emubi.h             |   1 +
 ubifs-utils/include/list_sort.h         |  11 +
 ubifs-utils/include/ubifs.h             |  34 ++
 ubifs-utils/lib/emubi.c                 |  20 +
 ubifs-utils/lib/list_sort.c             | 157 ++++++
 ubifs-utils/ubifs_unpack/index.c        | 648 ++++++++++++++++++++++++
 ubifs-utils/ubifs_unpack/replay.c       | 865 ++++++++++++++++++++++++++++++++
 ubifs-utils/ubifs_unpack/ubifs_unpack.c | 619 +++++++++++++++++++++++
 ubifs-utils/ubifs_unpack/ubifs_unpack.h | 107 ++++
 10 files changed, 2468 insertions(+), 1 deletion(-)
 create mode 100644 ubifs-utils/include/list_sort.h
 create mode 100644 ubifs-utils/lib/list_sort.c
 create mode 100644 ubifs-utils/ubifs_unpack/index.c
 create mode 100644 ubifs-utils/ubifs_unpack/replay.c
 create mode 100644 ubifs-utils/ubifs_unpack/ubifs_unpack.c
 create mode 100644 ubifs-utils/ubifs_unpack/ubifs_unpack.h

diff --git a/Makefile b/Makefile
index 1486791..bcf65fa 100644
--- a/Makefile
+++ b/Makefile
@@ -26,7 +26,8 @@ UBI_BINS = \
 	ubidetach ubinize ubiformat ubirename mtdinfo ubirsvol ubiblock
 UBIFS_BINS = \
 	mkfs.ubifs/mkfs.ubifs \
-	ubifs_dump/ubifs_dump
+	ubifs_dump/ubifs_dump \
+	ubifs_unpack/ubifs_unpack
 JFFSX_BINS = \
 	mkfs.jffs2 sumtool jffs2reader jffs2dump
 NAND_BINS = \
@@ -135,6 +136,10 @@ LDFLAGS_ubifs_dump = $(ZLIBLDFLAGS) $(LZOLDFLAGS) $(UUIDLDFLAGS)
 LDLIBS_ubifs_dump = -lz -llzo2 -lm -luuid
 $(call mkdep,ubifs-utils/ubifs_dump/,ubifs_dump,,ubi-utils/libubi.a)
 
+obj-ubifs_unpack = $(UBIFS_LIBS) ../lib/list_sort.o ../lib/scan.o ../lib/lpt.o ../lib/master.o ../../lib/libcrc32.o replay.o index.o
+LDFLAGS_ubifs_unpack = $(ZLIBLDFLAGS) $(LZOLDFLAGS) $(UUIDLDFLAGS) -lz -llzo2
+$(call mkdep,ubifs-utils/ubifs_unpack/,ubifs_unpack,,ubi-utils/libubi.a)
+
 obj-mkfs.ubifs = $(UBIFS_LIBS)
 LDFLAGS_mkfs.ubifs = $(ZLIBLDFLAGS) $(LZOLDFLAGS) $(UUIDLDFLAGS)
 LDLIBS_mkfs.ubifs = -lz $(LZOLDLIBS) -lm -luuid
diff --git a/ubifs-utils/include/emubi.h b/ubifs-utils/include/emubi.h
index e06ba7d..a2883ce 100644
--- a/ubifs-utils/include/emubi.h
+++ b/ubifs-utils/include/emubi.h
@@ -73,6 +73,7 @@ struct emubi_ctx {
 };
 
 void emubi_print(struct emubi_ctx *ctx);
+void emubi_close(struct emubi_ctx *ctx);
 int emubi_scan(struct emubi_ctx *ctx);
 int emubi_open(struct emubi_ctx *ctx, char *file);
 int emubi_leb_read(struct emubi_ctx *ctx, unsigned int lnum, unsigned int offset,
diff --git a/ubifs-utils/include/list_sort.h b/ubifs-utils/include/list_sort.h
new file mode 100644
index 0000000..35afa54
--- /dev/null
+++ b/ubifs-utils/include/list_sort.h
@@ -0,0 +1,11 @@
+#ifndef _LINUX_LIST_SORT_H
+#define _LINUX_LIST_SORT_H
+
+#include "list.h"
+
+struct list_head;
+
+void list_sort(void *priv, struct list_head *head,
+              int (*cmp)(void *priv, struct list_head *a,
+                         struct list_head *b));
+#endif
diff --git a/ubifs-utils/include/ubifs.h b/ubifs-utils/include/ubifs.h
index f03601d..a12d71e 100644
--- a/ubifs-utils/include/ubifs.h
+++ b/ubifs-utils/include/ubifs.h
@@ -52,6 +52,9 @@
 /* Largest key size supported in this implementation */
 #define CUR_MAX_KEY_LEN UBIFS_SK_LEN
 
+/* Maximum possible inode number (only 32-bit inodes are supported now) */
+#define MAX_INUM 0xFFFFFFFF
+
 #define NONDATA_JHEADS_CNT 2
 /*
  * There is no notion of truncation key because truncation nodes do not exist
@@ -340,6 +343,8 @@ enum {
  * @old_idx_sz: size of index on flash
  * @lst: lprops statistics
  *
+ * @max_inode_sz: maximum possible inode size in bytes
+ *
  * @dead_wm: LEB dead space watermark
  * @dark_wm: LEB dark space watermark
  *
@@ -381,6 +386,11 @@ enum {
  * @lsave_offs: offset of LPT's save table
  * @lsave: LPT's save table
  * @lscan_lnum: LEB number of last LPT scan
+ *
+ * @replay_list: temporary list used during journal replay
+ * @replay_buds: list of buds to replay
+ * @cs_sqnum: sequence number of first node in the log (commit start node)
+ *
  * @emubi: emubi context for working with image files
  * @verbose: verbose mode enabled
  */
@@ -424,6 +434,8 @@ struct ubifs_info
 	unsigned long long old_idx_sz;
 	struct ubifs_lp_stats lst;
 
+	long long max_inode_sz;
+
 	int dead_wm;
 	int dark_wm;
 
@@ -474,6 +486,11 @@ struct ubifs_info
 	int max_idx_node_sz;
 
 	int max_znode_sz;
+
+	struct list_head replay_list;
+	struct list_head replay_buds;
+	unsigned long long cs_sqnum;
+
 	struct emubi_ctx *emubi;
 	int verbose;
 };
@@ -556,6 +573,23 @@ struct ubifs_branch *ubifs_idx_branch(const struct ubifs_info *c,
 				       (UBIFS_BRANCH_SZ + c->key_len) * bnum);
 }
 
+/**
+ * ubifs_next_log_lnum - switch to the next log LEB.
+ * @c: UBIFS file-system description object
+ * @lnum: current log LEB
+ *
+ * This helper function returns the log LEB number which goes next after LEB
+ * 'lnum'.
+ */
+static inline int ubifs_next_log_lnum(const struct ubifs_info *c, int lnum)
+{
+       lnum += 1;
+       if (lnum > UBIFS_LOG_LNUM + c->log_lebs - 1)
+               lnum = UBIFS_LOG_LNUM;
+
+       return lnum;
+}
+
 /* Callback used by the 'ubifs_lpt_scan_nolock()' function */
 typedef int (*ubifs_lpt_scan_callback)(struct ubifs_info *c,
 				       const struct ubifs_lprops *lprops,
diff --git a/ubifs-utils/lib/emubi.c b/ubifs-utils/lib/emubi.c
index 1c88eea..b4bf896 100644
--- a/ubifs-utils/lib/emubi.c
+++ b/ubifs-utils/lib/emubi.c
@@ -225,6 +225,26 @@ void emubi_print(struct emubi_ctx *ctx)
 	printf("\n\temubi mode: %s\n", (ctx->mode == EMUBI_MODE_MMAP) ? "mmap" : "file");
 }
 
+static void destroy_scan_lebs(struct list_head *scan_lebs)
+{
+       struct ubi_scan_leb *sleb, *ltmp;
+
+       if (!list_empty(scan_lebs)) {
+               list_for_each_entry_safe(sleb, ltmp, scan_lebs, l) {
+                       list_del(&sleb->l);
+                       free(sleb);
+               }
+       }
+
+}
+
+void emubi_close(struct emubi_ctx *ctx)
+{
+       free(ctx->eba);
+       free(ctx->ff_peb);
+       destroy_scan_lebs(&ctx->scan_lebs);
+}
+
 static int is_empty(struct emubi_ctx *ctx, char *pbuf, size_t len)
 {
 	return memcmp(pbuf, ctx->ff_peb, len) == 0;
diff --git a/ubifs-utils/lib/list_sort.c b/ubifs-utils/lib/list_sort.c
new file mode 100644
index 0000000..843d796
--- /dev/null
+++ b/ubifs-utils/lib/list_sort.c
@@ -0,0 +1,157 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+#define PROGRAM_NAME "list_sort"
+
+#include "list_sort.h"
+#include "common.h"
+#include "defs.h"
+
+#define MAX_LIST_LENGTH_BITS 20
+
+/*
+ * Returns a list organized in an intermediate format suited
+ * to chaining of merge() calls: null-terminated, no reserved or
+ * sentinel head node, "prev" links not maintained.
+ */
+static struct list_head *merge(void *priv,
+                               int (*cmp)(void *priv, struct list_head *a,
+                                       struct list_head *b),
+                               struct list_head *a, struct list_head *b)
+{
+       struct list_head head, *tail = &head;
+
+       while (a && b) {
+               /* if equal, take 'a' -- important for sort stability */
+               if ((*cmp)(priv, a, b) <= 0) {
+                       tail->next = a;
+                       a = a->next;
+               } else {
+                       tail->next = b;
+                       b = b->next;
+               }
+               tail = tail->next;
+       }
+       tail->next = a?:b;
+       return head.next;
+}
+
+/*
+ * Combine final list merge with restoration of standard doubly-linked
+ * list structure.  This approach duplicates code from merge(), but
+ * runs faster than the tidier alternatives of either a separate final
+ * prev-link restoration pass, or maintaining the prev links
+ * throughout.
+ */
+static void merge_and_restore_back_links(void *priv,
+                               int (*cmp)(void *priv, struct list_head *a,
+                                       struct list_head *b),
+                               struct list_head *head,
+                               struct list_head *a, struct list_head *b)
+{
+       struct list_head *tail = head;
+       u8 count = 0;
+
+       while (a && b) {
+               /* if equal, take 'a' -- important for sort stability */
+               if ((*cmp)(priv, a, b) <= 0) {
+                       tail->next = a;
+                       a->prev = tail;
+                       a = a->next;
+               } else {
+                       tail->next = b;
+                       b->prev = tail;
+                       b = b->next;
+               }
+               tail = tail->next;
+       }
+       tail->next = a ? : b;
+
+       do {
+               /*
+                * In worst cases this loop may run many iterations.
+                * Continue callbacks to the client even though no
+                * element comparison is needed, so the client's cmp()
+                * routine can invoke cond_resched() periodically.
+                */
+               if (unlikely(!(++count)))
+                       (*cmp)(priv, tail->next, tail->next);
+
+               tail->next->prev = tail;
+               tail = tail->next;
+       } while (tail->next);
+
+       tail->next = head;
+       head->prev = tail;
+}
+
+/**
+ * list_sort - sort a list
+ * @priv: private data, opaque to list_sort(), passed to @cmp
+ * @head: the list to sort
+ * @cmp: the elements comparison function
+ *
+ * This function implements "merge sort", which has O(nlog(n))
+ * complexity.
+ *
+ * The comparison function @cmp must return a negative value if @a
+ * should sort before @b, and a positive value if @a should sort after
+ * @b. If @a and @b are equivalent, and their original relative
+ * ordering is to be preserved, @cmp must return 0.
+ */
+void list_sort(void *priv, struct list_head *head,
+               int (*cmp)(void *priv, struct list_head *a,
+                       struct list_head *b))
+{
+       struct list_head *part[MAX_LIST_LENGTH_BITS+1]; /* sorted partial lists
+                                               -- last slot is a sentinel */
+       int lev;  /* index into part[] */
+       int max_lev = 0;
+       struct list_head *list;
+
+       if (list_empty(head))
+               return;
+
+       memset(part, 0, sizeof(part));
+
+       head->prev->next = NULL;
+       list = head->next;
+
+       while (list) {
+               struct list_head *cur = list;
+               list = list->next;
+               cur->next = NULL;
+
+               for (lev = 0; part[lev]; lev++) {
+                       cur = merge(priv, cmp, part[lev], cur);
+                       part[lev] = NULL;
+               }
+               if (lev > max_lev) {
+                       if (lev >= ARRAY_SIZE(part)-1) {
+                               printf("list too long for efficiency\n");
+                               lev--;
+                       }
+                       max_lev = lev;
+               }
+               part[lev] = cur;
+       }
+
+       for (lev = 0; lev < max_lev; lev++)
+               if (part[lev])
+                       list = merge(priv, cmp, part[lev], list);
+
+       merge_and_restore_back_links(priv, cmp, head, part[max_lev], list);
+}
diff --git a/ubifs-utils/ubifs_unpack/index.c b/ubifs-utils/ubifs_unpack/index.c
new file mode 100644
index 0000000..e60e32f
--- /dev/null
+++ b/ubifs-utils/ubifs_unpack/index.c
@@ -0,0 +1,648 @@
+/*
+ * Copyright (C) 2015 sigma star gmbh
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Richard Weinberger
+ *          David Gstir
+ */
+
+#define PROGRAM_NAME "index"
+
+#include "ubifs_unpack.h"
+
+
+struct ubifs_ino_list {
+	ino_t ino;
+	struct list_head *start;
+	struct list_head l;
+};
+
+static LIST_HEAD(leaf_index);
+static LIST_HEAD(ino_index);
+
+
+static void get_key(struct ubifs_branch *zbr, union ubifs_key *key)
+{
+	union ubifs_key *tmp_key;
+
+	tmp_key = (union ubifs_key *)zbr->key;
+	key->u32[0] = le32toh(tmp_key->j32[0]);
+	key->u32[1] = le32toh(tmp_key->j32[1]);
+}
+
+static void index_add_leaf(union ubifs_key *key, unsigned int lnum,
+			   unsigned int offs, unsigned int len)
+{
+	struct ubifs_leaf *ul = xmalloc(sizeof(*ul));
+	struct ubifs_leaf *last_ul = NULL;
+
+	if (!list_empty(&leaf_index))
+		last_ul = list_last_entry(&leaf_index, struct ubifs_leaf, l);
+
+	ul->lnum = lnum;
+	ul->offs = offs;
+	ul->len = len;
+	key_copy(key, &ul->key);
+
+	if (!last_ul || key->u32[0] != last_ul->key.u32[0]) {
+		struct ubifs_ino_list *uil = xmalloc(sizeof(*uil));
+		uil->ino = key_inum(key);
+		uil->start = leaf_index.prev;
+
+
+		list_add_tail(&uil->l, &ino_index);
+	}
+
+	list_add_tail(&ul->l, &leaf_index);
+}
+
+/*
+ * ubifs_destroy_index - Cleanup index
+ * @c: ubifs context
+ */
+void ubifs_destroy_index()
+{
+	struct ubifs_leaf *leaf, *ltmp;
+	struct ubifs_ino_list *uil, *itmp;
+
+	if (!list_empty(&leaf_index)) {
+		list_for_each_entry_safe(leaf, ltmp, &leaf_index, l) {
+			list_del(&leaf->l);
+			free(leaf);
+		}
+	}
+
+	if (!list_empty(&ino_index)) {
+		list_for_each_entry_safe(uil, itmp, &ino_index, l) {
+			list_del(&uil->l);
+			free(uil);
+		}
+	}
+}
+
+/*
+ * ubifs_load_index - Load full index from media
+ * @c: ubifs context
+ * @lnum: LEB where index node is located
+ * @offs: offset in LEB
+ * @len: len if index node
+ */
+void ubifs_load_index(struct ubifs_info *c, unsigned int lnum,
+		      unsigned int offs, unsigned int len)
+{
+	struct ubifs_idx_node *idx;
+	union ubifs_key tmp_key;
+	struct ubifs_ch ch;
+	unsigned int i;
+
+	idx = xmalloc(len);
+	get_idx_node(c, idx, lnum, offs, len);
+
+	for (i = 0; i < le16toh(idx->child_cnt); i++) {
+		struct ubifs_branch *br = get_branch(idx, i);
+		unsigned int br_lnum = le32toh(br->lnum);
+		unsigned int br_offs = le32toh(br->offs);
+		unsigned int br_len = le32toh(br->len);
+
+		if (le16toh(idx->level) == 0) {
+			get_key(br, &tmp_key);
+			index_add_leaf(&tmp_key, br_lnum, br_offs, br_len);
+		}
+
+		ubifs_leb_read(c, br_lnum, &ch, br_offs, sizeof(ch));
+		if (ch.node_type == UBIFS_IDX_NODE)
+			ubifs_load_index(c, br_lnum, br_offs, br_len);
+	}
+
+	free(idx);
+}
+
+static struct ubifs_ino_list *lookup_ino_list(ino_t ino)
+{
+	struct ubifs_ino_list *uil;
+
+	list_for_each_entry(uil, &ino_index, l) {
+		if (uil->ino == ino)
+			return uil;
+	}
+
+	return NULL;
+}
+
+static struct ubifs_leaf *lookup_leaf(union ubifs_key *key, int *exact)
+{
+	struct ubifs_leaf *ul, *prev_ul = NULL;
+	struct list_head *start = NULL;
+	struct ubifs_ino_list *uil;
+	int res;
+
+	*exact = 0;
+
+	uil = lookup_ino_list(key_inum(key));
+	if (!uil)
+		return NULL;
+
+	start = uil->start;
+	assert(start);
+
+	list_for_each_entry(ul, start, l) {
+		res = keys_cmp(&ul->key, key);
+		if (res == 0) {
+			*exact = 1;
+			return ul;
+		}
+
+		if (res > 0) {
+			if (is_hash_key(key))
+				return prev_ul;
+			else
+				return NULL;
+		}
+
+		prev_ul = ul;
+	}
+
+	return NULL;
+}
+
+/*
+ * ubifs_lookup_ino_node - find INO node
+ * @c: ubifs context
+ * @ino: inode number
+ *
+ * Returns pointer to found ubifs_ino_node or NULL, if node was not found.
+ */
+struct ubifs_ino_node *ubifs_lookup_ino_node(struct ubifs_info *c, ino_t ino)
+{
+	struct ubifs_ino_node *i;
+	struct ubifs_leaf *leaf;
+	union ubifs_key key;
+	int exact;
+
+	ino_key_init(&key, ino);
+
+	leaf = lookup_leaf(&key, &exact);
+	if (!leaf || !exact)
+		return NULL;
+
+	i = xmalloc(leaf->len);
+	get_ino_node(c, i, leaf->lnum, leaf->offs, leaf->len);
+
+	return i;
+}
+
+/*
+ * ubifs_lookup_data_node - find DATA node
+ * @c: ubifs context
+ * @ino: inode number
+ * @block: block number
+ *
+ * Returns pointer to found ubifs_data_node or NULL, if node was not found.
+ */
+struct ubifs_data_node *ubifs_lookup_data_node(struct ubifs_info *c, ino_t ino,
+					       unsigned int block)
+{
+	struct ubifs_data_node *d;
+	struct ubifs_leaf *leaf;
+	union ubifs_key key;
+	int exact;
+
+	data_key_init(&key, ino, block);
+
+	leaf = lookup_leaf(&key, &exact);
+	if (!leaf || !exact)
+		return NULL;
+
+	d = xmalloc(leaf->len);
+	get_data_node(c, d, leaf->lnum, leaf->offs, leaf->len);
+
+	return d;
+}
+
+/*
+ * ubifs_next_leaf - Find the next leaf node after @ul which belongs to @ino.
+ * @ul: current leaf
+ * @ino: ino of current leaf
+ *
+ * If the end is reached, NULL is returned.
+ * If @ul is NULL, the first leaf node matching @ino is returned.
+ */
+struct ubifs_leaf *ubifs_next_leaf(struct ubifs_leaf *ul, ino_t ino)
+{
+	struct ubifs_leaf *next = NULL;
+	struct ubifs_ino_list *uil;
+
+	if (ul) {
+		next = list_next_entry(ul, l);
+		if (key_inum(&next->key) != ino)
+			next = NULL;
+	} else {
+		/* we don't have a leaf yet, so find the first */
+		uil = lookup_ino_list(ino);
+		if (uil && uil->start)
+			next = list_first_entry(uil->start, struct ubifs_leaf, l);
+	}
+
+	return next;
+}
+
+/*
+ * match_name - Compare @nm with name of node @leaf.
+ * @c: ubifs context
+ * @leaf: leaf node which name we want to match. It must use a hash key
+ * @nm: required name to match on
+ *
+ * This helps to resolve collisions for hash keys where duplicate keys are
+ * possible.
+ * Returns %-1 on error, %0 on full match and %1 on no match.
+ */
+static int match_name(struct ubifs_info *c, struct ubifs_leaf *leaf,
+		      struct qstr *nm)
+{
+	int len, ret;
+	struct ubifs_dent_node *dent;
+	assert(is_hash_key(&leaf->key));
+
+	if (!nm->name)
+		return -1;
+
+	dent = xmalloc(leaf->len);
+	get_dent_node(c, dent, leaf->lnum, leaf->offs, leaf->len);
+
+	len = (nm->len > le16toh(dent->nlen)) ? nm->len : dent->nlen;
+	ret = (memcmp(nm->name, dent->name, len) == 0) ? 0 : 1;
+
+	free(dent);
+
+	return ret;
+}
+
+/*
+ * index_remove_leaf - Safely remove a leaf from the skip list
+ * @leaf: the leaf to remove
+ * @uil: the ino_list entry. If NULL, will be search.
+ *
+ * Updates and removes ino_list entries accordingly.
+ * Returns %0 on success, %1 when last leaf was removed successfully and a
+ * value < 0 on error
+ */
+static int index_remove_leaf(struct ubifs_leaf *leaf, struct ubifs_ino_list *uil)
+{
+	struct ubifs_ino_list *next_uil;
+
+	if (!uil)
+		uil = lookup_ino_list(key_inum(&leaf->key));
+
+	if (!uil)
+		return -ENOENT;
+
+	/* fix ->start of next ino_list if we remove last node for this ino */
+	if (!list_is_last(&uil->l, &ino_index)) {
+		next_uil = list_next_entry(uil, l);
+		if (next_uil->start == &leaf->l)
+			next_uil->start = leaf->l.prev;
+	}
+
+	list_del(&leaf->l);
+	free(leaf);
+
+	/* if this was the last leaf, remove ino_list entry too */
+	leaf = list_first_entry(uil->start, struct ubifs_leaf, l);
+	if (key_inum(&leaf->key) != uil->ino) {
+		list_del(&uil->l);
+		free(uil);
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * ubifs_remove_inode - Remove all nodes for @ino from index
+ * @c: ubifs context
+ * @ino: the inode number to remove
+ *
+ * Returns %0 on success or when @ino was not found, %-1 on error
+ */
+int ubifs_remove_inode(struct ubifs_info *c, ino_t ino)
+{
+	struct ubifs_ino_list *uil;
+	struct ubifs_leaf *ul;
+	int err = 0;
+
+	verbose(c->verbose, "remove all nodes of ino %lu", ino);
+
+	uil = lookup_ino_list(ino);
+	if (!uil)
+		goto out;
+
+	/* remove all leafs of this inode */
+	ul = list_first_entry(uil->start, struct ubifs_leaf, l);
+	while (key_inum(&ul->key) == ino) {
+		err = index_remove_leaf(ul, uil);
+		if (err) {
+			if (err == 1)
+				/* last entry was removed, we're done */
+				err = 0;
+			goto out;
+		}
+
+		ul = list_first_entry(uil->start, struct ubifs_leaf, l);
+	}
+
+out:
+	return err;
+}
+
+/*
+ * ubifs_remove_node_nm - Remove node with @key from index
+ * @c: ubifs context
+ * @key: the key of the node to remove
+ * @nm: when @key is a hash key, this file name is used to resolve collisions
+ *
+ * Returns %0 on success or when no matching node can be found in the index.
+ */
+int ubifs_remove_node_nm(struct ubifs_info *c, union ubifs_key *key,
+			 struct qstr *nm)
+{
+	ino_t ino;
+	struct ubifs_leaf *ul = NULL;
+	int match = -1, err = 0;
+
+	assert(c);
+	assert(key);
+	assert(nm);
+
+	ino = key_inum(key);
+	verbose(c->verbose, "remove node 0x%lx (ino %lu, type %d blk/hash %d, hash_key %d name %s)",
+		key->u64[0], ino, key_type(key), key_block(key), is_hash_key(key), nm->name);
+
+	while ((ul = ubifs_next_leaf(ul, ino))) {
+		match = keys_cmp(&ul->key, key);
+
+		/* no need to search further */
+		if (match > 0) {
+			normsg("ignoring remove of non-existant leaf from index (ino %lu)", ino);
+			break;
+		}
+
+		if (is_hash_key(key) && match == 0) {
+			match = match_name(c, ul, nm);
+			if (match < 0) {
+				err = match;
+				errmsg("name matching failed for key 0x%lx", key->u64[0]);
+				goto out;
+			}
+		}
+
+		if (match == 0) {
+			err = index_remove_leaf(ul, NULL);
+			if (err < 0)
+				errmsg("failed to remove leaf (ino %lu type %d)", ino, key_type(key));
+			/* there can only be a single match */
+			break;
+		}
+	}
+
+out:
+	return err;
+}
+
+/*
+ * ubifs_remove_node - Remove node with @key from index
+ * @c: ubifs context
+ * @key: key of node to remove
+ *
+ * This equivalent to ubifs_remove_node_nm() however, it can only be used for
+ * keys which will never collide.
+ */
+int ubifs_remove_node(struct ubifs_info *c, union ubifs_key *key)
+{
+	struct qstr empty = { .name = NULL };
+
+	if (!is_hash_key(key)) {
+		errmsg("requested key is not hash key!\n");
+		return -EINVAL;
+	}
+
+	return ubifs_remove_node_nm(c, key, &empty);
+}
+
+/**
+ * key_in_range - determine if a key falls within a range of keys.
+ * @key: key to check
+ * @from_key: lowest key in range
+ * @to_key: highest key in range
+ *
+ * This function returns %1 if the key is in range and %0 otherwise.
+ */
+static int key_in_range(union ubifs_key *key, union ubifs_key *from_key,
+			union ubifs_key *to_key)
+{
+	if (keys_cmp(key, from_key) < 0)
+		return 0;
+	if (keys_cmp(key, to_key) > 0)
+		return 0;
+	return 1;
+}
+
+/*
+ * ubifs_remove_node_range - Remove all nodes within the given key range
+ * @c: ubifs context
+ * @from_key: first key in range (min)
+ * @to_key: last key in range to remove (max)
+ *
+ * The keys must be for the same inode. No hash keys are supported.
+ */
+int ubifs_remove_node_range(struct ubifs_info *c, union ubifs_key *from_key,
+			    union ubifs_key *to_key)
+{
+	ino_t ino;
+	struct ubifs_ino_list *uil;
+	struct ubifs_leaf *ul, *rm_ul;
+	int err = 0;
+
+	ino = key_inum(from_key);
+	verbose(c->verbose, "remove node range for ino %lu type %d blk %d - %d",
+		ino, key_type(from_key), key_block(from_key), key_block(to_key));
+
+	uil = lookup_ino_list(ino);
+	if (!uil)
+		goto out;
+
+	ul = list_first_entry(uil->start, struct ubifs_leaf, l);
+	while (key_inum(&ul->key) == ino) {
+		rm_ul = ul;
+		ul = list_next_entry(ul, l);
+		if (key_in_range(&rm_ul->key, from_key, to_key)) {
+			err = index_remove_leaf(rm_ul, uil);
+			if (err) {
+				if (err == 1)
+					/* last entry was removed, we're done */
+					err = 0;
+				goto out;
+			}
+		}
+	}
+
+out:
+	return err;
+}
+
+static void index_insert_ino(struct ubifs_ino_list *uil)
+{
+	struct ubifs_ino_list *i;
+
+	list_for_each_entry(i, &ino_index, l) {
+		if (i->ino > uil->ino)
+			break;
+	}
+
+	if (&i->l != &ino_index) {
+		list_add_tail(&uil->l, &i->l);
+		uil->start = i->start;
+	} else {
+		list_add_tail(&uil->l, &ino_index);
+		uil->start = leaf_index.prev;
+	}
+}
+
+/*
+ * index_insert_leaf - Insert new leaf at correct position in sorted leaf list
+ * @c: ubifs context
+ * @key: key to insert
+ * @lnum: LEB number of new node
+ * @offs: offset in LEB @lnum
+ * @len: length of new node
+ * @nm: file name to resolve key collisions
+ *
+ * In case a corresponding leaf with the same key already exists, this leaf is
+ * just updated and no new leaf is created.
+ * Retruns %0 on succces, or a value < 0 on error.
+ */
+static int index_insert_leaf(struct ubifs_info *c,union ubifs_key *key,
+			     unsigned int lnum, unsigned int offs, unsigned int len,
+			     struct qstr *nm)
+{
+	int match, err, new_ino = 0;
+	ino_t ino = key_inum(key);
+	struct ubifs_ino_list *uil;
+	struct ubifs_leaf *leaf, *ul = NULL;
+	struct list_head *prev;
+
+	verbose(c->verbose, "add replay inode %lu on LEB %d:%d type %d", ino, lnum, offs, key_type(key));
+
+	uil = lookup_ino_list(ino);
+	if (!uil) {
+		uil = xcalloc(1, sizeof(*uil));
+		uil->ino = ino;
+		new_ino = 1;
+		goto insert;
+	}
+
+	/* find position in leaf list */
+	assert(uil->start);
+	prev = uil->start;
+	ul = list_first_entry(uil->start, struct ubifs_leaf, l);
+	do {
+		match = keys_cmp(&ul->key, key);
+
+		/* for hash keys with colliding key values, we insert the new
+		 * leaf right after the colliding ones */
+		if (match > 0)
+			break;
+
+		/* we have a collision, so check the name to
+		 * ensure this is the node we want */
+		if (is_hash_key(key) && match == 0) {
+			match = match_name(c, ul, nm);
+			if (match < 0) {
+				err = match;
+				goto out;
+			}
+		}
+
+		/* just update the existing leaf */
+		if (match == 0) {
+			ul->lnum = lnum;
+			ul->offs = offs;
+			ul->len = len;
+			err = 0;
+			goto out;
+		}
+
+		prev = &ul->l;
+		ul = ubifs_next_leaf(ul, ino);
+	} while (ul);
+
+insert:
+	leaf = xmalloc(sizeof(*leaf));
+	leaf->lnum = lnum;
+	leaf->offs = offs;
+	leaf->len = len;
+	key_copy(key, &leaf->key);
+
+	if (new_ino) {
+		index_insert_ino(uil);
+		prev = uil->start;
+	}
+
+	list_add(&leaf->l, prev);
+
+	/* move skip pointer of next ino when appending to last leaf of ino
+	 * list */
+	if (!ul && !list_is_last(&uil->l, &ino_index)) {
+		uil = list_next_entry(uil, l);
+		uil->start = &leaf->l;
+	}
+	err = 0;
+out:
+	return err;
+}
+
+/*
+ * ubifs_add_node - Add new node to index
+ * @c: ubifs context
+ * @key: key of new node
+ * @lnum: LEB where node is located
+ * @off: offset in LEB where new node starts
+ * @len: length of new node
+ *
+ * This only works for non-hash keys.
+ * Returns %0 on success, or a value < 0 on error.
+ */
+int ubifs_add_node(struct ubifs_info *c, union ubifs_key *key, int lnum,
+		   int offs, unsigned int len)
+{
+	struct qstr empty = { .name = NULL };
+	return index_insert_leaf(c, key, lnum, offs, len, &empty);
+}
+
+/*
+ * ubifs_add_node_nm - Add new node to index with collision resolution
+ * @c: ubifs context
+ * @key: key of new node
+ * @lnum: LEB where new node is located
+ * @offs: offset in LEB where node starts
+ * @len: length of new node
+ * @nm: file name used to resolve collision
+ *
+ * Returns %0 on success, or a value < 0 on error.
+ */
+int ubifs_add_node_nm(struct ubifs_info *c, union ubifs_key *key, int lnum,
+		      int offs, unsigned int len, struct qstr *nm)
+{
+	return index_insert_leaf(c, key, lnum, offs, len, nm);
+}
diff --git a/ubifs-utils/ubifs_unpack/replay.c b/ubifs-utils/ubifs_unpack/replay.c
new file mode 100644
index 0000000..a5fbce9
--- /dev/null
+++ b/ubifs-utils/ubifs_unpack/replay.c
@@ -0,0 +1,865 @@
+/*
+ * This file is a modified copy of fs/ubifs/replay.c from the Linux Kernel UBIFS.
+ *
+ * Copyright (C) 2006-2008 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Adrian Hunter
+ *          Artem Bityutskiy (Битюцкий Артём)
+ */
+/*
+ * Modifications for mtd-utils.
+ *
+ * Copyright (C) 2015 sigma star gmbh
+ *
+ * Authors: Richard Weinberger
+ *          David Gstir
+ */
+
+/*
+ * This file contains journal replay code. It runs when the file-system is being
+ * mounted and requires no locking.
+ *
+ * The larger is the journal, the longer it takes to scan it, so the longer it
+ * takes to mount UBIFS. This is why the journal has limited size which may be
+ * changed depending on the system requirements. But a larger journal gives
+ * faster I/O speed because it writes the index less frequently. So this is a
+ * trade-off. Also, the journal is indexed by the in-memory index (TNC), so the
+ * larger is the journal, the more memory its index may consume.
+ */
+
+#define PROGRAM_NAME "replay"
+
+#include "ubifs_unpack.h"
+#include "key.h"
+#include "list_sort.h"
+
+/**
+ * struct replay_entry - replay list entry.
+ * @lnum: logical eraseblock number of the node
+ * @offs: node offset
+ * @len: node length
+ * @deletion: non-zero if this entry corresponds to a node deletion
+ * @sqnum: node sequence number
+ * @list: links the replay list
+ * @key: node key
+ * @nm: directory entry name
+ * @old_size: truncation old size
+ * @new_size: truncation new size
+ *
+ * The replay process first scans all buds and builds the replay list, then
+ * sorts the replay list in nodes sequence number order, and then inserts all
+ * the replay entries to the TNC.
+ */
+struct replay_entry {
+	int lnum;
+	int offs;
+	int len;
+	unsigned int deletion:1;
+	unsigned long long sqnum;
+	struct list_head list;
+	union ubifs_key key;
+	union {
+		struct qstr nm;
+		struct {
+			loff_t old_size;
+			loff_t new_size;
+		};
+	};
+};
+
+/**
+ * struct ubifs_bud - bud logical eraseblock used for replay.
+ * @lnum: logical eraseblock number
+ * @start: where the (uncommitted) bud data starts
+ * @jhead: journal head number this bud belongs to
+ * @sqnum: reference node sequence number
+ * @list: link in the list buds belonging to the same journal head
+ */
+struct ubifs_bud {
+	int lnum;
+	int start;
+	int jhead;
+	unsigned long long sqnum;
+	struct list_head list;
+};
+
+/**
+ * ubifs_search_bud - search bud LEB.
+ * @c: UBIFS file-system description object
+ * @lnum: logical eraseblock number to search
+ *
+ * This function searches bud LEB @lnum. Returns bud description object in case
+ * of success and %NULL if there is no bud with this LEB number.
+ */
+static struct ubifs_bud *ubifs_search_bud(struct ubifs_info *c, int lnum)
+{
+	struct ubifs_bud *bud;
+
+	list_for_each_entry(bud, &c->replay_buds, list) {
+		if (lnum == bud->lnum)
+			return bud;
+	}
+
+	return NULL;
+}
+/**
+ * trun_remove_range - apply a replay entry for a truncation to the TNC.
+ * @c: UBIFS file-system description object
+ * @r: replay entry of truncation
+ */
+static int trun_remove_range(struct ubifs_info *c, struct replay_entry *r)
+{
+	unsigned min_blk, max_blk;
+	union ubifs_key min_key, max_key;
+	ino_t ino;
+
+	min_blk = r->new_size / UBIFS_BLOCK_SIZE;
+	if (r->new_size & (UBIFS_BLOCK_SIZE - 1))
+		min_blk += 1;
+
+	max_blk = r->old_size / UBIFS_BLOCK_SIZE;
+	if ((r->old_size & (UBIFS_BLOCK_SIZE - 1)) == 0)
+		max_blk -= 1;
+
+	ino = key_inum(&r->key);
+
+	data_key_init(&min_key, ino, min_blk);
+	data_key_init(&max_key, ino, max_blk);
+
+	return ubifs_remove_node_range(c, &min_key, &max_key);
+}
+
+/**
+ * apply_replay_entry - apply a replay entry to the TNC.
+ * @c: UBIFS file-system description object
+ * @r: replay entry to apply
+ *
+ * Apply a replay entry to the TNC.
+ */
+static int apply_replay_entry(struct ubifs_info *c, struct replay_entry *r)
+{
+	int err;
+
+	verbose(c->verbose, "LEB %d:%d len %d deletion %d sqnum %llu key 0x%lx",
+		 r->lnum, r->offs, r->len, r->deletion, r->sqnum, r->key.u64[0]);
+
+	if (is_hash_key(&r->key)) {
+		if (r->deletion)
+			err = ubifs_remove_node_nm(c, &r->key, &r->nm);
+		else
+			err = ubifs_add_node_nm(c, &r->key, r->lnum, r->offs,
+					        r->len, &r->nm);
+	} else {
+		if (r->deletion)
+			switch (key_type(&r->key)) {
+			case UBIFS_INO_KEY:
+			{
+				ino_t inum = key_inum(&r->key);
+
+				err = ubifs_remove_inode(c, inum);
+				break;
+			}
+			case UBIFS_TRUN_KEY:
+				err = trun_remove_range(c, r);
+				break;
+			default:
+				err = ubifs_remove_node(c, &r->key);
+				break;
+			}
+		else
+			err = ubifs_add_node(c, &r->key, r->lnum, r->offs, r->len);
+		if (err)
+			return err;
+	}
+
+	return err;
+}
+
+/**
+ * replay_entries_cmp - compare 2 replay entries.
+ * @priv: UBIFS file-system description object
+ * @a: first replay entry
+ * @a: second replay entry
+ *
+ * This is a comparios function for 'list_sort()' which compares 2 replay
+ * entries @a and @b by comparing their sequence numer.  Returns %1 if @a has
+ * greater sequence number and %-1 otherwise.
+ */
+static int replay_entries_cmp(void *priv __attribute__((unused)),
+			      struct list_head *a, struct list_head *b)
+{
+	struct replay_entry *ra, *rb;
+
+	if (a == b)
+		return 0;
+
+	ra = list_entry(a, struct replay_entry, list);
+	rb = list_entry(b, struct replay_entry, list);
+	ubifs_assert(ra->sqnum != rb->sqnum);
+	if (ra->sqnum > rb->sqnum)
+		return 1;
+	return -1;
+}
+
+/**
+ * apply_replay_list - apply the replay list to the TNC.
+ * @c: UBIFS file-system description object
+ *
+ * Apply all entries in the replay list to the TNC. Returns zero in case of
+ * success and a negative error code in case of failure.
+ */
+static int apply_replay_list(struct ubifs_info *c)
+{
+	struct replay_entry *r;
+	int err;
+
+	list_sort(c, &c->replay_list, &replay_entries_cmp);
+
+	list_for_each_entry(r, &c->replay_list, list) {
+
+		err = apply_replay_entry(c, r);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+/**
+ * destroy_replay_list - destroy the replay.
+ * @c: UBIFS file-system description object
+ *
+ * Destroy the replay list.
+ */
+static void destroy_replay_list(struct ubifs_info *c)
+{
+	struct replay_entry *r, *tmp;
+
+	list_for_each_entry_safe(r, tmp, &c->replay_list, list) {
+		if (is_hash_key(&r->key))
+			kfree(r->nm.name);
+		list_del(&r->list);
+		kfree(r);
+	}
+}
+
+/**
+ * insert_node - insert a node to the replay list
+ * @c: UBIFS file-system description object
+ * @lnum: node logical eraseblock number
+ * @offs: node offset
+ * @len: node length
+ * @key: node key
+ * @sqnum: sequence number
+ * @deletion: non-zero if this is a deletion
+ * @used: number of bytes in use in a LEB
+ * @old_size: truncation old size
+ * @new_size: truncation new size
+ *
+ * This function inserts a scanned non-direntry node to the replay list. The
+ * replay list contains @struct replay_entry elements, and we sort this list in
+ * sequence number order before applying it. The replay list is applied at the
+ * very end of the replay process. Since the list is sorted in sequence number
+ * order, the older modifications are applied first. This function returns zero
+ * in case of success and a negative error code in case of failure.
+ */
+static int insert_node(struct ubifs_info *c, int lnum, int offs, int len,
+		       union ubifs_key *key, unsigned long long sqnum,
+		       int deletion, int *used, loff_t old_size,
+		       loff_t new_size)
+{
+	struct replay_entry *r;
+
+	verbose(c->verbose, "add LEB %d:%d, key 0x%lx", lnum, offs, key->u64[0]);
+
+	if (key_inum(key) >= c->highest_inum)
+		c->highest_inum = key_inum(key);
+
+	r = calloc(1, sizeof(struct replay_entry));
+	if (!r)
+		return -ENOMEM;
+
+	if (!deletion)
+		*used += ALIGN(len, 8);
+	r->lnum = lnum;
+	r->offs = offs;
+	r->len = len;
+	r->deletion = !!deletion;
+	r->sqnum = sqnum;
+	key_copy(key, &r->key);
+	r->old_size = old_size;
+	r->new_size = new_size;
+
+	list_add_tail(&r->list, &c->replay_list);
+	return 0;
+}
+
+/**
+ * insert_dent - insert a directory entry node into the replay list.
+ * @c: UBIFS file-system description object
+ * @lnum: node logical eraseblock number
+ * @offs: node offset
+ * @len: node length
+ * @key: node key
+ * @name: directory entry name
+ * @nlen: directory entry name length
+ * @sqnum: sequence number
+ * @deletion: non-zero if this is a deletion
+ * @used: number of bytes in use in a LEB
+ *
+ * This function inserts a scanned directory entry node or an extended
+ * attribute entry to the replay list. Returns zero in case of success and a
+ * negative error code in case of failure.
+ */
+static int insert_dent(struct ubifs_info *c, int lnum, int offs, int len,
+		       union ubifs_key *key, const char *name, int nlen,
+		       unsigned long long sqnum, int deletion, int *used)
+{
+	struct replay_entry *r;
+	char *nbuf;
+
+	verbose(c->verbose, "add LEB %d:%d, key 0x%lx ", lnum, offs, key->u64[0]);
+	if (key_inum(key) >= c->highest_inum)
+		c->highest_inum = key_inum(key);
+
+	r = calloc(1, sizeof(struct replay_entry));
+	if (!r)
+		return -ENOMEM;
+
+	nbuf = malloc(nlen + 1);
+	if (!nbuf) {
+		free(r);
+		return -ENOMEM;
+	}
+
+	if (!deletion)
+		*used += ALIGN(len, 8);
+	r->lnum = lnum;
+	r->offs = offs;
+	r->len = len;
+	r->deletion = !!deletion;
+	r->sqnum = sqnum;
+	key_copy(key, &r->key);
+	r->nm.len = nlen;
+	memcpy(nbuf, name, nlen);
+	nbuf[nlen] = '\0';
+	r->nm.name = nbuf;
+
+	list_add_tail(&r->list, &c->replay_list);
+	return 0;
+}
+
+/**
+ * ubifs_validate_entry - validate directory or extended attribute entry node.
+ * @c: UBIFS file-system description object
+ * @dent: the node to validate
+ *
+ * This function validates directory or extended attribute entry node @dent.
+ * Returns zero if the node is all right and a %-EINVAL if not.
+ */
+int ubifs_validate_entry(struct ubifs_info *c __attribute__((unused)),
+			 const struct ubifs_dent_node *dent)
+{
+	int key_type = key_type_flash(dent->key);
+	int nlen = le16_to_cpu(dent->nlen);
+
+	if (le32_to_cpu(dent->ch.len) != nlen + UBIFS_DENT_NODE_SZ + 1 ||
+	    dent->type >= UBIFS_ITYPES_CNT ||
+	    nlen > UBIFS_MAX_NLEN || dent->name[nlen] != 0 ||
+	    strnlen((const char *)dent->name, nlen) != nlen ||
+	    le64_to_cpu(dent->inum) > MAX_INUM) {
+		errmsg("bad %s node", key_type == UBIFS_DENT_KEY ?
+			  "directory entry" : "extended attribute entry");
+		return -EINVAL;
+	}
+
+	if (key_type != UBIFS_DENT_KEY && key_type != UBIFS_XENT_KEY) {
+		errmsg("bad key type %d", key_type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * replay_bud - replay a bud logical eraseblock.
+ * @c: UBIFS file-system description object
+ * @b: bud entry which describes the bud
+ *
+ * This function replays bud @bud, recovers it if needed, and adds all nodes
+ * from this bud to the replay list. Returns zero in case of success and a
+ * negative error code in case of failure.
+ */
+static int replay_bud(struct ubifs_info *c, struct ubifs_bud *b)
+{
+	int err = 0, used = 0, lnum = b->lnum, offs = b->start;
+	struct ubifs_scan_leb *sleb;
+	struct ubifs_scan_node *snod;
+
+	verbose(c->verbose, "replay bud LEB %d, head %d, offs %d",
+		lnum, b->jhead, offs);
+
+	// TODO LEB recovery for last bud of each journal head
+	//if (is_last)
+		/*
+		 * Recover only last LEBs in the journal heads, because power
+		 * cuts may cause corruptions only in these LEBs, because only
+		 * these LEBs could possibly be written to at the power cut
+		 * time.
+		 */
+		//sleb = ubifs_recover_leb(c, lnum, offs, c->sbuf, b->bud->jhead);
+	//else
+		sleb = ubifs_scan(c, lnum, offs, c->sbuf, 0);
+
+	if (IS_ERR(sleb))
+		return PTR_ERR(sleb);
+
+	/*
+	 * The bud does not have to start from offset zero - the beginning of
+	 * the 'lnum' LEB may contain previously committed data. One of the
+	 * things we have to do in replay is to correctly update lprops with
+	 * newer information about this LEB.
+	 *
+	 * At this point lprops thinks that this LEB has 'c->leb_size - offs'
+	 * bytes of free space because it only contain information about
+	 * committed data.
+	 *
+	 * But we know that real amount of free space is 'c->leb_size -
+	 * sleb->endpt', and the space in the 'lnum' LEB between 'offs' and
+	 * 'sleb->endpt' is used by bud data. We have to correctly calculate
+	 * how much of these data are dirty and update lprops with this
+	 * information.
+	 *
+	 * The dirt in that LEB region is comprised of padding nodes, deletion
+	 * nodes, truncation nodes and nodes which are obsoleted by subsequent
+	 * nodes in this LEB. So instead of calculating clean space, we
+	 * calculate used space ('used' variable).
+	 */
+
+	list_for_each_entry(snod, &sleb->nodes, list) {
+		int deletion = 0;
+
+		// TODO remove watermark check for unpack
+		if (snod->sqnum >= SQNUM_WATERMARK) {
+			errmsg("file system's life ended");
+			goto out_dump;
+		}
+
+		if (snod->sqnum > c->max_sqnum)
+			c->max_sqnum = snod->sqnum;
+
+		switch (snod->type) {
+		case UBIFS_INO_NODE:
+		{
+			struct ubifs_ino_node *ino = snod->node;
+			loff_t new_size = le64_to_cpu(ino->size);
+
+			if (le32_to_cpu(ino->nlink) == 0)
+				deletion = 1;
+			err = insert_node(c, lnum, snod->offs, snod->len,
+					  &snod->key, snod->sqnum, deletion,
+					  &used, 0, new_size);
+			break;
+		}
+		case UBIFS_DATA_NODE:
+		{
+			struct ubifs_data_node *dn = snod->node;
+			loff_t new_size = le32_to_cpu(dn->size) +
+					  key_block(&snod->key) *
+					  UBIFS_BLOCK_SIZE;
+
+			err = insert_node(c, lnum, snod->offs, snod->len,
+					  &snod->key, snod->sqnum, deletion,
+					  &used, 0, new_size);
+			break;
+		}
+		case UBIFS_DENT_NODE:
+		case UBIFS_XENT_NODE:
+		{
+			struct ubifs_dent_node *dent = snod->node;
+
+			err = ubifs_validate_entry(c, dent);
+			if (err)
+				goto out_dump;
+
+			err = insert_dent(c, lnum, snod->offs, snod->len,
+					  &snod->key, (const char *)dent->name,
+					  le16_to_cpu(dent->nlen), snod->sqnum,
+					  !le64_to_cpu(dent->inum), &used);
+			break;
+		}
+		case UBIFS_TRUN_NODE:
+		{
+			struct ubifs_trun_node *trun = snod->node;
+			loff_t old_size = le64_to_cpu(trun->old_size);
+			loff_t new_size = le64_to_cpu(trun->new_size);
+			union ubifs_key key;
+
+			/* Validate truncation node */
+			if (old_size < 0 || old_size > c->max_inode_sz ||
+			    new_size < 0 || new_size > c->max_inode_sz ||
+			    old_size <= new_size) {
+				errmsg("bad truncation node");
+				goto out_dump;
+			}
+
+			/*
+			 * Create a fake truncation key just to use the same
+			 * functions which expect nodes to have keys.
+			 */
+			trun_key_init(c, &key, le32_to_cpu(trun->inum));
+			err = insert_node(c, lnum, snod->offs, snod->len,
+					  &key, snod->sqnum, 1, &used,
+					  old_size, new_size);
+			break;
+		}
+		default:
+			errmsg("unexpected node type %d in bud LEB %d:%d",
+				  snod->type, lnum, snod->offs);
+			err = -EINVAL;
+			goto out_dump;
+		}
+		if (err)
+			goto out;
+	}
+
+	assert(ubifs_search_bud(c, lnum));
+	assert(sleb->endpt - offs >= used);
+	assert(sleb->endpt % c->min_io_size == 0);
+
+out:
+	ubifs_scan_destroy(sleb);
+	return err;
+
+out_dump:
+	errmsg("bad node is at LEB %d:%d", lnum, snod->offs);
+	ubifs_scan_destroy(sleb);
+	return -EINVAL;
+}
+
+/**
+ * replay_buds - replay all buds.
+ * @c: UBIFS file-system description object
+ *
+ * This function returns zero in case of success and a negative error code in
+ * case of failure.
+ */
+static int replay_buds(struct ubifs_info *c)
+{
+	struct ubifs_bud *bud;
+	int err;
+	unsigned long long prev_sqnum = 0;
+
+	list_for_each_entry(bud, &c->replay_buds, list) {
+		err = replay_bud(c, bud);
+		if (err)
+			return err;
+
+		assert(bud->sqnum > prev_sqnum);
+		prev_sqnum = bud->sqnum;
+	}
+
+	return 0;
+}
+
+/**
+ * destroy_bud_list - destroy the list of buds to replay.
+ * @c: UBIFS file-system description object
+ */
+static void destroy_bud_list(struct ubifs_info *c)
+{
+	struct ubifs_bud *b;
+
+	while (!list_empty(&c->replay_buds)) {
+		b = list_entry(c->replay_buds.next, struct ubifs_bud, list);
+		list_del(&b->list);
+		kfree(b);
+	}
+}
+
+/**
+ * add_replay_bud - add a bud to the list of buds to replay.
+ * @c: UBIFS file-system description object
+ * @lnum: bud logical eraseblock number to replay
+ * @offs: bud start offset
+ * @jhead: journal head to which this bud belongs
+ * @sqnum: reference node sequence number
+ *
+ * This function returns zero in case of success and a negative error code in
+ * case of failure.
+ */
+static int add_replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead,
+			  unsigned long long sqnum)
+{
+	struct ubifs_bud *bud;
+
+	verbose(c->verbose, "add replay bud LEB %d:%d, head %d", lnum, offs, jhead);
+
+	bud = malloc(sizeof(struct ubifs_bud));
+	if (!bud)
+		return -ENOMEM;
+
+	bud->lnum = lnum;
+	bud->start = offs;
+	bud->jhead = jhead;
+	bud->sqnum = sqnum;
+	list_add_tail(&bud->list, &c->replay_buds);
+
+	return 0;
+}
+
+/**
+ * validate_ref - validate a reference node.
+ * @c: UBIFS file-system description object
+ * @ref: the reference node to validate
+ * @ref_lnum: LEB number of the reference node
+ * @ref_offs: reference node offset
+ *
+ * This function returns %1 if a bud reference already exists for the LEB. %0 is
+ * returned if the reference node is new, otherwise %-EINVAL is returned if
+ * validation failed.
+ */
+static int validate_ref(struct ubifs_info *c, const struct ubifs_ref_node *ref)
+{
+	struct ubifs_bud *bud;
+	int lnum = le32_to_cpu(ref->lnum);
+	unsigned int offs = le32_to_cpu(ref->offs);
+	unsigned int jhead = le32_to_cpu(ref->jhead);
+
+	/*
+	 * ref->offs may point to the end of LEB when the journal head points
+	 * to the end of LEB and we write reference node for it during commit.
+	 * So this is why we require 'offs > c->leb_size'.
+	 */
+	if (jhead >= c->jhead_cnt || lnum >= c->leb_cnt ||
+	    lnum < c->main_first || offs > c->leb_size ||
+	    offs & (c->min_io_size - 1))
+		return -EINVAL;
+
+	/* Make sure we have not already looked at this bud */
+	bud = ubifs_search_bud(c, lnum);
+	if (bud) {
+		if (bud->jhead == jhead && bud->start <= offs)
+			return 1;
+		errmsg("bud at LEB %d:%d was already referred", lnum, offs);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * replay_log_leb - replay a log logical eraseblock.
+ * @c: UBIFS file-system description object
+ * @lnum: log logical eraseblock to replay
+ * @offs: offset to start replaying from
+ * @sbuf: scan buffer
+ *
+ * This function replays a log LEB and returns zero in case of success, %1 if
+ * this is the last LEB in the log, and a negative error code in case of
+ * failure.
+ */
+static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
+{
+	int err;
+	struct ubifs_scan_leb *sleb;
+	struct ubifs_scan_node *snod;
+	const struct ubifs_cs_node *node;
+
+	verbose(c->verbose, "replay log LEB %d:%d", lnum, offs);
+	sleb = ubifs_scan(c, lnum, offs, sbuf, !c->verbose);
+	if (IS_ERR(sleb)) {
+		if (PTR_ERR(sleb) != -EUCLEAN)
+			return PTR_ERR(sleb);
+		/*
+		 * Note, the below function will recover this log LEB only if
+		 * it is the last, because unclean reboots can possibly corrupt
+		 * only the tail of the log.
+		 */
+		// TODO implement recovery
+		//sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf);
+		//if (IS_ERR(sleb))
+			return PTR_ERR(sleb);
+	}
+
+	if (sleb->nodes_cnt == 0) {
+		err = 1;
+		goto out;
+	}
+
+	node = sleb->buf;
+	snod = list_entry(sleb->nodes.next, struct ubifs_scan_node, list);
+	if (c->cs_sqnum == 0) {
+		/*
+		 * This is the first log LEB we are looking at, make sure that
+		 * the first node is a commit start node. Also record its
+		 * sequence number so that UBIFS can determine where the log
+		 * ends, because all nodes which were have higher sequence
+		 * numbers.
+		 */
+		if (snod->type != UBIFS_CS_NODE) {
+			errmsg("first log node at LEB %d:%d is not CS node",
+				  lnum, offs);
+			goto out_dump;
+		}
+		if (le64_to_cpu(node->cmt_no) != c->cmt_no) {
+			errmsg("first CS node at LEB %d:%d has wrong commit number %llu expected %llu",
+				  lnum, offs,
+				  (unsigned long long)le64_to_cpu(node->cmt_no),
+				  c->cmt_no);
+			goto out_dump;
+		}
+
+		c->cs_sqnum = le64_to_cpu(node->ch.sqnum);
+		verbose(c->verbose, "commit start sqnum %llu", c->cs_sqnum);
+	}
+
+	if (snod->sqnum < c->cs_sqnum) {
+		/*
+		 * This means that we reached end of log and now
+		 * look to the older log data, which was already
+		 * committed but the eraseblock was not erased (UBIFS
+		 * only un-maps it). So this basically means we have to
+		 * exit with "end of log" code.
+		 */
+		err = 1;
+		goto out;
+	}
+
+	/* Make sure the first node sits at offset zero of the LEB */
+	if (snod->offs != 0) {
+		errmsg("first node is not at zero offset");
+		goto out_dump;
+	}
+
+	list_for_each_entry(snod, &sleb->nodes, list) {
+		// TODO remove this check since we still might be able to
+		// unpack a end-of-life UBIFS!
+		if (snod->sqnum >= SQNUM_WATERMARK) {
+			errmsg("file system's life ended");
+			goto out_dump;
+		}
+
+		if (snod->sqnum < c->cs_sqnum) {
+			errmsg("bad sqnum %llu, commit sqnum %llu",
+				  snod->sqnum, c->cs_sqnum);
+			goto out_dump;
+		}
+
+		if (snod->sqnum > c->max_sqnum)
+			c->max_sqnum = snod->sqnum;
+
+		switch (snod->type) {
+		case UBIFS_REF_NODE: {
+			const struct ubifs_ref_node *ref = snod->node;
+
+			err = validate_ref(c, ref);
+			if (err == 1)
+				break; /* Already have this bud */
+			if (err)
+				goto out_dump;
+
+			err = add_replay_bud(c, le32_to_cpu(ref->lnum),
+					     le32_to_cpu(ref->offs),
+					     le32_to_cpu(ref->jhead),
+					     snod->sqnum);
+			if (err)
+				goto out;
+
+			break;
+		}
+		case UBIFS_CS_NODE:
+			/* Make sure it sits at the beginning of LEB */
+			if (snod->offs != 0) {
+				errmsg("unexpected node in log");
+				goto out_dump;
+			}
+			break;
+		default:
+			errmsg("unexpected node in log");
+			goto out_dump;
+		}
+	}
+
+	if (sleb->endpt) {
+		c->lhead_lnum = lnum;
+	}
+
+	err = !sleb->endpt;
+out:
+	ubifs_scan_destroy(sleb);
+	return err;
+
+out_dump:
+	errmsg("log error detected while replaying the log at LEB %d:%d",
+		  lnum, offs + snod->offs);
+	ubifs_scan_destroy(sleb);
+	return -EINVAL;
+}
+
+/**
+ * ubifs_replay_journal - replay journal.
+ * @c: UBIFS file-system description object
+ *
+ * This function scans the journal, replays and cleans it up. It makes sure all
+ * memory data structures related to uncommitted journal are built (dirty TNC
+ * tree, tree of buds, modified lprops, etc).
+ */
+int ubifs_replay_journal(struct ubifs_info *c)
+{
+	int err, lnum, ltail_lnum;
+
+	verbose(c->verbose, "start replaying the journal");
+	lnum = ltail_lnum = c->lhead_lnum;
+
+	do {
+		err = replay_log_leb(c, lnum, 0, c->sbuf);
+		if (err == 1) {
+			if (lnum != c->lhead_lnum)
+				/* We hit the end of the log */
+				break;
+
+			/*
+			 * The head of the log must always start with the
+			 * "commit start" node on a properly formatted UBIFS.
+			 * But we found no nodes at all, which means that
+			 * someting went wrong and we cannot proceed mounting
+			 * the file-system.
+			 */
+			errmsg("no UBIFS nodes found at the log head LEB %d:%d, possibly corrupted",
+				  lnum, 0);
+			err = -EINVAL;
+		}
+		if (err)
+			goto out;
+		lnum = ubifs_next_log_lnum(c, lnum);
+	} while (lnum != ltail_lnum);
+
+	err = replay_buds(c);
+	if (err)
+		goto out;
+
+	err = apply_replay_list(c);
+	if (err)
+		goto out;
+
+	verbose(c->verbose, "finished, log head LEB %d, max_sqnum %llu, highest_inum %lu",
+		c->lhead_lnum, c->max_sqnum, (unsigned long)c->highest_inum);
+out:
+	destroy_replay_list(c);
+	destroy_bud_list(c);
+	return err;
+}
diff --git a/ubifs-utils/ubifs_unpack/ubifs_unpack.c b/ubifs-utils/ubifs_unpack/ubifs_unpack.c
new file mode 100644
index 0000000..321a42f
--- /dev/null
+++ b/ubifs-utils/ubifs_unpack/ubifs_unpack.c
@@ -0,0 +1,619 @@
+/*
+ * Copyright (C) 2015 sigma star gmbh
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Richard Weinberger
+ *          David Gstir
+ */
+
+#define PROGRAM_NAME "ubifs_unpack"
+
+#include "ubifs_common.h"
+#include "ubifs_unpack.h"
+
+#include "crc32.h"
+#include "lpt.h"
+#include "key.h"
+#include "emubi.h"
+#include "master.h"
+#include "ubiutils-common.h"
+#include "compr.h"
+
+#include <getopt.h>
+#include <sys/mman.h>
+#include <lzo/lzo1x.h>
+
+extern char *optarg;
+extern int optind;
+
+struct unpack_args {
+	int peb_size;
+	int page_size;
+	int vol_id;
+	char *ubi_dev;
+
+	int emubi_mode;
+	int verbose;
+	char *out_root;
+};
+
+static const char doc[] = PROGRAM_NAME " version " VERSION
+			  " - a tool to unpack UBIFS images.";
+
+static const char optionsstr[] =
+"-o, --output=<output dir>    root directory where extracted files will be\n"
+"                             extracted to (required)\n"
+"-p, --peb-size=<bytes>       size of the physical eraseblock of the flash\n"
+"                             this UBI image is created for in bytes,\n"
+"                             kilobytes (KiB), or megabytes (MiB)\n"
+"                             (required)\n"
+"-m, --min-io-size=<bytes>    minimum input/output unit size of the flash\n"
+"                             in bytes (required)\n"
+"-n, --vol-id=<volume ID>     UBI volume ID (defaults to 0)\n"
+"-u, --ubi-dev=<device path>  UBI volume device to read from\n"
+"-e, --emubi-mode=<mode>      EMUBI mode: 'mmap' or 'file' (defaults to 'file')\n"
+"-v, --verbose                verbose output\n"
+"-h, --help                   print help message\n"
+"-V, --version                print program version";
+
+static const char usage[] =
+"Usage: " PROGRAM_NAME " [-o <output dir>] [-p <bytes>] [-m <bytes>] [-n <volume ID>] [-v]\n"
+"\t\t[--output=<output dir>] [--peb-size=<bytes>] [--min-io-size=<bytes>]\n"
+"\t\t[--vol-id=<volume ID>] [--verbose] [--help] [--version] source\n"
+"Example: " PROGRAM_NAME " -p 16KiB -m 512 ubifs.img - unpack volume 1 of image\n"
+"         'ubifs.img'";
+
+static const struct option long_opts[] = {
+	{ .name = "output",         .has_arg = 1, .flag = NULL, .val = 'o' },
+	{ .name = "peb-size",       .has_arg = 1, .flag = NULL, .val = 'p' },
+	{ .name = "min-io-size",    .has_arg = 1, .flag = NULL, .val = 'm' },
+	{ .name = "vol-id",         .has_arg = 1, .flag = NULL, .val = 'n' },
+	{ .name = "ubi-dev",        .has_arg = 1, .flag = NULL, .val = 'u' },
+	{ .name = "emubi-mode",     .has_arg = 1, .flag = NULL, .val = 'e' },
+	{ .name = "verbose",        .has_arg = 0, .flag = NULL, .val = 'v' },
+	{ .name = "help",           .has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "version",        .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ NULL, 0, NULL, 0 }
+};
+
+// TODO replace all assert()s with proper error handling
+// TODO cleanup logging - esp. unify key logging
+
+static int write_block(struct ubifs_info *c, struct ubifs_dent_node *dent,
+		       int block, char *dst)
+{
+	struct ubifs_data_node *d;
+	size_t out_len = UBIFS_BLOCK_SIZE;
+	int data_len, ret;
+
+	d = ubifs_lookup_data_node(c, le64toh(dent->inum), block);
+	if (!d) {
+		/* file hole */
+		return 0;
+	}
+
+	data_len = le32toh(d->ch.len) - UBIFS_DATA_NODE_SZ;
+	ret = decompress_data(d->data, data_len, dst, &out_len, d->compr_type);
+	free(d);
+
+	return ret;
+}
+
+static void __set_attributes(struct ubifs_ino_node *ino, int target_fd)
+{
+	fchmod(target_fd, le32toh(ino->mode));
+	fchown(target_fd, le32toh(ino->uid), le32toh(ino->gid));
+}
+
+static void set_attributes(struct ubifs_info *c, struct ubifs_dent_node *dent,
+			   int target_fd)
+{
+	struct ubifs_ino_node *ino;
+
+	ino = ubifs_lookup_ino_node(c, le64toh(dent->inum));
+	__set_attributes(ino, target_fd);
+	free(ino);
+}
+
+static void write_symlink(struct ubifs_info *c, struct ubifs_dent_node *dent,
+			  int parent_fd)
+{
+	struct ubifs_ino_node *ino;
+	char *link_tgt;
+	int len;
+
+	ino = ubifs_lookup_ino_node(c, le64toh(dent->inum));
+	assert(ino);
+
+	len = le32toh(ino->data_len);
+	if (len > PATH_MAX) {
+		free(ino);
+		return;
+	}
+
+	link_tgt = xmalloc(len + 1);
+	memcpy(link_tgt, ino->data, len);
+	link_tgt[len] = '\0';
+
+	symlinkat(link_tgt, parent_fd, (char *)dent->name);
+
+	free(link_tgt);
+	free(ino);
+}
+
+static void write_file(struct ubifs_info *c, struct ubifs_dent_node *dent,
+		       int parent_fd)
+{
+	int fd, i, errs;
+	char *tgt;
+	struct ubifs_ino_node *ino;
+	char nul[1] = { 0 };
+	unsigned int file_len;
+	int num_blocks;
+
+	ino = ubifs_lookup_ino_node(c, le64toh(dent->inum));
+	assert(ino);
+	file_len = le64toh(ino->size);
+
+	num_blocks = (file_len + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
+
+	fd = openat(parent_fd, (const char *)dent->name, O_CREAT|O_RDWR|O_TRUNC, 0700);
+	assert(fd);
+
+	if (!file_len) {
+		free(ino);
+		close(fd);
+		return;
+	}
+
+	lseek(fd, file_len - 1, SEEK_SET);
+	write(fd, nul, 1);
+
+	tgt = mmap(NULL, file_len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+	assert(tgt != MAP_FAILED);
+	__set_attributes(ino, fd);
+	free(ino);
+	close(fd);
+
+	errs = 0;
+	for (i = 0; i < num_blocks; i++)
+		if (write_block(c, dent, i, tgt + (UBIFS_BLOCK_SIZE * i)) != 0)
+			errs++;
+
+	if (errs)
+		errmsg("decompress of %d data nodes of %s failed", errs, dent->name);
+
+	munmap(tgt, file_len);
+}
+
+static inline dev_t new_decode_dev(uint32_t dev)
+{
+	unsigned major = (dev & 0xfff00) >> 8;
+	unsigned minor = (dev & 0xff) | ((dev >> 12) & 0xfff00);
+
+	return makedev(major, minor);
+}
+
+static void write_devnode(struct ubifs_info *c, struct ubifs_dent_node *dent,
+			  int parent_fd)
+{
+	struct ubifs_ino_node *ino;
+	union ubifs_dev_desc *devd;
+	dev_t rdev;
+
+	ino = ubifs_lookup_ino_node(c, le64toh(dent->inum));
+	assert(ino);
+
+	devd = (union ubifs_dev_desc *)ino->data;
+
+	if (ino->data_len == sizeof(devd->new))
+		rdev = new_decode_dev(devd->new);
+	else if (ino->data_len == sizeof(devd->huge))
+		rdev = new_decode_dev(devd->huge);
+	else {
+		errmsg("Invalid inode data len!\n");
+		goto out;
+	}
+
+	mknodat(parent_fd, (const char *)dent->name, le32toh(ino->mode), rdev);
+
+out:
+	free(ino);
+}
+
+static void write_fifo(struct ubifs_info *c, struct ubifs_dent_node *dent,
+		       int parent_fd)
+{
+	struct ubifs_ino_node *ino;
+
+	ino = ubifs_lookup_ino_node(c, le64toh(dent->inum));
+	assert(ino);
+
+	mknodat(parent_fd, (const char *)dent->name, le32toh(ino->mode), 0);
+
+	free(ino);
+}
+
+static void unpack_dir(struct ubifs_info *c, ino_t dir_ino, int parent_fd, int depth)
+{
+	int fd;
+	struct ubifs_dent_node *dent;
+	struct ubifs_leaf *leaf = NULL;
+
+	for (;;) {
+		leaf = ubifs_next_leaf(leaf, dir_ino);
+		if (!leaf)
+			/* end of list */
+			break;
+
+		/* skip any nodes other than UBIFS_DENT_NODE. E.g extended
+		 * attribute nodes */
+		if (key_type(&leaf->key) != UBIFS_DENT_KEY)
+			continue;
+
+		dent = xmalloc(leaf->len);
+		get_dent_node(c, dent, leaf->lnum, leaf->offs, leaf->len);
+		bareverbose(c->verbose, "%.*s", depth, "                 ");
+		switch (dent->type) {
+		case UBIFS_ITYPE_REG:
+			bareverbose(c->verbose, "%s\n", dent->name);
+			write_file(c, dent, parent_fd);
+			break;
+		case UBIFS_ITYPE_DIR:
+			bareverbose(c->verbose, "[%s]\n", dent->name);
+
+			if (mkdirat(parent_fd, (const char *)dent->name, 0755) == -1) {
+				warnmsg("Unable to create %s: %m\n", dent->name);
+				continue;
+			}
+
+			fd = openat(parent_fd, (const char *)dent->name, O_RDONLY);
+			if (fd == -1) {
+				sys_errmsg_die("unpack of %s failed", dent->name);
+			}
+
+			unpack_dir(c, le64toh(dent->inum), fd, depth + 1);
+			set_attributes(c, dent, fd);
+			close(fd);
+			break;
+		case UBIFS_ITYPE_LNK:
+			write_symlink(c, dent, parent_fd);
+			break;
+		case UBIFS_ITYPE_CHR:
+		case UBIFS_ITYPE_BLK:
+			write_devnode(c, dent, parent_fd);
+			break;
+		case UBIFS_ITYPE_FIFO:
+			write_fifo(c, dent, parent_fd);
+			break;
+		case UBIFS_ITYPE_SOCK:
+			warnmsg("Ignoring UNIX domain socket %s", dent->name);
+			break;
+		default:
+			/* TODO handle other inode types (link, devices etc) */
+			warnmsg("Unsupported DENT type: %d", dent->type);
+		}
+
+		free(dent);
+	}
+}
+
+//TODO: make this common with ubifs_dump
+static void destroy_ubifs_info(struct ubifs_info *c)
+{
+	free(c->sbuf);
+}
+
+/*
+ * init_constants_sb - initialize UBIFS constants.
+ * @c: UBIFS file-system description object
+ *
+ * This is a helper function which initializes various UBIFS constants after
+ * the superblock has been read. It also checks various UBIFS parameters and
+ * makes sure they are all right. Returns zero in case of success and a
+ * negative error code in case of failure.
+ */
+//TODO: make this common with ubifs_dump
+static int init_constants_sb(struct ubifs_info *c)
+{
+	int tmp, err;
+
+	tmp = ubifs_idx_node_sz(c, 1);
+	c->min_idx_node_sz = ALIGN(tmp, 8);
+
+	tmp = ubifs_idx_node_sz(c, c->fanout);
+	c->max_idx_node_sz = ALIGN(tmp, 8);
+
+	c->max_znode_sz = sizeof(struct ubifs_znode) +
+			c->fanout * sizeof(struct ubifs_zbranch);
+	/* Make sure LEB size is large enough to fit full commit */
+	tmp = UBIFS_CS_NODE_SZ + UBIFS_REF_NODE_SZ * c->jhead_cnt;
+	tmp = ALIGN(tmp, c->min_io_size);
+	if (tmp > c->leb_size) {
+		errmsg("too small LEB size %d, at least %d needed",
+			  c->leb_size, tmp);
+		return -EINVAL;
+	}
+
+	err = ubifs_calc_lpt_geom(c);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+//TODO: make this common with ubifs_dump
+static int init_ubifs_info(struct ubifs_info *c, struct ubifs_sb_node *sb)
+{
+	int err;
+	unsigned long sup_flags;
+
+        switch (sb->key_hash) {
+        case UBIFS_KEY_HASH_R5:
+                c->key_hash = key_r5_hash;
+                c->key_hash_type = UBIFS_KEY_HASH_R5;
+                break;
+
+        case UBIFS_KEY_HASH_TEST:
+                c->key_hash = key_test_hash;
+                c->key_hash_type = UBIFS_KEY_HASH_TEST;
+                break;
+        };
+
+	c->key_fmt = sb->key_fmt;
+
+	switch (c->key_fmt) {
+	case UBIFS_SIMPLE_KEY_FMT:
+		c->key_len = UBIFS_SK_LEN;
+		break;
+	default:
+		errmsg("unsupported UBIFS key format");
+		err = -EINVAL;
+		goto out;
+	}
+
+	c->leb_size	 = le32_to_cpu(sb->leb_size);
+	c->min_io_size	 = le32_to_cpu(sb->min_io_size);
+	c->leb_cnt       = le32_to_cpu(sb->leb_cnt);
+	c->max_leb_cnt   = le32_to_cpu(sb->max_leb_cnt);
+	c->max_bud_bytes = le64_to_cpu(sb->max_bud_bytes);
+	c->log_lebs      = le32_to_cpu(sb->log_lebs);
+	c->lpt_lebs      = le32_to_cpu(sb->lpt_lebs);
+	c->orph_lebs     = le32_to_cpu(sb->orph_lebs);
+	c->jhead_cnt     = le32_to_cpu(sb->jhead_cnt) + NONDATA_JHEADS_CNT;
+	c->fanout        = le32_to_cpu(sb->fanout);
+	c->lsave_cnt     = le32_to_cpu(sb->lsave_cnt);
+	c->rp_size       = le64_to_cpu(sb->rp_size);
+	sup_flags        = le32_to_cpu(sb->flags);
+	c->cs_sqnum      = 0;
+
+	c->default_compr = le16_to_cpu(sb->default_compr);
+
+	c->big_lpt = !!(sup_flags & UBIFS_FLG_BIGLPT);
+	c->space_fixup = !!(sup_flags & UBIFS_FLG_SPACE_FIXUP);
+
+	c->lpt_first = UBIFS_LOG_LNUM + c->log_lebs;
+	c->lpt_last = c->lpt_first + c->lpt_lebs - 1;
+	c->main_lebs = c->leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS;
+	c->main_lebs -= c->log_lebs + c->lpt_lebs + c->orph_lebs;
+	c->main_first = c->leb_cnt - c->main_lebs;
+
+	c->max_inode_sz = key_max_inode_size(c);
+
+	err = init_constants_sb(c);
+
+	c->sbuf = xmalloc(c->leb_size);
+
+	INIT_LIST_HEAD(&c->replay_list);
+	INIT_LIST_HEAD(&c->replay_buds);
+out:
+	return err;
+}
+
+static int ubifs_read_sb(struct ubifs_info *c)
+{
+	struct ubifs_sb_node sb;
+
+	ubifs_leb_read(c, UBIFS_SB_LNUM, &sb, 0, sizeof(sb));
+	if (le32toh(sb.ch.magic) != UBIFS_NODE_MAGIC) {
+		return errmsg("invalid superblock node");
+	}
+
+	init_ubifs_info(c, &sb);
+
+	// TODO call validate_sb() here to properly check the sb node.
+	return 0;
+}
+
+static int unpack(struct ubifs_info *c, char *out_root)
+{
+	int fd, err = 0;
+
+	normsg("reading superblock node...");
+	err = ubifs_read_sb(c);
+	if (err)
+		goto out;
+
+	normsg("reading master node...");
+	err = ubifs_read_master(c);
+	if (err)
+		goto out;
+
+	normsg("reading on-flash index...");
+	ubifs_load_index(c, c->zroot.lnum, c->zroot.offs, c->zroot.len);
+
+	normsg("replaying journal...");
+	err = ubifs_replay_journal(c);
+	if (err)
+		goto out;
+
+	normsg("unpacking files...");
+	fd = open(out_root, O_RDONLY);
+	if (fd == -1)
+		return sys_errmsg("open of output folder failed");
+
+	unpack_dir(c, 1, fd, 0);
+
+out:
+	return err;
+}
+
+static int parse_opt(int argc, char *argv[], struct unpack_args *args)
+{
+	long long val;
+	int key, err;
+
+	while ((key = getopt_long(argc, argv, "o:p:m:n:u:e:vhV", long_opts, NULL)) != -1) {
+		switch (key) {
+		case 'o':
+			args->out_root = optarg;
+			err = mkdir(args->out_root, 0755);
+			if (err && errno == EEXIST)
+				return errmsg("output directory exists");
+			else if (err)
+				return sys_errmsg("mkdir of %s failed", optarg);
+			break;
+		case 'p':
+			val = parse_bytes(optarg);
+			if (val <= 0 || val > UINT_MAX)
+				return errmsg("bad physical eraseblock size: \"%s\"", optarg);
+			args->peb_size = val;
+			break;
+		case 'm':
+			val = parse_bytes(optarg);
+			if (val <= 0 || val > UINT_MAX)
+				return errmsg("bad min. I/O unit size: \"%s\"", optarg);
+			if (!is_power_of_2(val))
+				return errmsg("min. I/O unit size must be power of 2");
+			args->page_size = val;
+			break;
+		case 'n':
+			args->vol_id = atoi(optarg);
+			if (args->vol_id < 0)
+				return errmsg("bad volume ID: \"%s\"", optarg);
+			break;
+		case 'u':
+			args->ubi_dev = optarg;
+			break;
+		case 'e':
+			if (strcasecmp(optarg, "mmap") == 0)
+				args->emubi_mode = EMUBI_MODE_MMAP;
+			else if (strcasecmp(optarg, "file") == 0)
+				args->emubi_mode = EMUBI_MODE_FILE;
+			else
+				return errmsg("invalid emubi mode %s (use 'file' or 'mmap')", optarg);
+			break;
+		case 'v':
+			args->verbose = 1;
+			break;
+		case 'h':
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n\n", optionsstr);
+			exit(EXIT_SUCCESS);
+		case 'V':
+			common_print_version();
+			exit(EXIT_SUCCESS);
+		default:
+			return errmsg("unknown option. Use -h for help");
+		}
+
+	}
+
+	if (!args->out_root)
+		return errmsg("no output directory specified");
+
+	if (!args->ubi_dev) {
+		if (optind == argc)
+			return errmsg("image file is missing (use -h for help)");
+
+		if (args->peb_size < 0)
+			return errmsg("physical eraseblock size was not specified (use -p <bytes>)");
+
+		if (args->page_size < 0)
+			return errmsg("min. I/O unit size was not specified (use -m <bytes>)");
+
+		if (args->peb_size % args->page_size)
+			return errmsg("physical eraseblock size must be multiple of min. I/O unit size");
+	}
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	int err;
+	struct ubifs_info info;
+	struct emubi_ctx emubi;
+	struct unpack_args args = {
+		.peb_size = -1,
+		.page_size = -1,
+		.vol_id = 0,
+		.ubi_dev = NULL,
+		.verbose = 0,
+		.out_root = NULL,
+		.emubi_mode = EMUBI_MODE_FILE,
+	};
+
+	err = parse_opt(argc, argv, &args);
+	if (err)
+		return EXIT_FAILURE;
+
+	emubi.mode = args.emubi_mode;
+	if (args.ubi_dev) {
+		output = xstrdup(args.ubi_dev);
+		open_ubi(&info, output);
+		if (open_target(&info, 1)) {
+			errmsg("Unable to open UBI volume device\n");
+			return EXIT_FAILURE;
+		}
+	}
+	else {
+		emubi.peb_size = args.peb_size;
+		emubi.page_size = args.page_size;
+		emubi.vol_id = args.vol_id;
+		info.emubi = &emubi;
+		info.verbose = args.verbose;
+
+		err = emubi_open(&emubi, argv[optind]);
+		if (err)
+			goto out;
+
+		err = emubi_scan(&emubi);
+		if (err)
+			goto out;
+
+
+		emubi_print(&emubi);
+	}
+
+	err = unpack(&info, args.out_root);
+
+out:
+	if (args.ubi_dev)
+		close_target();
+
+	ubifs_destroy_index();
+	emubi_close(&emubi);
+	destroy_ubifs_info(&info);
+
+	if (err) {
+		errmsg("unpack failed");
+		return EXIT_FAILURE;
+	}
+
+	normsg("unpack finished");
+	return EXIT_SUCCESS;
+}
diff --git a/ubifs-utils/ubifs_unpack/ubifs_unpack.h b/ubifs-utils/ubifs_unpack/ubifs_unpack.h
new file mode 100644
index 0000000..5c033e8
--- /dev/null
+++ b/ubifs-utils/ubifs_unpack/ubifs_unpack.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2015 sigma star gmbh
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Richard Weinberger
+ *          David Gstir
+ */
+
+#ifndef __UBIFS_UNPACK_H__
+#define __UBIFS_UNPACK_H__
+
+#include "ubifs_common.h"
+#include "common.h"
+#include "ubifs.h"
+#include "scan.h"
+#include "key.h"
+#include "xalloc.h"
+#include "io.h"
+
+struct ubifs_leaf {
+	union ubifs_key key;
+	unsigned int lnum;
+	unsigned int offs;
+	unsigned int len;
+	struct list_head l;
+};
+
+static inline void get_idx_node(struct ubifs_info *c, struct ubifs_idx_node *n,
+				unsigned int lnum, unsigned int offset,
+				unsigned int len)
+{
+	ubifs_leb_read(c, lnum, n, offset, len);
+	assert(le32toh(n->ch.magic) == UBIFS_NODE_MAGIC);
+	assert(n->ch.node_type == UBIFS_IDX_NODE);
+}
+
+static inline void get_dent_node(struct ubifs_info *c, struct ubifs_dent_node *n,
+				 unsigned int lnum, unsigned int offset,
+				 unsigned int len)
+{
+	ubifs_leb_read(c, lnum, n, offset, len);
+	assert(le32toh(n->ch.magic) == UBIFS_NODE_MAGIC);
+	assert(n->ch.node_type == UBIFS_DENT_NODE);
+}
+
+static inline void get_ino_node(struct ubifs_info *c, struct ubifs_ino_node *n,
+				unsigned int lnum, unsigned int offset,
+				unsigned int len)
+{
+	ubifs_leb_read(c, lnum, n, offset, len);
+	assert(le32toh(n->ch.magic) == UBIFS_NODE_MAGIC);
+	assert(n->ch.node_type == UBIFS_INO_NODE);
+}
+
+static inline void get_data_node(struct ubifs_info *c, struct ubifs_data_node *n,
+				 unsigned int lnum, unsigned int offset,
+				 unsigned int len)
+{
+	ubifs_leb_read(c, lnum, n, offset, len);
+	assert(le32toh(n->ch.magic) == UBIFS_NODE_MAGIC);
+	assert(n->ch.node_type == UBIFS_DATA_NODE);
+}
+
+static inline struct ubifs_branch *get_branch(struct ubifs_idx_node *idx,
+					      unsigned int n)
+{
+	return (struct ubifs_branch *)(idx->branches
+		 + ((UBIFS_BRANCH_SZ + UBIFS_SK_LEN) * n));
+}
+
+/* replay.c */
+int ubifs_replay_journal(struct ubifs_info *c);
+
+/* index.c */
+void ubifs_destroy_index();
+void ubifs_load_index(struct ubifs_info *c, unsigned int lnum,
+		      unsigned int offset, unsigned int len);
+struct ubifs_ino_node *ubifs_lookup_ino_node(struct ubifs_info *c, ino_t ino);
+struct ubifs_data_node *ubifs_lookup_data_node(struct ubifs_info *c, ino_t ino,
+					       unsigned int block);
+struct ubifs_leaf *ubifs_next_leaf(struct ubifs_leaf *ul, ino_t ino);
+
+int ubifs_add_node(struct ubifs_info *c, union ubifs_key *key, int lnum,
+		   int offs, unsigned int len);
+int ubifs_add_node_nm(struct ubifs_info *c, union ubifs_key *key, int lnum,
+		      int offs, unsigned int len, struct qstr *nm);
+int ubifs_remove_inode(struct ubifs_info *c, ino_t ino);
+int ubifs_remove_node(struct ubifs_info *c, union ubifs_key *key);
+int ubifs_remove_node_nm(struct ubifs_info *c, union ubifs_key *key,
+			 struct qstr *nm);
+int ubifs_remove_node_range(struct ubifs_info *c, union ubifs_key *min_key,
+			    union ubifs_key *max_key);
+
+
+#endif
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2015-12-21  8:52 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-21  8:41 [PATCH 00/38] mtd-utils: add ubifs_dump and ubifs_unpacker Dongsheng Yang
2015-12-21  8:41 ` [PATCH 01/38] ubifs: pick some common definitions into ubifs_common.h Dongsheng Yang
2015-12-21  8:41 ` [PATCH 02/38] ubifs: move the all io related code into io.[h|c] Dongsheng Yang
2015-12-21  8:41 ` [PATCH 03/38] ubifs: remove the including of mkfs.ubifs.h in lpt.c Dongsheng Yang
2015-12-21  8:41 ` [PATCH 04/38] ubifs: cut off the dependence from compr.o to mkfs.ubifs Dongsheng Yang
2015-12-21  8:41 ` [PATCH 05/38] ubifs: cut off the dependence from devtable to mkfs.ubifs.h Dongsheng Yang
2015-12-21  8:41 ` [PATCH 06/38] ubifs: introduce ubifs-utils/include and ubifs-utils/lib Dongsheng Yang
2015-12-21  8:41 ` [PATCH 07/38] ubifs: move more functions into io lib Dongsheng Yang
2015-12-21  8:41 ` [PATCH 08/38] ubifs: introduce a new tool ubifs_dump Dongsheng Yang
2015-12-21  8:41 ` [PATCH 09/38] ubifs: introduce list.h Dongsheng Yang
2015-12-21  8:41 ` [PATCH 10/38] ubifs: copy some important data in ubifs.h from kernel to ubifs-utils Dongsheng Yang
2015-12-21  8:41 ` [PATCH 11/38] ubifs: copy some important functions in key.h " Dongsheng Yang
2015-12-21  8:41 ` [PATCH 12/38] ubifs: ubifs_dump: add dump_ch and dump_node functions Dongsheng Yang
2015-12-21  8:41 ` [PATCH 13/38] ubifs: defs.h: introduce some compatible definition for printk class Dongsheng Yang
2015-12-21  8:41 ` [PATCH 14/38] ubifs: io: introduce ubifs_read function to read ubi volume Dongsheng Yang
2015-12-21  8:41 ` [PATCH 15/38] ubifs: ubifs_dump: dump super block Dongsheng Yang
2015-12-21  8:41 ` [PATCH 16/38] ubifs: introduce scan for ubifs-utils Dongsheng Yang
2015-12-21  8:41 ` [PATCH 17/38] ubifs: add some more compatible definitions in defs.h Dongsheng Yang
2015-12-21  8:41 ` [PATCH 18/38] ubifs: ubifs_dump: dump master node Dongsheng Yang
2015-12-21  8:41 ` [PATCH 19/38] ubifs: ubifs_dump: dump log area Dongsheng Yang
2015-12-21  8:41 ` [PATCH 20/38] ubifs: introduce lprops lib Dongsheng Yang
2015-12-21  8:41 ` [PATCH 21/38] ubifs: lpt: implement functions to scan lpt Dongsheng Yang
2015-12-21  8:41 ` [PATCH 22/38] ubifs: ubifs_dump: dump lpt area Dongsheng Yang
2015-12-21  8:41 ` [PATCH 23/38] ubifs: ubifs_dump: dump index area Dongsheng Yang
2015-12-21  8:41 ` [PATCH 24/38] ubifs: defs.h: introduce some compatible definitions about integer such as __u16 Dongsheng Yang
2015-12-21  8:41 ` [PATCH 25/38] ubifs: introduce hexdump lib Dongsheng Yang
2015-12-21  8:41 ` [PATCH 26/38] ubifs: ubifs_dump: dump data in hex format Dongsheng Yang
2015-12-21  8:41 ` [PATCH 27/38] gitignore: add ubifs_dump to gitignore Dongsheng Yang
2015-12-21  8:41 ` [PATCH 28/38] ubifs: add complete version of list.h Dongsheng Yang
2015-12-21  8:41 ` [PATCH 29/38] ubifs: fix typo in ubifs_read Dongsheng Yang
2015-12-21  8:41 ` [PATCH 30/38] Make cli byte parsing from ubi-utils available for all tools Dongsheng Yang
2015-12-21  8:41 ` [PATCH 31/38] ubifs: add decompression functions Dongsheng Yang
2015-12-21  8:41 ` [PATCH 32/38] ubifs: remove ununsed ubifs context from key helpers Dongsheng Yang
2015-12-21  8:41 ` [PATCH 33/38] ubifs: keep scan buffer in ubifs_info Dongsheng Yang
2015-12-21  8:41 ` [PATCH 34/38] ubifs: extend master scanning code Dongsheng Yang
2015-12-21  8:41 ` [PATCH 35/38] ubifs: add missing include to defs.h Dongsheng Yang
2015-12-21  8:41 ` [PATCH 36/38] ubifs: Add more key helper functions Dongsheng Yang
2015-12-21  8:42 ` [PATCH 37/38] ubifs: add emubi, a minimal UBI emulation layer Dongsheng Yang
2015-12-21  8:42 ` [PATCH 38/38] UBIFS: introduce ubifs_unpacker tool Dongsheng Yang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.