1 // SPDX-License-Identifier: GPL-2.0-or-later 2 3 #include "common.h" 4 #define BUFLEN 128 5 6 int 7 read_uint_from_file(char *dirname, char *filename, unsigned int *i) 8 { 9 FILE *f; 10 char fname[BUFLEN]; 11 int ret = -1; 12 13 snprintf(fname, sizeof(fname), "%s/%s", dirname, filename); 14 15 f = fopen(fname, "r"); 16 if (!f) 17 return ret; 18 19 if (fscanf(f, "%u", i) == 1) 20 ret = 0; 21 22 fclose(f); 23 return ret; 24 } 25 26 char 27 *read_string_from_file(const char *dirname, const char *filename, char *buf, size_t bufsz) 28 { 29 FILE *f; 30 char fname[BUFLEN]; 31 int i; 32 33 snprintf(fname, sizeof(fname), "%s/%s", dirname, filename); 34 35 f = fopen(fname, "r"); 36 if (!f) 37 return NULL; 38 39 if (fgets(buf, bufsz, f) == NULL) { 40 fclose(f); 41 return NULL; 42 } 43 44 fclose(f); 45 46 /* make sure the string is \0 terminated */ 47 buf[bufsz - 1] = '\0'; 48 49 /* remove trailing whitespace */ 50 i = strlen(buf) - 1; 51 while (i > 0 && buf[i] <= ' ') 52 buf[i--] = '\0'; 53 54 return buf; 55 } 56 57 int block_file_identify(FILE *f, uint64_t offset) 58 { 59 uint32_t magic = 0; 60 size_t n; 61 62 if (fseeko(f, offset, SEEK_SET) < 0) 63 return -1; 64 65 n = fread(&magic, sizeof(magic), 1, f); 66 if (magic == cpu_to_le32(0x88b1f)) 67 return FS_TARGZ; 68 69 if (magic == cpu_to_be32(0xdeadc0de)) 70 return FS_DEADCODE; 71 72 if (fseeko(f, offset + 0x400, SEEK_SET) < 0) 73 return -1; 74 75 n = fread(&magic, sizeof(magic), 1, f); 76 if (n != 1) 77 return -1; 78 79 if (magic == cpu_to_le32(0xF2F52010)) 80 return FS_F2FS; 81 82 magic = 0; 83 if (fseeko(f, offset + 0x438, SEEK_SET) < 0) 84 return -1; 85 86 n = fread(&magic, sizeof(magic), 1, f); 87 if (n != 1) 88 return -1; 89 90 if ((le32_to_cpu(magic) & 0xffff) == 0xef53) 91 return FS_EXT4; 92 93 return FS_NONE; 94 } 95 96 static bool use_f2fs(struct volume *v, uint64_t offset, const char *bdev) 97 { 98 uint64_t size = 0; 99 bool ret = false; 100 int fd; 101 102 fd = open(bdev, O_RDONLY); 103 if (fd < 0) 104 return false; 105 106 if (ioctl(fd, BLKGETSIZE64, &size) == 0) 107 ret = size - offset > F2FS_MINSIZE; 108 109 close(fd); 110 111 return ret; 112 } 113 114 int block_volume_format(struct volume *v, uint64_t offset, const char *bdev) 115 { 116 int ret = 0; 117 char str[128]; 118 unsigned int skip_blocks = 0; 119 int fd; 120 __u32 deadc0de; 121 size_t sz; 122 123 switch (volume_identify(v)) { 124 case FS_DEADCODE: 125 case FS_NONE: 126 /* skip padding */ 127 fd = open(v->blk, O_RDONLY); 128 if (fd < 0) { 129 ret = EIO; 130 break; 131 } 132 do { 133 if (lseek(fd, (skip_blocks + 1) * 512, SEEK_SET) == (off_t) -1) { 134 ret = EIO; 135 break; 136 } 137 sz = read(fd, &deadc0de, sizeof(deadc0de)); 138 if (sz != sizeof(deadc0de)) { 139 ret = EIO; 140 break; 141 } 142 } while(++skip_blocks <= 512 && 143 (deadc0de == cpu_to_be32(0xdeadc0de) || deadc0de == 0xffffffff)); 144 145 close(fd); 146 if (ret) 147 break; 148 149 /* only try extracting in case gzip header is present */ 150 if (deadc0de != cpu_to_le32(0x88b1f)) 151 goto do_format; 152 153 /* fall-through */ 154 case FS_TARGZ: 155 snprintf(str, sizeof(str), 156 "dd if=%s bs=512 skip=%u 2>/dev/null | gzip -cd > /tmp/sysupgrade.tar 2>/dev/null", 157 v->blk, skip_blocks); 158 ret = system(str); 159 if (ret < 0) { 160 ULOG_ERR("failed extracting config backup from %s\n", v->blk); 161 break; 162 } 163 do_format: 164 ULOG_INFO("overlay filesystem in %s has not been formatted yet\n", v->blk); 165 if (use_f2fs(v, offset, bdev)) 166 snprintf(str, sizeof(str), "mkfs.f2fs -q -f -l rootfs_data %s", v->blk); 167 else 168 snprintf(str, sizeof(str), "mkfs.ext4 -q -F -L rootfs_data %s", v->blk); 169 170 ret = system(str); 171 break; 172 default: 173 break; 174 } 175 176 return ret; 177 } 178
This page was automatically generated by LXR 0.3.1. • OpenWrt