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 /* skip padding */ 126 fd = open(v->blk, O_RDONLY); 127 if (fd < 0) { 128 ret = EIO; 129 break; 130 } 131 do { 132 if (lseek(fd, (skip_blocks + 1) * 512, SEEK_SET) == (off_t) -1) { 133 ret = EIO; 134 break; 135 } 136 sz = read(fd, &deadc0de, sizeof(deadc0de)); 137 if (sz != sizeof(deadc0de)) { 138 ret = EIO; 139 break; 140 } 141 } while(++skip_blocks <= 512 && 142 (deadc0de == cpu_to_be32(0xdeadc0de) || deadc0de == 0xffffffff)); 143 144 close(fd); 145 if (ret) 146 break; 147 148 /* only try extracting in case gzip header is present */ 149 if (deadc0de != cpu_to_le32(0x88b1f)) 150 goto do_format; 151 152 /* fall-through */ 153 case FS_TARGZ: 154 snprintf(str, sizeof(str), 155 "dd if=%s bs=512 skip=%u 2>/dev/null | gzip -cd > /tmp/sysupgrade.tar 2>/dev/null", 156 v->blk, skip_blocks); 157 ret = system(str); 158 if (ret < 0) { 159 ULOG_ERR("failed extracting config backup from %s\n", v->blk); 160 break; 161 } 162 /* fall-through */ 163 case FS_NONE: 164 do_format: 165 ULOG_INFO("overlay filesystem in %s has not been formatted yet\n", v->blk); 166 if (use_f2fs(v, offset, bdev)) 167 snprintf(str, sizeof(str), "mkfs.f2fs -q -l rootfs_data %s", v->blk); 168 else 169 snprintf(str, sizeof(str), "mkfs.ext4 -q -L rootfs_data %s", v->blk); 170 171 ret = system(str); 172 break; 173 default: 174 break; 175 } 176 177 return ret; 178 } 179
This page was automatically generated by LXR 0.3.1. • OpenWrt