#include <libubox/md5.h>
#include "../fs-state.h"
-#include "../lib/mtd.h"
+#include "../driver/volume.h"
#define PATH_MAX 256
#define OWRT 0x4f575254
}
static int
-pad_file_size(int size)
+pad_file_size(struct volume *v, int size)
{
int mod;
size += sizeof(struct file_header);
- mod = size % erasesize;
+ mod = size % v->block_size;
if (mod) {
size -= mod;
- size += erasesize;
+ size += v->block_size;
}
return size;
}
static int
-snapshot_next_free(int fd, uint32_t *seq)
+snapshot_next_free(struct volume *v, uint32_t *seq)
{
struct file_header hdr = { 0 };
int block = 0;
*seq = rand();
do {
- if (mtd_read_buffer(fd, &hdr, block * erasesize, sizeof(struct file_header))) {
+ if (volume_read(v, &hdr, block * v->block_size, sizeof(struct file_header))) {
fprintf(stderr, "scanning for next free block failed\n");
return 0;
}
if (*seq + 1 != hdr.seq && block)
return block;
*seq = hdr.seq;
- block += pad_file_size(hdr.length) / erasesize;
+ block += pad_file_size(v, hdr.length) / v->block_size;
}
} while (hdr.type == DATA);
}
static int
-config_find(int fd, struct file_header *conf, struct file_header *sentinel)
+config_find(struct volume *v, struct file_header *conf, struct file_header *sentinel)
{
uint32_t seq;
- int i, next = snapshot_next_free(fd, &seq);
+ int i, next = snapshot_next_free(v, &seq);
conf->magic = sentinel->magic = 0;
- if (!mtd_read_buffer(fd, conf, next, sizeof(*conf)))
+ if (!volume_read(v, conf, next, sizeof(*conf)))
be32_to_hdr(conf);
- for (i = (mtdsize / erasesize) - 1; i > 0; i--) {
- if (mtd_read_buffer(fd, sentinel, i * erasesize, sizeof(*sentinel))) {
+ for (i = (v->size / v->block_size) - 1; i > 0; i--) {
+ if (volume_read(v, sentinel, i * v->block_size, sizeof(*sentinel))) {
fprintf(stderr, "failed to read header\n");
return -1;
}
static int
snapshot_info(void)
{
- int fd = mtd_load("rootfs_data");
+ struct volume *v = volume_find("rootfs_data");
struct file_header hdr = { 0 }, conf;
int block = 0;
- if (fd < 1)
+ if (!v)
return -1;
- fprintf(stderr, "sectors:\t%d, erasesize:\t%dK\n", mtdsize / erasesize, erasesize / 1024);
+ fprintf(stderr, "sectors:\t%llu, block_size:\t%dK\n", v->size / v->block_size, v->block_size / 1024);
do {
- if (mtd_read_buffer(fd, &hdr, block * erasesize, sizeof(struct file_header))) {
+ if (volume_read(v, &hdr, block * v->block_size, sizeof(struct file_header))) {
fprintf(stderr, "scanning for next free block failed\n");
- close(fd);
return 0;
}
break;
if (hdr.type == DATA)
- fprintf(stderr, "block %d:\tsnapshot entry, size: %d, sectors: %d, sequence: %d\n", block, hdr.length, pad_file_size(hdr.length) / erasesize, hdr.seq);
+ 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);
else if (hdr.type == CONF)
- fprintf(stderr, "block %d:\tvolatile entry, size: %d, sectors: %d, sequence: %d\n", block, hdr.length, pad_file_size(hdr.length) / erasesize, hdr.seq);
+ 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);
if (hdr.type == DATA && !valid_file_size(hdr.length))
- block += pad_file_size(hdr.length) / erasesize;
+ block += pad_file_size(v, hdr.length) / v->block_size;
} while (hdr.type == DATA);
- block = config_find(fd, &conf, &hdr);
+ block = config_find(v, &conf, &hdr);
if (block > 0)
- fprintf(stderr, "block %d:\tsentinel entry, size: %d, sectors: %d, sequence: %d\n", block, hdr.length, pad_file_size(hdr.length) / erasesize, hdr.seq);
- close(fd);
+ 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);
+
return 0;
}
static int
-snapshot_write_file(int fd, int block, char *file, uint32_t seq, uint32_t type)
+snapshot_write_file(struct volume *v, int block, char *file, uint32_t seq, uint32_t type)
{
uint32_t md5[4] = { 0 };
struct file_header hdr;
goto out;
}
- if ((block * erasesize) + pad_file_size(s.st_size) > mtdsize) {
+ if ((block * v->block_size) + pad_file_size(v, s.st_size) > v->size) {
fprintf(stderr, "upgrade is too big for the flash\n");
goto out;
}
- mtd_erase(fd, block, (pad_file_size(s.st_size) / erasesize));
- mtd_erase(fd, block + (pad_file_size(s.st_size) / erasesize), 1);
+ volume_erase(v, block * v->block_size, pad_file_size(v, s.st_size));
+ volume_erase(v, block * v->block_size + pad_file_size(v, s.st_size), v->block_size);
hdr.length = s.st_size;
hdr.magic = OWRT;
memcpy(hdr.md5, md5, sizeof(md5));
hdr_to_be32(&hdr);
- if (mtd_write_buffer(fd, &hdr, block * erasesize, sizeof(struct file_header))) {
+ if (volume_write(v, &hdr, block * v->block_size, sizeof(struct file_header))) {
fprintf(stderr, "failed to write header\n");
goto out;
}
goto out;
}
- offset = (block * erasesize) + sizeof(struct file_header);
+ offset = (block * v->block_size) + sizeof(struct file_header);
while ((len = read(in, buffer, sizeof(buffer))) > 0) {
- if (mtd_write_buffer(fd, buffer, offset, len) < 0)
+ if (volume_write(v, buffer, offset, len) < 0)
goto out;
offset += len;
}
}
static int
-snapshot_read_file(int fd, int block, char *file, uint32_t type)
+snapshot_read_file(struct volume *v, int block, char *file, uint32_t type)
{
struct file_header hdr;
char buffer[256];
- int out;
+ int out, offset = 0;
- if (mtd_read_buffer(fd, &hdr, block * erasesize, sizeof(struct file_header))) {
+ if (volume_read(v, &hdr, block * v->block_size, sizeof(struct file_header))) {
fprintf(stderr, "failed to read header\n");
return -1;
}
if (hdr.length < len)
len = hdr.length;
- if ((read(fd, buffer, len) != len) || (write(out, buffer, len) != len)) {
+ if ((volume_read(v, buffer, offset, len) != len) || (write(out, buffer, len) != len))
return -1;
- }
+ offset += len;
hdr.length -= len;
}
return 0;
}
- block += pad_file_size(hdr.length) / erasesize;
+ block += pad_file_size(v, hdr.length) / v->block_size;
return block;
}
static int
-sentinel_write(int fd, uint32_t _seq)
+sentinel_write(struct volume *v, uint32_t _seq)
{
int ret, block;
struct stat s;
return -1;
}
- snapshot_next_free(fd, &seq);
+ snapshot_next_free(v, &seq);
if (_seq)
seq = _seq;
- block = mtdsize / erasesize;
- block -= pad_file_size(s.st_size) / erasesize;
+ block = v->size / v->block_size;
+ block -= pad_file_size(v, s.st_size) / v->block_size;
if (block < 0)
block = 0;
- ret = snapshot_write_file(fd, block, "/tmp/config.tar.gz", seq, CONF);
+ ret = snapshot_write_file(v, block, "/tmp/config.tar.gz", seq, CONF);
if (ret)
fprintf(stderr, "failed to write sentinel\n");
else
}
static int
-volatile_write(int fd, uint32_t _seq)
+volatile_write(struct volume *v, uint32_t _seq)
{
int block, ret;
uint32_t seq;
- block = snapshot_next_free(fd, &seq);
+ block = snapshot_next_free(v, &seq);
if (_seq)
seq = _seq;
if (block < 0)
block = 0;
- ret = snapshot_write_file(fd, block, "/tmp/config.tar.gz", seq, CONF);
+ ret = snapshot_write_file(v, block, "/tmp/config.tar.gz", seq, CONF);
if (ret)
fprintf(stderr, "failed to write /tmp/config.tar.gz\n");
else
static int
config_write(int argc, char **argv)
{
- int fd, ret;
+ struct volume *v = volume_find("rootfs_data");
+ int ret;
- fd = mtd_load("rootfs_data");
- if (fd < 1) {
- fprintf(stderr, "failed to open rootfs_config\n");
+ if (!v)
return -1;
- }
- ret = volatile_write(fd, 0);
+ ret = volatile_write(v, 0);
if (!ret)
- ret = sentinel_write(fd, 0);
-
- close(fd);
+ ret = sentinel_write(v, 0);
return ret;
}
static int
config_read(int argc, char **argv)
{
+ struct volume *v = volume_find("rootfs_data");
struct file_header conf, sentinel;
- int fd, next, block, ret = 0;
+ int next, block, ret = 0;
uint32_t seq;
- fd = mtd_load("rootfs_data");
- if (fd < 1) {
- fprintf(stderr, "failed to open rootfs_data\n");
+ if (!v)
return -1;
- }
- block = config_find(fd, &conf, &sentinel);
- next = snapshot_next_free(fd, &seq);
+ block = config_find(v, &conf, &sentinel);
+ next = snapshot_next_free(v, &seq);
if (is_config(&conf) && conf.seq == seq)
block = next;
else if (!is_config(&sentinel) || sentinel.seq != seq)
return -1;
unlink("/tmp/config.tar.gz");
- ret = snapshot_read_file(fd, block, "/tmp/config.tar.gz", CONF);
+ ret = snapshot_read_file(v, block, "/tmp/config.tar.gz", CONF);
if (ret < 1)
fprintf(stderr, "failed to read /tmp/config.tar.gz\n");
- close(fd);
+
return ret;
}
static int
snapshot_write(int argc, char **argv)
{
- int mtd, block, ret;
+ struct volume *v = volume_find("rootfs_data");
+ int block, ret;
uint32_t seq;
- mtd = mtd_load("rootfs_data");
- if (mtd < 1) {
- fprintf(stderr, "failed to open rootfs_data\n");
+ if (!v)
return -1;
- }
- block = snapshot_next_free(mtd, &seq);
+ block = snapshot_next_free(v, &seq);
if (block < 0)
block = 0;
- ret = snapshot_write_file(mtd, block, "/tmp/snapshot.tar.gz", seq + 1, DATA);
+ ret = snapshot_write_file(v, block, "/tmp/snapshot.tar.gz", seq + 1, DATA);
if (ret)
fprintf(stderr, "failed to write /tmp/snapshot.tar.gz\n");
else
fprintf(stderr, "wrote /tmp/snapshot.tar.gz\n");
- close(mtd);
-
return ret;
}
static int
snapshot_mark(int argc, char **argv)
{
- FILE *fp;
__be32 owrt = cpu_to_be32(OWRT);
- char mtd[32];
+ struct volume *v;
size_t sz;
+ int fd;
fprintf(stderr, "This will remove all snapshot data stored on the system. Are you sure? [N/y]\n");
if (getchar() != 'y')
return -1;
- if (find_mtd_block("rootfs_data", mtd, sizeof(mtd))) {
+ v = volume_find("rootfs_data");
+ if (!v) {
fprintf(stderr, "no rootfs_data was found\n");
return -1;
}
- fp = fopen(mtd, "w");
- fprintf(stderr, "%s - marking with 0x4f575254\n", mtd);
- if (!fp) {
- fprintf(stderr, "opening %s failed\n", mtd);
+ fd = open(v->blk, O_WRONLY);
+ fprintf(stderr, "%s - marking with 0x%08x\n", v->blk, owrt);
+ if (fd < 0) {
+ fprintf(stderr, "opening %s failed\n", v->blk);
return -1;
}
- sz = fwrite(&owrt, sizeof(owrt), 1, fp);
- fclose(fp);
+ sz = write(fd, &owrt, sizeof(owrt));
+ close(fd);
if (sz != 1) {
- fprintf(stderr, "writing %s failed: %s\n", mtd, strerror(errno));
+ fprintf(stderr, "writing %s failed: %s\n", v->blk, strerror(errno));
return -1;
}
static int
snapshot_read(int argc, char **argv)
{
+ struct volume *v = volume_find("rootfs_data");;
+ int block = 0, ret = 0;
char file[64];
- int block = 0, fd, ret = 0;
- fd = mtd_load("rootfs_data");
- if (fd < 1) {
- fprintf(stderr, "failed to open rootfs_data\n");
+ if (!v)
return -1;
- }
if (argc > 1) {
block = atoi(argv[1]);
- if (block >= (mtdsize / erasesize)) {
- fprintf(stderr, "invalid block %d > %d\n", block, mtdsize / erasesize);
+ if (block >= (v->size / v->block_size)) {
+ fprintf(stderr, "invalid block %d > %llu\n", block, v->size / v->block_size);
goto out;
}
snprintf(file, sizeof(file), "/tmp/snapshot/block%d.tar.gz", block);
- ret = snapshot_read_file(fd, block, file, DATA);
+ ret = snapshot_read_file(v, block, file, DATA);
goto out;
}
do {
snprintf(file, sizeof(file), "/tmp/snapshot/block%d.tar.gz", block);
- block = snapshot_read_file(fd, block, file, DATA);
+ block = snapshot_read_file(v, block, file, DATA);
} while (block > 0);
out:
- close(fd);
return ret;
}
static int
snapshot_sync(void)
{
- int fd = mtd_load("rootfs_data");
+ struct volume *v = volume_find("rootfs_data");
struct file_header sentinel, conf;
int next, block = 0;
uint32_t seq;
- if (fd < 1)
+ if (!v)
return -1;
- next = snapshot_next_free(fd, &seq);
- block = config_find(fd, &conf, &sentinel);
+ next = snapshot_next_free(v, &seq);
+ block = config_find(v, &conf, &sentinel);
if (is_config(&conf) && conf.seq != seq) {
conf.magic = 0;
- mtd_erase(fd, next, 2);
+ volume_erase(v, next * v->block_size, 2 * v->block_size);
}
if (is_config(&sentinel) && (sentinel.seq != seq)) {
sentinel.magic = 0;
- mtd_erase(fd, block, 1);
+ volume_erase(v, block * v->block_size, v->block_size);
}
if (!is_config(&conf) && !is_config(&sentinel)) {
(memcmp(conf.md5, sentinel.md5, sizeof(conf.md5)) || (conf.seq != sentinel.seq))) ||
(is_config(&conf) && !is_config(&sentinel))) {
uint32_t seq;
- int next = snapshot_next_free(fd, &seq);
- int ret = snapshot_read_file(fd, next, "/tmp/config.tar.gz", CONF);
+ int next = snapshot_next_free(v, &seq);
+ int ret = snapshot_read_file(v, next, "/tmp/config.tar.gz", CONF);
if (ret > 0) {
- if (sentinel_write(fd, conf.seq))
+ if (sentinel_write(v, conf.seq))
fprintf(stderr, "failed to write sentinel data");
}
} else if (!is_config(&conf) && is_config(&sentinel) && next) {
- int ret = snapshot_read_file(fd, block, "/tmp/config.tar.gz", CONF);
+ int ret = snapshot_read_file(v, block, "/tmp/config.tar.gz", CONF);
if (ret > 0)
- if (volatile_write(fd, sentinel.seq))
+ if (volatile_write(v, sentinel.seq))
fprintf(stderr, "failed to write sentinel data");
} else
fprintf(stderr, "config in sync\n");
unlink("/tmp/config.tar.gz");
- close(fd);
return 0;
}