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>
33 #include <libubox/ulog.h>
35 #include "libfstools/libfstools.h"
36 #include "libfstools/volume.h"
37 #include "libfstools/snapshot.h"
40 config_write(int argc
, char **argv
)
42 struct volume
*v
= volume_find("rootfs_data");
48 ret
= volatile_write(v
, 0);
50 ret
= sentinel_write(v
, 0);
56 config_read(int argc
, char **argv
)
58 struct volume
*v
= volume_find("rootfs_data");
59 struct file_header conf
, sentinel
;
60 int next
, block
, ret
= 0;
66 block
= config_find(v
, &conf
, &sentinel
);
67 next
= snapshot_next_free(v
, &seq
);
68 if (is_config(&conf
) && conf
.seq
== seq
)
70 else if (!is_config(&sentinel
) || sentinel
.seq
!= seq
)
73 unlink("/tmp/config.tar.gz");
74 ret
= snapshot_read_file(v
, block
, "/tmp/config.tar.gz", CONF
);
77 ULOG_ERR("failed to read /tmp/config.tar.gz\n");
83 snapshot_write(int argc
, char **argv
)
85 struct volume
*v
= volume_find("rootfs_data");
92 block
= snapshot_next_free(v
, &seq
);
96 ret
= snapshot_write_file(v
, block
, "/tmp/snapshot.tar.gz", seq
+ 1, DATA
);
98 ULOG_ERR("failed to write /tmp/snapshot.tar.gz\n");
100 ULOG_INFO("wrote /tmp/snapshot.tar.gz\n");
106 snapshot_mark(int argc
, char **argv
)
108 __be32 owrt
= cpu_to_be32(OWRT
);
113 ULOG_WARN("This will remove all snapshot data stored on the system. Are you sure? [N/y]\n");
114 if (getchar() != 'y')
117 v
= volume_find("rootfs_data");
119 ULOG_ERR("MTD partition 'rootfs_data' not found\n");
123 fd
= open(v
->blk
, O_WRONLY
);
124 ULOG_INFO("%s - marking with 0x%08x\n", v
->blk
, owrt
);
126 ULOG_ERR("opening %s failed\n", v
->blk
);
130 sz
= write(fd
, &owrt
, sizeof(owrt
));
134 ULOG_ERR("writing %s failed: %s\n", v
->blk
, strerror(errno
));
142 snapshot_read(int argc
, char **argv
)
144 struct volume
*v
= volume_find("rootfs_data");;
145 int block
= 0, ret
= 0;
152 block
= atoi(argv
[2]);
153 if (block
>= (v
->size
/ v
->block_size
)) {
154 ULOG_ERR("invalid block %d > %" PRIu64
"\n",
155 block
, (uint64_t) v
->size
/ v
->block_size
);
158 snprintf(file
, sizeof(file
), "/tmp/snapshot/block%d.tar.gz", block
);
160 ret
= snapshot_read_file(v
, block
, file
, DATA
);
165 snprintf(file
, sizeof(file
), "/tmp/snapshot/block%d.tar.gz", block
);
166 block
= snapshot_read_file(v
, block
, file
, DATA
);
176 struct volume
*v
= volume_find("rootfs_data");
177 struct file_header hdr
= { 0 }, conf
;
183 ULOG_INFO("sectors:\t%" PRIu64
", block_size:\t%dK\n",
184 (uint64_t) v
->size
/ v
->block_size
, v
->block_size
/ 1024);
186 if (volume_read(v
, &hdr
, block
* v
->block_size
, sizeof(struct file_header
))) {
187 ULOG_ERR("scanning for next free block failed\n");
193 if (hdr
.magic
!= OWRT
)
196 if (hdr
.type
== DATA
)
197 ULOG_INFO("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
);
198 else if (hdr
.type
== CONF
)
199 ULOG_INFO("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
);
201 if (hdr
.type
== DATA
&& !valid_file_size(hdr
.length
))
202 block
+= pad_file_size(v
, hdr
.length
) / v
->block_size
;
203 } while (hdr
.type
== DATA
);
204 block
= config_find(v
, &conf
, &hdr
);
206 ULOG_INFO("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
);
211 int main(int argc
, char **argv
)
216 if (!strcmp(argv
[1], "config_read"))
217 return config_read(argc
, argv
);
218 if (!strcmp(argv
[1], "config_write"))
219 return config_write(argc
, argv
);
220 if (!strcmp(argv
[1], "read"))
221 return snapshot_read(argc
, argv
);
222 if (!strcmp(argv
[1], "write"))
223 return snapshot_write(argc
, argv
);
224 if (!strcmp(argv
[1], "mark"))
225 return snapshot_mark(argc
, argv
);
226 if (!strcmp(argv
[1], "info"))
227 return snapshot_info();