• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/fstools/libfstools/common.c

  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