2 * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2.1
6 * as published by the Free Software Foundation
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
16 #include <sys/types.h>
17 #include <sys/ioctl.h>
18 #include <sys/mount.h>
19 #include <mtd/mtd-user.h>
30 #include <libubox/list.h>
31 #include <libubox/blob.h>
32 #include <libubox/md5.h>
34 #include "libfstools/libfstools.h"
35 #include "libfstools/volume.h"
36 #include "libfstools/snapshot.h"
39 config_write(int argc, char **argv)
41 struct volume *v = volume_find("rootfs_data");
47 ret = volatile_write(v, 0);
49 ret = sentinel_write(v, 0);
55 config_read(int argc, char **argv)
57 struct volume *v = volume_find("rootfs_data");
58 struct file_header conf, sentinel;
59 int next, block, ret = 0;
65 block = config_find(v, &conf, &sentinel);
66 next = snapshot_next_free(v, &seq);
67 if (is_config(&conf) && conf.seq == seq)
69 else if (!is_config(&sentinel) || sentinel.seq != seq)
72 unlink("/tmp/config.tar.gz");
73 ret = snapshot_read_file(v, block, "/tmp/config.tar.gz", CONF);
76 fprintf(stderr, "failed to read /tmp/config.tar.gz\n");
82 snapshot_write(int argc, char **argv)
84 struct volume *v = volume_find("rootfs_data");
91 block = snapshot_next_free(v, &seq);
95 ret = snapshot_write_file(v, block, "/tmp/snapshot.tar.gz", seq + 1, DATA);
97 fprintf(stderr, "failed to write /tmp/snapshot.tar.gz\n");
99 fprintf(stderr, "wrote /tmp/snapshot.tar.gz\n");
105 snapshot_mark(int argc, char **argv)
107 __be32 owrt = cpu_to_be32(OWRT);
112 fprintf(stderr, "This will remove all snapshot data stored on the system. Are you sure? [N/y]\n");
113 if (getchar() != 'y')
116 v = volume_find("rootfs_data");
118 fprintf(stderr, "no rootfs_data was found\n");
122 fd = open(v->blk, O_WRONLY);
123 fprintf(stderr, "%s - marking with 0x%08x\n", v->blk, owrt);
125 fprintf(stderr, "opening %s failed\n", v->blk);
129 sz = write(fd, &owrt, sizeof(owrt));
133 fprintf(stderr, "writing %s failed: %s\n", v->blk, strerror(errno));
141 snapshot_read(int argc, char **argv)
143 struct volume *v = volume_find("rootfs_data");;
144 int block = 0, ret = 0;
151 block = atoi(argv[2]);
152 if (block >= (v->size / v->block_size)) {
153 fprintf(stderr, "invalid block %d > %" PRId64 "\n", block, v->size / v->block_size);
156 snprintf(file, sizeof(file), "/tmp/snapshot/block%d.tar.gz", block);
158 ret = snapshot_read_file(v, block, file, DATA);
163 snprintf(file, sizeof(file), "/tmp/snapshot/block%d.tar.gz", block);
164 block = snapshot_read_file(v, block, file, DATA);
174 struct volume *v = volume_find("rootfs_data");
175 struct file_header hdr = { 0 }, conf;
181 fprintf(stderr, "sectors:\t%" PRId64 ", block_size:\t%dK\n", v->size / v->block_size, v->block_size / 1024);
183 if (volume_read(v, &hdr, block * v->block_size, sizeof(struct file_header))) {
184 fprintf(stderr, "scanning for next free block failed\n");
190 if (hdr.magic != OWRT)
193 if (hdr.type == DATA)
194 fprintf(stderr, "block %d:\tsnapshot entry, size: %d, sectors: %d, sequence: %d\n", block, hdr.length, pad_file_size(v, hdr.length) / v->block_size, hdr.seq);
195 else if (hdr.type == CONF)
196 fprintf(stderr, "block %d:\tvolatile entry, size: %d, sectors: %d, sequence: %d\n", block, hdr.length, pad_file_size(v, hdr.length) / v->block_size, hdr.seq);
198 if (hdr.type == DATA && !valid_file_size(hdr.length))
199 block += pad_file_size(v, hdr.length) / v->block_size;
200 } while (hdr.type == DATA);
201 block = config_find(v, &conf, &hdr);
203 fprintf(stderr, "block %d:\tsentinel entry, size: %d, sectors: %d, sequence: %d\n", block, hdr.length, pad_file_size(v, hdr.length) / v->block_size, hdr.seq);
208 int main(int argc, char **argv)
213 if (!strcmp(argv[1], "config_read"))
214 return config_read(argc, argv);
215 if (!strcmp(argv[1], "config_write"))
216 return config_write(argc, argv);
217 if (!strcmp(argv[1], "read"))
218 return snapshot_read(argc, argv);
219 if (!strcmp(argv[1], "write"))
220 return snapshot_write(argc, argv);
221 if (!strcmp(argv[1], "mark"))
222 return snapshot_mark(argc, argv);
223 if (!strcmp(argv[1], "info"))
224 return snapshot_info();