1 // SPDX-License-Identifier: GPL-2.0-or-later 2 3 #include "common.h" 4 #define BUFLEN 128 5 6 int read_uint_from_file(char *dirname, char *filename, unsigned int *i) 7 { 8 FILE *f; 9 char fname[BUFLEN]; 10 int ret = -1; 11 12 snprintf(fname, sizeof(fname), "%s/%s", dirname, filename); 13 14 f = fopen(fname, "r"); 15 if (!f) 16 return ret; 17 18 if (fscanf(f, "%u", i) == 1) 19 ret = 0; 20 21 fclose(f); 22 return ret; 23 } 24 25 char *read_string_from_file(const char *dirname, const char *filename, char *buf, size_t bufsz) 26 { 27 FILE *f; 28 char fname[BUFLEN]; 29 int i; 30 31 snprintf(fname, sizeof(fname), "%s/%s", dirname, filename); 32 33 f = fopen(fname, "r"); 34 if (!f) 35 return NULL; 36 37 if (fgets(buf, bufsz, f) == NULL) { 38 fclose(f); 39 return NULL; 40 } 41 42 fclose(f); 43 44 /* make sure the string is \0 terminated */ 45 buf[bufsz - 1] = '\0'; 46 47 /* remove trailing whitespace */ 48 i = strlen(buf) - 1; 49 while (i > 0 && buf[i] <= ' ') 50 buf[i--] = '\0'; 51 52 return buf; 53 } 54 55 /* adapted from procd/utils.c -> should go to libubox */ 56 char *get_var_from_file(const char *filename, const char *name, char *out, int len) 57 { 58 char line[1024], *c, *sptr; 59 60 int fd = open(filename, O_RDONLY); 61 if (fd == -1) 62 return NULL; 63 64 ssize_t r = read(fd, line, sizeof(line) - 1); 65 close(fd); 66 67 if (r <= 0) 68 return NULL; 69 70 line[r] = 0; 71 72 for (c = strtok_r(line, " \t\n", &sptr); c; 73 c = strtok_r(NULL, " \t\n", &sptr)) { 74 char *sep = strchr(c, '='); 75 if (sep == NULL) 76 continue; 77 78 ssize_t klen = sep - c; 79 if (strncmp(name, c, klen) || name[klen] != 0) 80 continue; 81 82 strncpy(out, &sep[1], len); 83 out[len-1] = '\0'; 84 return out; 85 } 86 87 return NULL; 88 } 89 90 int block_file_identify(FILE *f, uint64_t offset) 91 { 92 uint32_t magic = 0; 93 size_t n; 94 95 if (fseeko(f, offset, SEEK_SET) < 0) 96 return -1; 97 98 n = fread(&magic, sizeof(magic), 1, f); 99 if (magic == cpu_to_le32(0x88b1f)) 100 return FS_TARGZ; 101 102 if (magic == cpu_to_be32(0xdeadc0de)) 103 return FS_DEADCODE; 104 105 if (fseeko(f, offset + 0x400, SEEK_SET) < 0) 106 return -1; 107 108 n = fread(&magic, sizeof(magic), 1, f); 109 if (n != 1) 110 return -1; 111 112 if (magic == cpu_to_le32(0xF2F52010)) 113 return FS_F2FS; 114 115 magic = 0; 116 if (fseeko(f, offset + 0x438, SEEK_SET) < 0) 117 return -1; 118 119 n = fread(&magic, sizeof(magic), 1, f); 120 if (n != 1) 121 return -1; 122 123 if ((le32_to_cpu(magic) & 0xffff) == 0xef53) 124 return FS_EXT4; 125 126 return FS_NONE; 127 } 128 129 static bool use_f2fs(struct volume *v, uint64_t offset, const char *bdev) 130 { 131 char typeparam[BUFLEN]; 132 uint64_t size = 0; 133 bool ret = false; 134 int fd; 135 136 if (get_var_from_file("/proc/cmdline", "fstools_overlay_fstype", typeparam, sizeof(typeparam))) { 137 if (!strcmp("f2fs", typeparam)) 138 return true; 139 else if (!strcmp("ext4", typeparam)) 140 return false; 141 else if (strcmp("auto", typeparam)) 142 ULOG_ERR("unsupported overlay filesystem type: %s\n", typeparam); 143 } 144 145 fd = open(bdev, O_RDONLY); 146 if (fd < 0) 147 return false; 148 149 if (ioctl(fd, BLKGETSIZE64, &size) == 0) 150 ret = size - offset > F2FS_MINSIZE; 151 152 close(fd); 153 154 return ret; 155 } 156 157 static bool use_f2fs_compression(void) 158 { 159 char typeparam[BUFLEN]; 160 161 if (!get_var_from_file("/proc/cmdline", "fstools_overlay_compression_type", 162 typeparam, sizeof(typeparam))) 163 return false; 164 165 return typeparam[0] && strcmp(typeparam, "none"); 166 } 167 168 int block_volume_format(struct volume *v, uint64_t offset, const char *bdev) 169 { 170 int ret = 0; 171 char str[256]; 172 unsigned int skip_blocks = 0; 173 int fd; 174 __u32 deadc0de; 175 size_t sz; 176 177 switch (volume_identify(v)) { 178 case FS_DEADCODE: 179 case FS_NONE: 180 /* skip padding */ 181 fd = open(v->blk, O_RDONLY); 182 if (fd < 0) { 183 ret = EIO; 184 break; 185 } 186 do { 187 if (lseek(fd, (skip_blocks + 1) * 512, SEEK_SET) == (off_t) -1) { 188 ret = EIO; 189 break; 190 } 191 sz = read(fd, &deadc0de, sizeof(deadc0de)); 192 if (sz != sizeof(deadc0de)) { 193 ret = EIO; 194 break; 195 } 196 } while(++skip_blocks <= 512 && 197 (deadc0de == cpu_to_be32(0xdeadc0de) || deadc0de == 0xffffffff)); 198 199 close(fd); 200 if (ret) 201 break; 202 203 /* only try extracting in case gzip header is present */ 204 if (deadc0de != cpu_to_le32(0x88b1f)) 205 goto do_format; 206 207 /* fall-through */ 208 case FS_TARGZ: 209 snprintf(str, sizeof(str), 210 "dd if=%s bs=512 skip=%u 2>/dev/null | gzip -cd > /tmp/sysupgrade.tar 2>/dev/null", 211 v->blk, skip_blocks); 212 ret = system(str); 213 if (ret < 0) { 214 ULOG_ERR("failed extracting config backup from %s\n", v->blk); 215 break; 216 } 217 do_format: 218 ULOG_INFO("overlay filesystem in %s has not been formatted yet\n", v->blk); 219 if (use_f2fs(v, offset, bdev)) { 220 if (use_f2fs_compression()) { 221 ULOG_INFO("f2fs overlay compression enabled\n"); 222 snprintf(str, sizeof(str), 223 "mkfs.f2fs -q -f -O extra_attr,compression -l rootfs_data %s", v->blk); 224 } else { 225 snprintf(str, sizeof(str), "mkfs.f2fs -q -f -l rootfs_data %s", v->blk); 226 } 227 } else { 228 snprintf(str, sizeof(str), "mkfs.ext4 -q -F -L rootfs_data %s", v->blk); 229 } 230 231 ret = system(str); 232 break; 233 default: 234 break; 235 } 236 237 return ret; 238 } 239
This page was automatically generated by LXR 0.3.1. • OpenWrt