From: hujianyang <hujianyang@huawei.com>
To: linux-mtd <linux-mtd@lists.infradead.org>
Cc: Artem Bityutskiy <dedekind1@gmail.com>
Subject: [PATCH 5/7] Add libubifs.c
Date: Mon, 7 Jul 2014 15:24:48 +0800 [thread overview]
Message-ID: <53BA4B40.70902@huawei.com> (raw)
In-Reply-To: <53BA491E.8060502@huawei.com>
These functions are copied from fs/ubifs/scan.c and fs/ubifs/debug.c
with some small changes. We don't have 'ubifs_info *c' in user space
and we don't need to check NODEs, just print what they are.
I think if data is corrupted, kernel will warn it and we can't check
it here because the checking codes are to heavy.
case SCANNED_A_NODE:
We will get the whole detailed info about this node if we set '-i'.
I just dump detailed info with some kinds of NODEs because I think
others are useless for debugging and you can simply add what you need
if it is necessary.
Signed-off-by: hujianyang <hujianyang@huawei.com>
---
ubi-utils/libubifs.c | 399 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 399 insertions(+)
create mode 100644 ubi-utils/libubifs.c
diff --git a/ubi-utils/libubifs.c b/ubi-utils/libubifs.c
new file mode 100644
index 0000000..86517fa
--- /dev/null
+++ b/ubi-utils/libubifs.c
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * 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.
+ *
+ * Author: Hu Jianyang <hujianyang@huawei.com>
+ *
+ * UBIFS library.
+ */
+
+#define PROGRAM_NAME "libubifs"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <libubifs.h>
+#include <mtd_swab.h>
+#include "common.h"
+
+static const char *get_key_fmt(int fmt)
+{
+ switch (fmt) {
+ case UBIFS_SIMPLE_KEY_FMT:
+ return "simple";
+ default:
+ return "unknown/invalid format";
+ }
+}
+
+static const char *get_key_hash(int hash)
+{
+ switch (hash) {
+ case UBIFS_KEY_HASH_R5:
+ return "R5";
+ case UBIFS_KEY_HASH_TEST:
+ return "test";
+ default:
+ return "unknown/invalid name hash";
+ }
+}
+
+static const char *node_ntype(int type)
+{
+ switch (type) {
+ case UBIFS_PAD_NODE:
+ return "padding node";
+ case UBIFS_SB_NODE:
+ return "superblock node";
+ case UBIFS_MST_NODE:
+ return "master node";
+ case UBIFS_REF_NODE:
+ return "reference node";
+ case UBIFS_INO_NODE:
+ return "inode node";
+ case UBIFS_DENT_NODE:
+ return "direntry node";
+ case UBIFS_XENT_NODE:
+ return "xentry node";
+ case UBIFS_DATA_NODE:
+ return "data node";
+ case UBIFS_TRUN_NODE:
+ return "truncate node";
+ case UBIFS_IDX_NODE:
+ return "indexing node";
+ case UBIFS_CS_NODE:
+ return "commit start node";
+ case UBIFS_ORPH_NODE:
+ return "orphan node";
+ default:
+ return "unknown node";
+ }
+}
+
+static const char *node_gtype(int type)
+{
+ switch (type) {
+ case UBIFS_NO_NODE_GROUP:
+ return "no node group";
+ case UBIFS_IN_NODE_GROUP:
+ return "in node group";
+ case UBIFS_LAST_OF_NODE_GROUP:
+ return "last of node group";
+ default:
+ return "unknown";
+ }
+}
+
+static void dump_ch(const struct ubifs_ch *ch)
+{
+ printf("\tmagic %#x\n", le32_to_cpu(ch->magic));
+ printf("\tcrc %#x\n", le32_to_cpu(ch->crc));
+ printf("\tnode_type %d (%s)\n", ch->node_type,
+ node_ntype(ch->node_type));
+ printf("\tgroup_type %d (%s)\n", ch->group_type,
+ node_gtype(ch->group_type));
+ printf("\tsqnum %llu\n",
+ (unsigned long long)le64_to_cpu(ch->sqnum));
+ printf("\tlen %u\n", le32_to_cpu(ch->len));
+}
+
+void ubifs_dump_node(const void *node)
+{
+ const struct ubifs_ch *ch = node;
+
+ if (le32_to_cpu(ch->magic) != UBIFS_NODE_MAGIC) {
+ printf("Not a node, first %zu bytes:\n", UBIFS_CH_SZ);
+ return;
+ }
+
+ dump_ch(node);
+
+ switch (ch->node_type) {
+ case UBIFS_PAD_NODE:
+ {
+ const struct ubifs_pad_node *pad = node;
+
+ printf("\tpad_len %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);
+
+ printf("\tkey_hash %d (%s)\n",
+ (int)sup->key_hash, get_key_hash(sup->key_hash));
+ printf("\tkey_fmt %d (%s)\n",
+ (int)sup->key_fmt, get_key_fmt(sup->key_fmt));
+ printf("\tflags %#x\n", sup_flags);
+ printf("\tbig_lpt %u\n",
+ !!(sup_flags & UBIFS_FLG_BIGLPT));
+ printf("\tspace_fixup %u\n",
+ !!(sup_flags & UBIFS_FLG_SPACE_FIXUP));
+ printf("\tmin_io_size %u\n", le32_to_cpu(sup->min_io_size));
+ printf("\tleb_size %u\n", le32_to_cpu(sup->leb_size));
+ printf("\tleb_cnt %u\n", le32_to_cpu(sup->leb_cnt));
+ printf("\tmax_leb_cnt %u\n", le32_to_cpu(sup->max_leb_cnt));
+ printf("\tmax_bud_bytes %llu\n",
+ (unsigned long long)le64_to_cpu(sup->max_bud_bytes));
+ printf("\tlog_lebs %u\n", le32_to_cpu(sup->log_lebs));
+ printf("\tlpt_lebs %u\n", le32_to_cpu(sup->lpt_lebs));
+ printf("\torph_lebs %u\n", le32_to_cpu(sup->orph_lebs));
+ printf("\tjhead_cnt %u\n", le32_to_cpu(sup->jhead_cnt));
+ printf("\tfanout %u\n", le32_to_cpu(sup->fanout));
+ printf("\tlsave_cnt %u\n", le32_to_cpu(sup->lsave_cnt));
+ printf("\tdefault_compr %u\n",
+ (int)le16_to_cpu(sup->default_compr));
+ printf("\trp_size %llu\n",
+ (unsigned long long)le64_to_cpu(sup->rp_size));
+ printf("\trp_uid %u\n", le32_to_cpu(sup->rp_uid));
+ printf("\trp_gid %u\n", le32_to_cpu(sup->rp_gid));
+ printf("\tfmt_version %u\n", le32_to_cpu(sup->fmt_version));
+ printf("\ttime_gran %u\n", le32_to_cpu(sup->time_gran));
+ printf("\tUUID %pUB\n", sup->uuid);
+ break;
+ }
+ case UBIFS_MST_NODE:
+ {
+ const struct ubifs_mst_node *mst = node;
+
+ printf("\thighest_inum %llu\n",
+ (unsigned long long)le64_to_cpu(mst->highest_inum));
+ printf("\tcommit number %llu\n",
+ (unsigned long long)le64_to_cpu(mst->cmt_no));
+ printf("\tflags %#x\n", le32_to_cpu(mst->flags));
+ printf("\tlog_lnum %u\n", le32_to_cpu(mst->log_lnum));
+ printf("\troot_lnum %u\n", le32_to_cpu(mst->root_lnum));
+ printf("\troot_offs %u\n", le32_to_cpu(mst->root_offs));
+ printf("\troot_len %u\n", le32_to_cpu(mst->root_len));
+ printf("\tgc_lnum %u\n", le32_to_cpu(mst->gc_lnum));
+ printf("\tihead_lnum %u\n", le32_to_cpu(mst->ihead_lnum));
+ printf("\tihead_offs %u\n", le32_to_cpu(mst->ihead_offs));
+ printf("\tindex_size %llu\n",
+ (unsigned long long)le64_to_cpu(mst->index_size));
+ printf("\tlpt_lnum %u\n", le32_to_cpu(mst->lpt_lnum));
+ printf("\tlpt_offs %u\n", le32_to_cpu(mst->lpt_offs));
+ printf("\tnhead_lnum %u\n", le32_to_cpu(mst->nhead_lnum));
+ printf("\tnhead_offs %u\n", le32_to_cpu(mst->nhead_offs));
+ printf("\tltab_lnum %u\n", le32_to_cpu(mst->ltab_lnum));
+ printf("\tltab_offs %u\n", le32_to_cpu(mst->ltab_offs));
+ printf("\tlsave_lnum %u\n", le32_to_cpu(mst->lsave_lnum));
+ printf("\tlsave_offs %u\n", le32_to_cpu(mst->lsave_offs));
+ printf("\tlscan_lnum %u\n", le32_to_cpu(mst->lscan_lnum));
+ printf("\tleb_cnt %u\n", le32_to_cpu(mst->leb_cnt));
+ printf("\tempty_lebs %u\n", le32_to_cpu(mst->empty_lebs));
+ printf("\tidx_lebs %u\n", le32_to_cpu(mst->idx_lebs));
+ printf("\ttotal_free %llu\n",
+ (unsigned long long)le64_to_cpu(mst->total_free));
+ printf("\ttotal_dirty %llu\n",
+ (unsigned long long)le64_to_cpu(mst->total_dirty));
+ printf("\ttotal_used %llu\n",
+ (unsigned long long)le64_to_cpu(mst->total_used));
+ printf("\ttotal_dead %llu\n",
+ (unsigned long long)le64_to_cpu(mst->total_dead));
+ printf("\ttotal_dark %llu\n",
+ (unsigned long long)le64_to_cpu(mst->total_dark));
+ break;
+ }
+ case UBIFS_REF_NODE:
+ {
+ const struct ubifs_ref_node *ref = node;
+
+ printf("\tlnum %u\n", le32_to_cpu(ref->lnum));
+ printf("\toffs %u\n", le32_to_cpu(ref->offs));
+ printf("\tjhead %u\n", le32_to_cpu(ref->jhead));
+ break;
+ }
+ case UBIFS_CS_NODE:
+ break;
+ case UBIFS_INO_NODE:
+ case UBIFS_DENT_NODE:
+ case UBIFS_XENT_NODE:
+ case UBIFS_DATA_NODE:
+ case UBIFS_TRUN_NODE:
+ case UBIFS_IDX_NODE:
+ case UBIFS_ORPH_NODE:
+ printf("cannot dump node, type not support\n");
+ default:
+ printf("node type %d was not recognized\n",
+ (int)ch->node_type);
+ }
+}
+
+/**
+ * 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);
+ uint8_t *p = buf;
+
+ printf("not a node\n");
+
+ while (pad_len < max_pad_len && *p++ == UBIFS_PADDING_BYTE)
+ pad_len += 1;
+
+ if (!pad_len || (pad_len & 7))
+ return SCANNED_GARBAGE;
+
+ printf("%d padding bytes\n", pad_len);
+
+ return pad_len;
+}
+
+/**
+ * ubifs_scan_a_node - scan for a node or padding.
+ * @buf: buffer to scan
+ * @size: logical eraseblock size
+ * @len: length of buffer
+ * @lnum: logical eraseblock number
+ * @offs: offset within the logical eraseblock
+ *
+ * This function returns a scanning code to indicate what was scanned.
+ */
+int ubifs_scan_a_node(void *buf, int leb_size, int len, int lnum, int offs)
+{
+ struct ubifs_ch *ch = buf;
+ uint32_t magic;
+
+ magic = le32_to_cpu(ch->magic);
+
+ if (magic == 0xFFFFFFFF) {
+ printf("hit empty space at LEB %d:%d\n", lnum, offs);
+ return SCANNED_EMPTY_SPACE;
+ }
+
+ if (magic != UBIFS_NODE_MAGIC)
+ return scan_padding_bytes(buf, len);
+
+ if (len < UBIFS_CH_SZ)
+ return SCANNED_GARBAGE;
+
+ printf("scanning %s at LEB %d:%d\n",
+ node_ntype(ch->node_type), lnum, offs);
+
+ /* No ubifs_check_nodei() perform here */
+
+ 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 > leb_size) {
+ printf("bad pad node at LEB %d:%d\n", lnum, offs);
+ ubifs_dump_node(pad);
+ return SCANNED_A_BAD_PAD_NODE;
+ }
+
+ /* Make the node pads to 8-byte boundary */
+ if ((node_len + pad_len) & 7) {
+ printf("bad padding length %d - %d\n",
+ offs, offs + node_len + pad_len);
+ return SCANNED_A_BAD_PAD_NODE;
+ }
+
+ printf("%d bytes padded at LEB %d:%d, offset now %d\n", pad_len,
+ lnum, offs, ALIGN(offs + node_len + pad_len, 8));
+
+ return node_len + pad_len;
+ }
+
+ return SCANNED_A_NODE;
+}
+
+/**
+ * ubifs_scan - scan a logical eraseblock.
+ * @lnum: logical eraseblock number
+ * @sbuf: scan buffer
+ * @size: size of @buf in bytes
+ * @offs: offset to start at (usually zero)
+ * @detailed: print NODEs detailed info
+ *
+ * This function scans LEB and prints complete information about
+ * its contents.
+ */
+void ubifs_scan(int lnum, void *sbuf, int leb_size, int offs, int detailed)
+{
+ void *buf = sbuf + offs;
+ int err, len = leb_size - offs;
+
+ printf("scan LEB %d:%d\n", lnum, offs);
+
+ while (len >= 8) {
+ struct ubifs_ch *ch = buf;
+ int node_len, ret;
+
+ printf("look at LEB %d:%d (%d bytes left)\n",
+ lnum, offs, len);
+
+ ret = ubifs_scan_a_node(buf, leb_size, len, lnum, offs);
+ 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:
+ printf("garbage\n");
+ goto corrupted;
+ case SCANNED_A_NODE:
+ if (detailed)
+ ubifs_dump_node(buf);
+ break;
+ case SCANNED_A_CORRUPT_NODE:
+ case SCANNED_A_BAD_PAD_NODE:
+ printf("bad node\n");
+ goto corrupted;
+ default:
+ printf("unknown\n");
+ err = -EINVAL;
+ goto error;
+ }
+
+ node_len = ALIGN(le32_to_cpu(ch->len), 8);
+ offs += node_len;
+ buf += node_len;
+ len -= node_len;
+ }
+
+ for (; len > 4; offs += 4, buf = buf + 4, len -= 4)
+ if (*(uint32_t *)buf != 0xffffffff)
+ break;
+ for (; len; offs++, buf++, len--)
+ if (*(uint8_t *)buf != 0xff) {
+ printf("corrupt empty space at LEB %d:%d\n",
+ lnum, offs);
+ goto corrupted;
+ }
+
+ printf("stop scanning LEB %d at offset %d\n", lnum, offs);
+ return;
+
+corrupted:
+ printf("corruption at LEB %d:%d\n", lnum, offs);
+ err = -EUCLEAN;
+error:
+ printf("LEB %d scanning failed, error %d\n", lnum, err);
+}
--
1.8.1.4
next prev parent reply other threads:[~2014-07-07 7:25 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-07 7:15 [PATCH RFC] ubi-utils: Add a new utility ubidump hujianyang
2014-07-07 7:17 ` [PATCH 1/7] UBI: Add a new ioctl to support ubidump hujianyang
2014-07-16 7:59 ` Artem Bityutskiy
2014-07-16 8:47 ` hujianyang
2014-07-16 10:30 ` Artem Bityutskiy
2014-07-07 7:19 ` [PATCH 2/7] Add new ioctl in userspace hujianyang
2014-07-07 7:20 ` [PATCH 3/7] Add ubifs-media.h hujianyang
2014-07-07 7:22 ` [PATCH 4/7] Add libubifs.h hujianyang
2014-07-07 7:24 ` hujianyang [this message]
2014-07-07 7:26 ` [PATCH 6/7] New utility ubidump hujianyang
2014-07-16 8:05 ` Artem Bityutskiy
2014-07-16 8:53 ` hujianyang
2014-07-16 10:37 ` Artem Bityutskiy
2014-07-16 11:27 ` hujianyang
2014-07-16 11:37 ` Artem Bityutskiy
2014-07-16 11:43 ` Artem Bityutskiy
2014-07-16 11:57 ` hujianyang
2014-07-21 16:20 ` Bill Pringlemeir
2014-07-22 8:15 ` hujianyang
2014-07-22 15:42 ` Bill Pringlemeir
2014-07-29 9:14 ` Artem Bityutskiy
2014-07-29 10:01 ` hujianyang
2014-07-07 7:27 ` [PATCH 7/7] Compile support hujianyang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=53BA4B40.70902@huawei.com \
--to=hujianyang@huawei.com \
--cc=dedekind1@gmail.com \
--cc=linux-mtd@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.