libfstools: skip JFFS2 padding when BLOCKSIZE was given
[project/fstools.git] / libfstools / mtd.c
index a1811c315e8332e4f810865d6960a24ad9edcf19..fe381450940e522833028cb26cfb0f720bd04365 100644 (file)
@@ -67,7 +67,7 @@ static void mtd_volume_close(struct mtd_volume *p)
                return;
 
        close(p->fd);
-       p->fd = 0;
+       p->fd = -1;
 }
 
 static int mtd_volume_load(struct mtd_volume *p)
@@ -76,15 +76,14 @@ static int mtd_volume_load(struct mtd_volume *p)
        struct mtd_info_user mtdInfo;
        struct erase_info_user mtdLockInfo;
 
-       if (p->fd)
-               return 0;
+       if (p->fd >= 0)
+               return (lseek(p->fd, 0, SEEK_SET) == -1);
 
        if (!p->chr)
                return -1;
 
        p->fd = mtd_open(p->chr, 0);
        if (p->fd < 0) {
-               p->fd = 0;
                ULOG_ERR("Could not open mtd device: %s\n", p->chr);
                return -1;
        }
@@ -165,6 +164,7 @@ static struct volume *mtd_volume_find(char *name)
        v->name = strdup(name);
        v->drv = &mtd_driver;
        p->idx = atoi(idx);
+       p->fd = -1;
 
        snprintf(buffer, sizeof(buffer), "/dev/mtdblock%s", idx);
        v->blk = strdup(buffer);
@@ -185,7 +185,6 @@ static int mtd_volume_identify(struct volume *v)
 {
        struct mtd_volume *p = container_of(v, struct mtd_volume, v);;
        __u32 deadc0de;
-       __u16 jffs2;
        size_t sz;
 
        if (mtd_volume_load(p)) {
@@ -196,10 +195,20 @@ static int mtd_volume_identify(struct volume *v)
        sz = read(p->fd, &deadc0de, sizeof(deadc0de));
 
        if (sz != sizeof(deadc0de)) {
-               ULOG_ERR("reading %s failed: %s\n", v->name, strerror(errno));
+               ULOG_ERR("reading %s failed: %m\n", v->name);
                return -1;
        }
 
+       if (deadc0de == ~0) {
+               struct mtd_oob_buf oob = {
+                       .start = 0,
+                       .length = sizeof(deadc0de),
+                       .ptr = (void *)&deadc0de,
+               };
+
+               ioctl(p->fd, MEMREADOOB, &oob);
+       }
+
        if (deadc0de == __be32_to_cpu(0x4f575254))
                return FS_SNAPSHOT;
 
@@ -208,10 +217,9 @@ static int mtd_volume_identify(struct volume *v)
                return FS_DEADCODE;
        }
 
-       jffs2 = __be16_to_cpu(deadc0de >> 16);
-       if (jffs2 == 0x1985) {
+       if (__be16_to_cpu(deadc0de) == 0x1985 ||
+           __be16_to_cpu(deadc0de >> 16) == 0x1985)
                return FS_JFFS2;
-       }
 
        if (v->type == UBIVOLUME && deadc0de == 0xffffffff) {
                return FS_JFFS2;
@@ -273,7 +281,7 @@ static int mtd_volume_init(struct volume *v)
 
        ret = ioctl(p->fd, MEMGETINFO, &mtdinfo);
        if (ret) {
-               ULOG_ERR("ioctl(%d, MEMGETINFO) failed: %s\n", p->fd, strerror(errno));
+               ULOG_ERR("ioctl(%d, MEMGETINFO) failed: %m\n", p->fd);
        } else {
                struct erase_info_user mtdlock;
 
@@ -328,6 +336,7 @@ static int mtd_volume_write(struct volume *v, void *buf, int offset, int length)
 
 static struct driver mtd_driver = {
        .name = "mtd",
+       .priority = 10,
        .find = mtd_volume_find,
        .init = mtd_volume_init,
        .erase = mtd_volume_erase,