libfstools/mtd: attempt to read from OOB data if empty space is found
[project/fstools.git] / libfstools / mtd.c
index aae633e6ff1ff2eb29b2178fb22eb9d128bbcb03..c5dce500c20283f5610b198d2b63a90e1a641893 100644 (file)
@@ -36,31 +36,20 @@ struct mtd_volume {
 
 static struct driver mtd_driver;
 
-static int mtd_open_device(const char *dev)
-{
-       int ret;
-
-       ret = open(dev, O_RDWR | O_SYNC);
-       if (ret < 0)
-               ret = open(dev, O_RDONLY);
-
-       return ret;
-}
-
 static int mtd_open(const char *mtd, int block)
 {
        FILE *fp;
        char dev[PATH_MAX];
-       int i, ret;
+       int i, ret, flags = O_RDWR | O_SYNC;
 
        if ((fp = fopen("/proc/mtd", "r"))) {
                while (fgets(dev, sizeof(dev), fp)) {
                        if (sscanf(dev, "mtd%d:", &i) && strstr(dev, mtd)) {
                                snprintf(dev, sizeof(dev), "/dev/mtd%s/%d", (block ? "block" : ""), i);
-                               ret = mtd_open_device(dev);
+                               ret = open(dev, flags);
                                if (ret < 0) {
                                        snprintf(dev, sizeof(dev), "/dev/mtd%s%d", (block ? "block" : ""), i);
-                                       ret = mtd_open_device(dev);
+                                       ret = open(dev, flags);
                                }
                                fclose(fp);
                                return ret;
@@ -69,7 +58,7 @@ static int mtd_open(const char *mtd, int block)
                fclose(fp);
        }
 
-       return mtd_open_device(mtd);
+       return open(mtd, flags);
 }
 
 static void mtd_volume_close(struct mtd_volume *p)
@@ -198,7 +187,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)) {
@@ -213,6 +201,16 @@ static int mtd_volume_identify(struct volume *v)
                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;
 
@@ -221,10 +219,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;