123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- // SPDX-License-Identifier: GPL-2.0-or-later
- #include "common.h"
- #define BUFLEN 128
- int
- read_uint_from_file(char *dirname, char *filename, unsigned int *i)
- {
- FILE *f;
- char fname[BUFLEN];
- int ret = -1;
- snprintf(fname, sizeof(fname), "%s/%s", dirname, filename);
- f = fopen(fname, "r");
- if (!f)
- return ret;
- if (fscanf(f, "%u", i) == 1)
- ret = 0;
- fclose(f);
- return ret;
- }
- char
- *read_string_from_file(const char *dirname, const char *filename, char *buf, size_t bufsz)
- {
- FILE *f;
- char fname[BUFLEN];
- int i;
- snprintf(fname, sizeof(fname), "%s/%s", dirname, filename);
- f = fopen(fname, "r");
- if (!f)
- return NULL;
- if (fgets(buf, bufsz, f) == NULL) {
- fclose(f);
- return NULL;
- }
- fclose(f);
- /* make sure the string is \0 terminated */
- buf[bufsz - 1] = '\0';
- /* remove trailing whitespace */
- i = strlen(buf) - 1;
- while (i > 0 && buf[i] <= ' ')
- buf[i--] = '\0';
- return buf;
- }
- int block_file_identify(FILE *f, uint64_t offset)
- {
- uint32_t magic = 0;
- size_t n;
- if (fseeko(f, offset, SEEK_SET) < 0)
- return -1;
- n = fread(&magic, sizeof(magic), 1, f);
- 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;
- n = fread(&magic, sizeof(magic), 1, f);
- if (n != 1)
- return -1;
- if (magic == cpu_to_le32(0xF2F52010))
- return FS_F2FS;
- magic = 0;
- if (fseeko(f, offset + 0x438, SEEK_SET) < 0)
- return -1;
- n = fread(&magic, sizeof(magic), 1, f);
- if (n != 1)
- return -1;
- if ((le32_to_cpu(magic) & 0xffff) == 0xef53)
- return FS_EXT4;
- return FS_NONE;
- }
- static bool use_f2fs(struct volume *v, uint64_t offset, const char *bdev)
- {
- uint64_t size = 0;
- bool ret = false;
- int fd;
- fd = open(bdev, O_RDONLY);
- if (fd < 0)
- return false;
- if (ioctl(fd, BLKGETSIZE64, &size) == 0)
- ret = size - offset > F2FS_MINSIZE;
- close(fd);
- return ret;
- }
- 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),
- "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 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 -f -l rootfs_data %s", v->blk);
- else
- snprintf(str, sizeof(str), "mkfs.ext4 -q -F -L rootfs_data %s", v->blk);
- ret = system(str);
- break;
- default:
- break;
- }
- return ret;
- }
|