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

Sources/fstools/snapshot.c

  1 /*
  2  * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
  3  *
  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
  7  *
  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.
 12  */
 13 
 14 #include <sys/stat.h>
 15 #include <sys/stat.h>
 16 #include <sys/types.h>
 17 #include <sys/ioctl.h>
 18 #include <sys/mount.h>
 19 #include <mtd/mtd-user.h>
 20 
 21 #include <glob.h>
 22 #include <fcntl.h>
 23 #include <stdio.h>
 24 #include <stdlib.h>
 25 #include <libgen.h>
 26 #include <unistd.h>
 27 #include <string.h>
 28 #include <inttypes.h>
 29 
 30 #include <libubox/list.h>
 31 #include <libubox/blob.h>
 32 #include <libubox/md5.h>
 33 #include <libubox/ulog.h>
 34 
 35 #include "libfstools/libfstools.h"
 36 #include "libfstools/volume.h"
 37 #include "libfstools/snapshot.h"
 38 
 39 static int
 40 config_write(int argc, char **argv)
 41 {
 42         struct volume *v = volume_find("rootfs_data");
 43         int ret;
 44 
 45         if (!v)
 46                 return -1;
 47 
 48         volume_init(v);
 49         ret = volatile_write(v, 0);
 50         if (!ret)
 51                 ret = sentinel_write(v, 0);
 52 
 53         return ret;
 54 }
 55 
 56 static int
 57 config_read(int argc, char **argv)
 58 {
 59         struct volume *v = volume_find("rootfs_data");
 60         struct file_header conf, sentinel;
 61         int next, block, ret = 0;
 62         uint32_t seq;
 63 
 64         if (!v)
 65                 return -1;
 66 
 67         volume_init(v);
 68         block = config_find(v, &conf, &sentinel);
 69         next = snapshot_next_free(v, &seq);
 70         if (is_config(&conf) && conf.seq == seq)
 71                 block = next;
 72         else if (!is_config(&sentinel) || sentinel.seq != seq)
 73                 return -1;
 74 
 75         unlink("/tmp/config.tar.gz");
 76         ret = snapshot_read_file(v, block, "/tmp/config.tar.gz", CONF);
 77 
 78         if (ret < 1)
 79                 ULOG_ERR("failed to read /tmp/config.tar.gz\n");
 80 
 81         return ret;
 82 }
 83 
 84 static int
 85 snapshot_write(int argc, char **argv)
 86 {
 87         struct volume *v = volume_find("rootfs_data");
 88         int block, ret;
 89         uint32_t seq;
 90 
 91         if (!v)
 92                 return -1;
 93 
 94         volume_init(v);
 95         block = snapshot_next_free(v, &seq);
 96         if (block < 0)
 97                 block = 0;
 98 
 99         ret = snapshot_write_file(v, block, "/tmp/snapshot.tar.gz", seq + 1, DATA);
100         if (ret)
101                 ULOG_ERR("failed to write /tmp/snapshot.tar.gz\n");
102         else
103                 ULOG_INFO("wrote /tmp/snapshot.tar.gz\n");
104 
105         return ret;
106 }
107 
108 static int
109 snapshot_mark(int argc, char **argv)
110 {
111         __be32 owrt = cpu_to_be32(OWRT);
112         struct volume *v;
113         size_t sz;
114         int fd;
115 
116         ULOG_WARN("This will remove all snapshot data stored on the system. Are you sure? [N/y]\n");
117         if (getchar() != 'y')
118                 return -1;
119 
120         v = volume_find("rootfs_data");
121         if (!v) {
122                 ULOG_ERR("MTD partition 'rootfs_data' not found\n");
123                 return -1;
124         }
125 
126         volume_init(v);
127 
128         fd = open(v->blk, O_WRONLY);
129         ULOG_INFO("%s - marking with 0x%08x\n", v->blk, owrt);
130         if (fd < 0) {
131                 ULOG_ERR("opening %s failed\n", v->blk);
132                 return -1;
133         }
134 
135         sz = write(fd, &owrt, sizeof(owrt));
136         close(fd);
137 
138         if (sz != 1) {
139                 ULOG_ERR("writing %s failed: %m\n", v->blk);
140                 return -1;
141         }
142 
143         return 0;
144 }
145 
146 static int
147 snapshot_read(int argc, char **argv)
148 {
149         struct volume *v = volume_find("rootfs_data");;
150         int block = 0, ret = 0;
151         char file[64];
152 
153         if (!v)
154                 return -1;
155 
156         volume_init(v);
157         if (argc > 2) {
158                 block = atoi(argv[2]);
159                 if (block >= (v->size / v->block_size)) {
160                         ULOG_ERR("invalid block %d > %" PRIu64 "\n",
161                                  block, (uint64_t) v->size / v->block_size);
162                         goto out;
163                 }
164                 snprintf(file, sizeof(file), "/tmp/snapshot/block%d.tar.gz", block);
165 
166                 ret = snapshot_read_file(v, block, file, DATA);
167                 goto out;
168         }
169 
170         do {
171                 snprintf(file, sizeof(file), "/tmp/snapshot/block%d.tar.gz", block);
172                 block = snapshot_read_file(v, block, file, DATA);
173         } while (block > 0);
174 
175 out:
176         return ret;
177 }
178 
179 static int
180 snapshot_info(void)
181 {
182         struct volume *v = volume_find("rootfs_data");
183         struct file_header hdr = { 0 }, conf;
184         int block = 0;
185 
186         if (!v)
187                 return -1;
188 
189         volume_init(v);
190         ULOG_INFO("sectors:\t%" PRIu64 ", block_size:\t%dK\n",
191                   (uint64_t) v->size / v->block_size, v->block_size / 1024);
192         do {
193                 if (volume_read(v, &hdr, block * v->block_size, sizeof(struct file_header))) {
194                         ULOG_ERR("scanning for next free block failed\n");
195                         return 0;
196                 }
197 
198                 be32_to_hdr(&hdr);
199 
200                 if (hdr.magic != OWRT)
201                         break;
202 
203                 if (hdr.type == DATA)
204                         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);
205                 else if (hdr.type == CONF)
206                         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);
207 
208                 if (hdr.type == DATA && !valid_file_size(hdr.length))
209                         block += pad_file_size(v, hdr.length) / v->block_size;
210         } while (hdr.type == DATA);
211         block = config_find(v, &conf, &hdr);
212         if (block > 0)
213                 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);
214 
215         return 0;
216 }
217 
218 int main(int argc, char **argv)
219 {
220         if (argc < 2)
221                 return -1;
222 
223         if (!strcmp(argv[1], "config_read"))
224                 return config_read(argc, argv);
225         if (!strcmp(argv[1], "config_write"))
226                 return config_write(argc, argv);
227         if (!strcmp(argv[1], "read"))
228                 return snapshot_read(argc, argv);
229         if (!strcmp(argv[1], "write"))
230                 return snapshot_write(argc, argv);
231         if (!strcmp(argv[1], "mark"))
232                 return snapshot_mark(argc, argv);
233         if (!strcmp(argv[1], "info"))
234                 return snapshot_info();
235         return -1;
236 }
237 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt