diff options
author | Daniel Golle <daniel@makrotopia.org> | 2022-10-18 17:17:29 +0100 |
---|---|---|
committer | Daniel Golle <daniel@makrotopia.org> | 2022-10-18 19:34:41 +0100 |
commit | ee54c6bce17c48a725eadcc313b6ca8445f9ec8c (patch) | |
tree | 3f63843509ba97aba13b2221695e9ab800dc21e0 /libfstools/common.c | |
parent | 81785c1b9a9c1b797e7406a3542c01d972c61315 (diff) | |
download | fstools-ee54c6bce17c48a725eadcc313b6ca8445f9ec8c.tar.gz |
libfstools: skip JFFS2 padding on block devices
Images also used on devices with NOR flash may come with JFFS2 deadc0de
marking and padding up to the largest NOR erase size.
Skip that padding and take it into account when extracting sysupgrade
backup from mmc/block partition.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Diffstat (limited to 'libfstools/common.c')
-rw-r--r-- | libfstools/common.c | 46 |
1 files changed, 42 insertions, 4 deletions
diff --git a/libfstools/common.c b/libfstools/common.c index 55c1b87..e5b7bc3 100644 --- a/libfstools/common.c +++ b/libfstools/common.c @@ -63,9 +63,11 @@ int block_file_identify(FILE *f, uint64_t offset) return -1; n = fread(&magic, sizeof(magic), 1, f); - if (magic == cpu_to_le32(0x88b1f)) { + if (magic == cpu_to_le32(0x88b1f)) return FS_TARGZ; - } + + if (magic == cpu_to_be32(0xdeadc0de)) + return FS_DEADCODE; if (fseeko(f, offset + 0x400, SEEK_SET) < 0) return -1; @@ -113,17 +115,53 @@ int block_volume_format(struct volume *v, uint64_t offset, const char *bdev) { int ret = 0; char str[128]; + unsigned int skip_blocks = 0; + int fd; + __u32 deadc0de; + size_t sz; switch (volume_identify(v)) { + case FS_DEADCODE: + /* skip padding */ + fd = open(v->blk, O_RDONLY); + if (fd < 0) { + ret = EIO; + break; + } + do { + if (lseek(fd, (skip_blocks + 1) * 512, SEEK_SET) == (off_t) -1) { + ret = EIO; + break; + } + sz = read(fd, &deadc0de, sizeof(deadc0de)); + if (sz != sizeof(deadc0de)) { + ret = EIO; + break; + } + } while(++skip_blocks <= 512 && + (deadc0de == cpu_to_be32(0xdeadc0de) || deadc0de == 0xffffffff)); + + close(fd); + if (ret) + break; + + /* only try extracting in case gzip header is present */ + if (deadc0de != cpu_to_le32(0x88b1f)) + goto do_format; + + /* fall-through */ case FS_TARGZ: - snprintf(str, sizeof(str), "gzip -cd %s > /tmp/sysupgrade.tar", v->blk); + snprintf(str, sizeof(str), + "dd if=%s bs=512 skip=%u 2>/dev/null | gzip -cd > /tmp/sysupgrade.tar 2>/dev/null", + v->blk, skip_blocks); ret = system(str); if (ret < 0) { - ULOG_ERR("failed extracting %s\n", v->blk); + ULOG_ERR("failed extracting config backup from %s\n", v->blk); break; } /* fall-through */ case FS_NONE: +do_format: ULOG_INFO("overlay filesystem in %s has not been formatted yet\n", v->blk); if (use_f2fs(v, offset, bdev)) snprintf(str, sizeof(str), "mkfs.f2fs -q -l rootfs_data %s", v->blk); |