diff --git a/Makefile b/Makefile index 0188ca8..3c2fe53 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ all: realloc-inodes e2patch realloc-inodes: realloc-inodes.c bmove.c bmove.h check_uninit.c check_uninit.h Makefile patch_io.c patch_io.h patch.c patch.h - gcc -g -Wsign-compare -Wall -o realloc-inodes -lcom_err -lext2fs realloc-inodes.c bmove.c patch_io.c patch.c check_uninit.c + gcc -D_FILE_OFFSET_BITS=64 -g -Wsign-compare -Wall -o realloc-inodes -lcom_err -lext2fs realloc-inodes.c bmove.c patch_io.c patch.c check_uninit.c e2patch: e2patch.c patch.c patch.h - gcc -g -Wsign-compare -Wall -o e2patch -lcom_err -lext2fs e2patch.c patch.c + gcc -D_FILE_OFFSET_BITS=64 -g -Wsign-compare -Wall -o e2patch -lcom_err -lext2fs e2patch.c patch.c test-ext2.img: sudo sh test-mkimages.sh sudo chown $(shell id -u) *.img diff --git a/e2patch.c b/e2patch.c index bc4db5f..a3bde5d 100644 --- a/e2patch.c +++ b/e2patch.c @@ -45,7 +45,7 @@ errcode_t make_backup_patch(char *device, char *io_options, char *patch_file, ch blk64_t blk, start, buf_blocks; int eq; void *buf = NULL; - struct ext2fs_patch_file patch, backup; + struct ext2fs_patch_file patch = { 0 }, backup = { 0 }; retval = mgr->open(device, IO_FLAG_EXCLUSIVE, &io); if (retval) goto out; if (io_options && @@ -93,7 +93,7 @@ errcode_t apply_patch(char *device, char *io_options, char *patch_file) blk64_t blk, start, buf_blocks; int eq; void *buf = NULL; - struct ext2fs_patch_file patch; + struct ext2fs_patch_file patch = { 0 }; retval = mgr->open(device, IO_FLAG_EXCLUSIVE|IO_FLAG_RW, &io); if (retval) goto out; if (io_options && @@ -111,7 +111,7 @@ errcode_t apply_patch(char *device, char *io_options, char *patch_file) { if (start != blk) { - retval = retry_read_at(patch.patch_fd, start*patch.block_size, (blk-start)*patch.block_size, buf); + retval = retry_read_at(patch.patch_fd, patch.offset + start*patch.block_size, (blk-start)*patch.block_size, buf); if (retval) goto out; retval = io_channel_write_blk64(io, start, blk-start, buf); if (retval) goto out; diff --git a/patch.c b/patch.c index 159dbcb..4725d97 100644 --- a/patch.c +++ b/patch.c @@ -32,7 +32,7 @@ errcode_t retry_read(int fd, ssize_t size, void *buf) while (done < size) { r = read(fd, buf+done, size-done); - if (r < 0 && errno != EAGAIN) + if (!r || (r < 0 && errno != EAGAIN)) break; done += r; } @@ -47,7 +47,7 @@ errcode_t retry_write(int fd, ssize_t size, const void *buf) while (done < size) { r = write(fd, buf+done, size-done); - if (r < 0 && errno != EAGAIN) + if (r <= 0 && errno != EAGAIN) break; done += r; } @@ -78,7 +78,7 @@ errcode_t ext2fs_patch_read_bmap(struct ext2fs_patch_file *data) void *buf = malloc(bufsize); if (!buf) return ENOMEM; - ext2fs_llseek(data->patch_fd, data->size*data->block_size, SEEK_SET); + ext2fs_llseek(data->patch_fd, data->block_size, SEEK_SET); for (i = 0; i < data->size/8; ) { r = bufsize; @@ -100,10 +100,11 @@ errcode_t ext2fs_patch_write_bmap(struct ext2fs_patch_file *data) errcode_t retval = 0; int bufsize = 65536; blk64_t i, r; + struct patchbd_super s; void *buf = malloc(bufsize); if (!buf) return ENOMEM; - ext2fs_llseek(data->patch_fd, data->size*data->block_size, SEEK_SET); + ext2fs_llseek(data->patch_fd, data->block_size, SEEK_SET); for (i = 0; i < data->size/8; ) { r = bufsize; @@ -115,8 +116,11 @@ errcode_t ext2fs_patch_write_bmap(struct ext2fs_patch_file *data) goto out; i += r; } - write(data->patch_fd, &data->block_size, sizeof(__u32)); - write(data->patch_fd, &data->size, sizeof(blk64_t)); + ext2fs_llseek(data->patch_fd, 0, SEEK_SET); + s.magic = PATCHBD_MAGIC; + s.patch_block = data->block_size; + s.patch_size = data->size; + write(data->patch_fd, &s, sizeof(struct patchbd_super)); out: free(buf); return 0; @@ -126,8 +130,10 @@ errcode_t ext2fs_patch_open(struct ext2fs_patch_file *data, char *patch_file, in { errcode_t retval = 0; ext2_loff_t size; + struct patchbd_super s; data->block_size = 0; data->size = 0; + data->offset = 0; data->bmap = NULL; data->patch_file = strdup(patch_file); data->patch_fd = open(data->patch_file, flags|O_RDWR, 0666); @@ -138,9 +144,14 @@ errcode_t ext2fs_patch_open(struct ext2fs_patch_file *data, char *patch_file, in return errno; if (size > 0) { - size = ext2fs_llseek(data->patch_fd, size-sizeof(__u32)-sizeof(blk64_t), SEEK_SET); - read(data->patch_fd, &data->block_size, sizeof(__u32)); - read(data->patch_fd, &data->size, sizeof(blk64_t)); + size = ext2fs_llseek(data->patch_fd, 0, SEEK_SET); + read(data->patch_fd, &s, sizeof(struct patchbd_super)); + if (s.magic != PATCHBD_MAGIC) + return 0; + data->block_size = s.patch_block; +// if (data->block_size != 4096) +// return EINVAL; + data->size = s.patch_size; retval = ext2fs_patch_init_bmap(data, NULL); if (retval) return retval; @@ -181,7 +192,10 @@ errcode_t ext2fs_patch_init_bmap(struct ext2fs_patch_file *data, io_channel chan { if (channel) { + // channel is optional parameter, if passed, means 'take size from channel' data->block_size = channel->block_size; +// if (data->block_size != 4096) +// return EINVAL; retval = ext2fs_get_device_size2(channel->name, data->block_size, &data->size); if (retval) return retval; @@ -190,6 +204,7 @@ errcode_t ext2fs_patch_init_bmap(struct ext2fs_patch_file *data, io_channel chan return EINVAL; retval = ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP, NULL, 0, data->size, data->size, "overwritten blocks", 0, &data->bmap); + data->offset = data->block_size + ((((data->size+7)>>3)+(data->block_size-1))&~(data->block_size-1)); } return retval; } @@ -209,5 +224,5 @@ errcode_t ext2fs_patch_write_blk64(struct ext2fs_patch_file *data, unsigned long else size = count*data->block_size; ext2fs_mark_block_bitmap_range2(data->bmap, block, count); - return retry_write_at(data->patch_fd, block*data->block_size, size, buf); + return retry_write_at(data->patch_fd, data->offset + block*data->block_size, size, buf); } diff --git a/patch.h b/patch.h index 9cf23f1..a75bd21 100644 --- a/patch.h +++ b/patch.h @@ -31,15 +31,25 @@ #include #include +#define PATCHBD_MAGIC 0x44623950 // P9bD + struct ext2fs_patch_file { char *patch_file; int patch_fd; __u32 block_size; blk64_t size; + ext2_loff_t offset; ext2fs_generic_bitmap bmap; }; +struct patchbd_super +{ + __u32 magic; + __u32 patch_block; + __u64 patch_size; +}; + errcode_t retry_read(int fd, ssize_t size, void *buf); errcode_t retry_write(int fd, ssize_t size, const void *buf); errcode_t retry_read_at(int fd, unsigned long long offset, ssize_t size, void *buf); diff --git a/patch_io.c b/patch_io.c index de8fab9..d273216 100644 --- a/patch_io.c +++ b/patch_io.c @@ -222,7 +222,7 @@ static errcode_t patch_read_blk64(io_channel channel, unsigned long long block, if (-count <= channel->block_size) { if (data->patch.bmap && ext2fs_test_generic_bitmap(data->patch.bmap, block)) - retval = retry_read_at(data->patch.patch_fd, block*channel->block_size, -count, buf); + retval = retry_read_at(data->patch.patch_fd, data->patch.offset + block*channel->block_size, -count, buf); else retval = io_channel_read_blk64(data->real, block, count, buf); return retval; @@ -235,7 +235,7 @@ static errcode_t patch_read_blk64(io_channel channel, unsigned long long block, for (n = 0; (b+n < count) && data->patch.bmap && ext2fs_test_generic_bitmap(data->patch.bmap, block+b+n); n++) {} if (n > 0) { - retval = retry_read_at(data->patch.patch_fd, (block+b)*channel->block_size, n*channel->block_size, buf+b*channel->block_size); + retval = retry_read_at(data->patch.patch_fd, data->patch.offset + (block+b)*channel->block_size, n*channel->block_size, buf+b*channel->block_size); if (retval) break; b += n;