From f94c155aabec45a178b63c3a58a8ef2ef15dc589 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Tue, 7 Jan 2014 08:07:24 +0000 Subject: [PATCH] Move common patch file functions to separate source --- Makefile | 8 +-- patch.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++ patch.h | 26 ++++++++ patch_io.c | 165 +++++++------------------------------------------- 4 files changed, 228 insertions(+), 146 deletions(-) create mode 100644 patch.c create mode 100644 patch.h diff --git a/Makefile b/Makefile index 18ebed7..927fa66 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ all: realloc-inodes e2patch -realloc-inodes: realloc-inodes.c bmove.c ext2fsP.h Makefile patch_io.c patch_io.h - gcc -g -Wsign-compare -Wall -o realloc-inodes -lcom_err -lext2fs realloc-inodes.c bmove.c patch_io.c -e2patch: e2patch.c - gcc -g -Wsign-compare -Wall -o e2patch -lcom_err -lext2fs e2patch.c +realloc-inodes: realloc-inodes.c bmove.c ext2fsP.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 +e2patch: e2patch.c patch.c patch.h + gcc -g -Wsign-compare -Wall -o e2patch -lcom_err -lext2fs e2patch.c patch.c diff --git a/patch.c b/patch.c new file mode 100644 index 0000000..6aa852f --- /dev/null +++ b/patch.c @@ -0,0 +1,175 @@ +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE + +#include +#include +#include "patch.h" + +errcode_t retry_read(int fd, ssize_t size, void *buf) +{ + ssize_t r, done = 0; + while (done < size) + { + r = read(fd, buf+done, size-done); + if (r < 0 && errno != EAGAIN) + break; + done += r; + } + if (done < size) + return errno; + return 0; +} + +errcode_t retry_write(int fd, ssize_t size, void *buf) +{ + ssize_t r, done = 0; + while (done < size) + { + r = write(fd, buf+done, size-done); + if (r < 0 && errno != EAGAIN) + break; + done += r; + } + if (done < size) + return errno; + return 0; +} + +errcode_t retry_read_at(int fd, unsigned long long offset, ssize_t size, void *buf) +{ + if ((unsigned)ext2fs_llseek(fd, offset, SEEK_SET) != offset) + return errno ? errno : EXT2_ET_LLSEEK_FAILED; + return retry_read(fd, size, buf); +} + +errcode_t retry_write_at(int fd, unsigned long long offset, ssize_t size, void *buf) +{ + if ((unsigned)ext2fs_llseek(fd, offset, SEEK_SET) != offset) + return errno ? errno : EXT2_ET_LLSEEK_FAILED; + return retry_write(fd, size, buf); +} + +errcode_t ext2fs_patch_read_bmap(struct ext2fs_patch_file *data) +{ + errcode_t retval = 0; + int bufsize = 65536; + blk64_t i, r; + void *buf = malloc(bufsize); + if (!buf) + return ENOMEM; + ext2fs_llseek(data->patch_fd, data->size*data->block_size, SEEK_SET); + for (i = 0; i < data->size/8; ) + { + r = bufsize; + if (data->size/8 - i < r) + r = data->size/8 - i; + retval = retry_read(data->patch_fd, r, buf); + if (retval) + goto out; + ext2fs_set_generic_bmap_range(data->bmap, i*8, r*8, buf); + i += r; + } +out: + free(buf); + return retval; +} + +errcode_t ext2fs_patch_write_bmap(struct ext2fs_patch_file *data) +{ + errcode_t retval = 0; + int bufsize = 65536; + blk64_t i, r; + void *buf = malloc(bufsize); + if (!buf) + return ENOMEM; + ext2fs_llseek(data->patch_fd, data->size*data->block_size, SEEK_SET); + for (i = 0; i < data->size/8; ) + { + r = bufsize; + if (data->size/8 - i < r) + r = data->size/8 - i; + ext2fs_get_generic_bmap_range(data->bmap, i*8, r*8, buf); + retval = retry_write(data->patch_fd, r, buf); + if (retval) + goto out; + i += r; + } + write(data->patch_fd, &data->block_size, sizeof(__u32)); + write(data->patch_fd, &data->size, sizeof(blk64_t)); +out: + free(buf); + return 0; +} + +errcode_t ext2fs_patch_open(struct ext2fs_patch_file *data, char *patch_file) +{ + errcode_t retval = 0; + ext2_loff_t size; + data->block_size = 0; + data->size = 0; + data->bmap = NULL; + data->patch_file = strdup(patch_file); + data->patch_fd = open(data->patch_file, O_CREAT|O_RDWR, 0666); + if (data->patch_fd < 0) + return errno; + size = ext2fs_llseek(data->patch_fd, 0, SEEK_END); + if (size < 0) + 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)); + retval = ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP, NULL, + 0, data->size, data->size, "overwritten blocks", 0, &data->bmap); + if (retval) + return retval; + retval = ext2fs_patch_read_bmap(data); + } + return 0; +} + +errcode_t ext2fs_patch_close(struct ext2fs_patch_file *data) +{ + if (data) + { + if (data->bmap) + { + if (data->patch_fd >= 0) + ext2fs_patch_write_bmap(data); + ext2fs_free_generic_bmap(data->bmap); + data->bmap = NULL; + } + if (data->patch_fd >= 0) + { + close(data->patch_fd); + data->patch_fd = -1; + } + if (data->patch_file) + { + free(data->patch_file); + data->patch_file = NULL; + } + } + return 0; +} + +errcode_t ext2fs_patch_init_bmap(struct ext2fs_patch_file *data, io_channel channel) +{ + errcode_t retval = 0; + if (!data->bmap) + { + if (channel) + { + data->block_size = channel->block_size; + retval = ext2fs_get_device_size2(channel->name, data->block_size, &data->size); + if (retval) + return retval; + } + else if (!data->block_size || !data->size) + return EINVAL; + retval = ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP, NULL, + 0, data->size, data->size, "overwritten blocks", 0, &data->bmap); + } + return retval; +} diff --git a/patch.h b/patch.h new file mode 100644 index 0000000..670f99a --- /dev/null +++ b/patch.h @@ -0,0 +1,26 @@ +#ifndef E2_PATCH_H +#define E2_PATCH_H + +#include +#include + +struct ext2fs_patch_file +{ + char *patch_file; + int patch_fd; + __u32 block_size; + blk64_t size; + ext2fs_generic_bitmap bmap; +}; + +errcode_t retry_read(int fd, ssize_t size, void *buf); +errcode_t retry_write(int fd, ssize_t size, void *buf); +errcode_t retry_read_at(int fd, unsigned long long offset, ssize_t size, void *buf); +errcode_t retry_write_at(int fd, unsigned long long offset, ssize_t size, void *buf); +errcode_t ext2fs_patch_read_bmap(struct ext2fs_patch_file *data); +errcode_t ext2fs_patch_write_bmap(struct ext2fs_patch_file *data); +errcode_t ext2fs_patch_open(struct ext2fs_patch_file *data, char *patch_file); +errcode_t ext2fs_patch_close(struct ext2fs_patch_file *data); +errcode_t ext2fs_patch_init_bmap(struct ext2fs_patch_file *data, io_channel channel); + +#endif diff --git a/patch_io.c b/patch_io.c index c3021d5..0bf7e9f 100644 --- a/patch_io.c +++ b/patch_io.c @@ -28,6 +28,8 @@ #include #include +#include "patch.h" + #ifdef __GNUC__ #define ATTR(x) __attribute__(x) #else @@ -36,13 +38,10 @@ #define EXT2_CHECK_MAGIC(struct, code) if ((struct)->magic != (code)) return (code) -struct patch_private_data { - int magic; - char *patch_file; - int patch_fd; - int block_size; - blk64_t size; - ext2fs_generic_bitmap bmap; +struct patch_private_data +{ + int magic; + struct ext2fs_patch_file patch; /* The backing io channel */ io_channel real; /* to support offset in unix I/O manager */ @@ -93,56 +92,6 @@ errcode_t set_patch_io_patch_file(char *file) return 0; } -static void patch_read_bmap(struct patch_private_data *data, int fd) -{ - int bufsize = 65536; - blk64_t i, r; - void *buf = malloc(bufsize); - ext2fs_llseek(fd, data->size*data->block_size, SEEK_SET); - for (i = 0; i < data->size/8; ) - { - r = bufsize; - if (data->size/8 - i < r) - r = data->size/8 - i; - r = read(fd, buf, r); - if (r < 0) - { - r = 0; - if (errno != EAGAIN) - break; - } - ext2fs_set_generic_bmap_range(data->bmap, i*8, r*8, buf); - i += r; - } - free(buf); -} - -static void patch_write_bmap(struct patch_private_data *data, int fd) -{ - int bufsize = 65536; - blk64_t i, r; - void *buf = malloc(bufsize); - ext2fs_llseek(fd, data->size*data->block_size, SEEK_SET); - for (i = 0; i < data->size/8; ) - { - r = bufsize; - if (data->size/8 - i < r) - r = data->size/8 - i; - ext2fs_get_generic_bmap_range(data->bmap, i*8, r*8, buf); - r = write(fd, buf, r); - if (r < 0) - { - r = 0; - if (errno != EAGAIN) - break; - } - i += r; - } - free(buf); - write(fd, &data->block_size, sizeof(int)); - write(fd, &data->size, sizeof(blk64_t)); -} - static errcode_t patch_open(const char *name, int flags, io_channel *channel) { io_channel io = NULL; @@ -184,31 +133,9 @@ static errcode_t patch_open(const char *name, int flags, io_channel *channel) if (patch_file) { - long long size; - data->patch_file = strdup(patch_file); - data->patch_fd = open(data->patch_file, O_CREAT|O_RDWR, 0666); - if (data->patch_fd < 0) - { - retval = errno; + retval = ext2fs_patch_open(&data->patch, patch_file); + if (retval) goto cleanup; - } - size = ext2fs_llseek(data->patch_fd, 0, SEEK_END); - if (size < 0) - { - retval = errno; - goto cleanup; - } - if (size > sizeof(int)+sizeof(blk64_t)) - { - ext2fs_llseek(data->patch_fd, size-sizeof(int)-sizeof(blk64_t), 0); - read(data->patch_fd, &data->block_size, sizeof(int)); - read(data->patch_fd, &data->size, sizeof(blk64_t)); - retval = ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP, NULL, - 0, data->size, data->size, "overwritten blocks", 0, &data->bmap); - if (retval) - goto cleanup; - patch_read_bmap(data, data->patch_fd); - } } *channel = io; @@ -217,12 +144,7 @@ static errcode_t patch_open(const char *name, int flags, io_channel *channel) cleanup: if (data) { - if (data->bmap) - ext2fs_free_generic_bmap(data->bmap); - if (data->patch_fd >= 0) - close(data->patch_fd); - if (data->patch_file) - free(data->patch_file); + ext2fs_patch_close(&data->patch); if (data->real) io_channel_close(data->real); ext2fs_free_mem(&data); @@ -248,16 +170,7 @@ static errcode_t patch_close(io_channel channel) if (--channel->refcount > 0) return 0; - if (data->bmap) - { - if (data->patch_fd >= 0) - patch_write_bmap(data, data->patch_fd); - ext2fs_free_generic_bmap(data->bmap); - } - if (data->patch_fd >= 0) - close(data->patch_fd); - if (data->patch_file) - free(data->patch_file); + ext2fs_patch_close(&data->patch); if (data->real) retval = io_channel_close(data->real); ext2fs_free_mem(&channel->private_data); @@ -277,31 +190,14 @@ static errcode_t patch_set_blksize(io_channel channel, int blksize) data = (struct patch_private_data *) channel->private_data; EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); - if (data->block_size && data->block_size != blksize) + if (data->patch.block_size && data->patch.block_size != (unsigned)blksize) return EINVAL; if (data->real) retval = io_channel_set_blksize(data->real, blksize); - channel->block_size = blksize; + channel->block_size = (unsigned)blksize; return retval; } -static errcode_t re_read(int fd, unsigned long long offset, ssize_t size, void *buf) -{ - ssize_t r, done = 0; - if ((unsigned)ext2fs_llseek(fd, offset, SEEK_SET) != offset) - return errno ? errno : EXT2_ET_LLSEEK_FAILED; - while (done < size) - { - r = read(fd, buf+done, size-done); - if (r < 0 && errno != EAGAIN) - break; - done += r; - } - if (done < size) - return errno; - return 0; -} - static errcode_t patch_read_blk64(io_channel channel, unsigned long long block, int count, void *buf) { errcode_t retval = 0; @@ -316,8 +212,8 @@ static errcode_t patch_read_blk64(io_channel channel, unsigned long long block, { if (-count <= channel->block_size) { - if (data->bmap && ext2fs_test_generic_bitmap(data->bmap, block)) - retval = re_read(data->patch_fd, block*channel->block_size, -count, buf); + 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); else retval = io_channel_read_blk64(data->real, block, count, buf); return retval; @@ -327,15 +223,15 @@ static errcode_t patch_read_blk64(io_channel channel, unsigned long long block, } for (b = 0; b < count; ) { - for (n = 0; (b+n < count) && data->bmap && ext2fs_test_generic_bitmap(data->bmap, block+b+n); n++) {} + for (n = 0; (b+n < count) && data->patch.bmap && ext2fs_test_generic_bitmap(data->patch.bmap, block+b+n); n++) {} if (n > 0) { - retval = re_read(data->patch_fd, (block+b)*channel->block_size, n*channel->block_size, buf+b*channel->block_size); + retval = retry_read_at(data->patch.patch_fd, (block+b)*channel->block_size, n*channel->block_size, buf+b*channel->block_size); if (retval) break; b += n; } - for (n = 0; (b+n < count) && (!data->bmap || !ext2fs_test_generic_bitmap(data->bmap, block+b+n)); n++) {} + for (n = 0; (b+n < count) && (!data->patch.bmap || !ext2fs_test_generic_bitmap(data->patch.bmap, block+b+n)); n++) {} if (n > 0 && data->real) { retval = io_channel_read_blk64(data->real, block+b, n, buf+(block+b)*channel->block_size); @@ -353,21 +249,6 @@ static errcode_t patch_read_blk(io_channel channel, unsigned long block, int cou return patch_read_blk64(channel, block, count, buf); } -static errcode_t patch_check_bmap_init(struct patch_private_data *data, io_channel channel) -{ - errcode_t retval = 0; - if (!data->bmap) - { - data->block_size = channel->block_size; - retval = ext2fs_get_device_size2(channel->name, data->block_size, &data->size); - if (retval) - return retval; - retval = ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP, NULL, - 0, data->size, data->size, "overwritten blocks", 0, &data->bmap); - } - return retval; -} - static errcode_t patch_write_blk64(io_channel channel, unsigned long long block, int count, const void *buf) { struct patch_private_data *data; @@ -378,9 +259,9 @@ static errcode_t patch_write_blk64(io_channel channel, unsigned long long block, data = (struct patch_private_data *) channel->private_data; EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); - if ((unsigned)ext2fs_llseek(data->patch_fd, block*channel->block_size, SEEK_SET) != block*channel->block_size) + if ((unsigned)ext2fs_llseek(data->patch.patch_fd, block*channel->block_size, SEEK_SET) != block*channel->block_size) return errno ? errno : EXT2_ET_LLSEEK_FAILED; - retval = patch_check_bmap_init(data, channel); + retval = ext2fs_patch_init_bmap(&data->patch, channel); if (retval) return retval; if (count < 0) @@ -390,11 +271,11 @@ static errcode_t patch_write_blk64(io_channel channel, unsigned long long block, left = -count; count = 1; } - ext2fs_mark_block_bitmap_range2(data->bmap, block, count); + ext2fs_mark_block_bitmap_range2(data->patch.bmap, block, count); buf += left; while (left > 0) { - r = write(data->patch_fd, buf-left, left); + r = write(data->patch.patch_fd, buf-left, left); if (r < 0 && errno != EAGAIN) break; left -= r; @@ -426,8 +307,8 @@ static errcode_t patch_flush(io_channel channel) if (data->real) retval = io_channel_flush(data->real); - if (data->patch_fd) - fsync(data->patch_fd); + if (data->patch.patch_fd) + fsync(data->patch.patch_fd); return retval; }