diff options
author | Sami Tolvanen <samitolvanen@google.com> | 2015-12-18 15:28:06 +0000 |
---|---|---|
committer | Sami Tolvanen <samitolvanen@google.com> | 2015-12-18 15:28:06 +0000 |
commit | f35a15d11e79892c06ce303e0b983c132955d261 (patch) | |
tree | c9c6c1305f738102ae9363ebd412751c734c1dff | |
parent | abf5656527ec767fdf306fbf703f73a10e4ae3d6 (diff) | |
download | extras-f35a15d11e79892c06ce303e0b983c132955d261.tar.gz |
fec: accept multiple input files for encoding
Make it possible to encode input files in pieces (not with -m).
Bug: 26251929
Change-Id: I09349368925e5e2f2a7961a712a1e933eb0b9ec8
-rw-r--r-- | verity/fec/image.cpp | 149 | ||||
-rw-r--r-- | verity/fec/image.h | 10 | ||||
-rw-r--r-- | verity/fec/main.cpp | 76 |
3 files changed, 147 insertions, 88 deletions
diff --git a/verity/fec/image.cpp b/verity/fec/image.cpp index 95bc88ee..a378c932 100644 --- a/verity/fec/image.cpp +++ b/verity/fec/image.cpp @@ -55,12 +55,12 @@ static void mmap_image_free(image *ctx) { if (ctx->input) { munmap(ctx->input, (size_t)ctx->inp_size); - TEMP_FAILURE_RETRY(close(ctx->inp_fd)); + close(ctx->inp_fd); } if (ctx->fec_mmap_addr) { munmap(ctx->fec_mmap_addr, FEC_BLOCKSIZE + ctx->fec_size); - TEMP_FAILURE_RETRY(close(ctx->fec_fd)); + close(ctx->fec_fd); } if (!ctx->inplace && ctx->output) { @@ -129,8 +129,15 @@ static void calculate_rounds(uint64_t size, image *ctx) ctx->rounds = fec_div_round_up(ctx->blocks, ctx->rs_n); } -static void mmap_image_load(int fd, image *ctx, bool output_needed) +static void mmap_image_load(const std::vector<int>& fds, image *ctx, + bool output_needed) { + if (fds.size() != 1) { + FATAL("multiple input files not supported with mmap\n"); + } + + int fd = fds.front(); + calculate_rounds(get_size(fd), ctx); /* check that we can memory map the file; on 32-bit platforms we are @@ -194,33 +201,43 @@ static int process_chunk(void *priv, const void *data, int len) } #endif -static void file_image_load(int fd, image *ctx) +static void file_image_load(const std::vector<int>& fds, image *ctx) { - uint64_t len = 0; + uint64_t size = 0; +#ifndef IMAGE_NO_SPARSE + std::vector<struct sparse_file *> files; +#endif + + for (auto fd : fds) { + uint64_t len = 0; #ifdef IMAGE_NO_SPARSE - if (ctx->sparse) { - FATAL("sparse files not supported\n"); - } + if (ctx->sparse) { + FATAL("sparse files not supported\n"); + } - len = get_size(fd); + len = get_size(fd); #else - struct sparse_file *file; + struct sparse_file *file; - if (ctx->sparse) { - file = sparse_file_import(fd, false, false); - } else { - file = sparse_file_import_auto(fd, false, ctx->verbose); - } + if (ctx->sparse) { + file = sparse_file_import(fd, false, false); + } else { + file = sparse_file_import_auto(fd, false, ctx->verbose); + } - if (!file) { - FATAL("failed to read file %s\n", ctx->fec_filename); - } + if (!file) { + FATAL("failed to read file %s\n", ctx->fec_filename); + } - len = sparse_file_len(file, false, false); + len = sparse_file_len(file, false, false); + files.push_back(file); #endif /* IMAGE_NO_SPARSE */ - calculate_rounds(len, ctx); + size += len; + } + + calculate_rounds(size, ctx); if (ctx->verbose) { INFO("allocating %" PRIu64 " bytes of memory\n", ctx->inp_size); @@ -234,21 +251,33 @@ static void file_image_load(int fd, image *ctx) memset(ctx->input, 0, ctx->inp_size); ctx->output = ctx->input; + ctx->pos = 0; #ifdef IMAGE_NO_SPARSE - if (!android::base::ReadFully(fd, ctx->input, ctx->inp_size)) { - FATAL("failed to read: %s\n", strerror(errno)); + for (auto fd : fds) { + uint64_t len = get_size(fd); + + if (!android::base::ReadFully(fd, &ctx->input[ctx->pos], len)) { + FATAL("failed to read: %s\n", strerror(errno)); + } + + ctx->pos += len; + close(fd); } #else - ctx->pos = 0; - sparse_file_callback(file, false, false, process_chunk, ctx); - sparse_file_destroy(file); -#endif + for (auto file : files) { + sparse_file_callback(file, false, false, process_chunk, ctx); + sparse_file_destroy(file); + } - TEMP_FAILURE_RETRY(close(fd)); + for (auto fd : fds) { + close(fd); + } +#endif } -bool image_load(const char *filename, image *ctx, bool output_needed) +bool image_load(const std::vector<std::string>& filenames, image *ctx, + bool output_needed) { assert(ctx->roots > 0 && ctx->roots < FEC_RSM); ctx->rs_n = FEC_RSM - ctx->roots; @@ -259,40 +288,47 @@ bool image_load(const char *filename, image *ctx, bool output_needed) flags = O_RDWR; } - int fd = TEMP_FAILURE_RETRY(open(filename, flags | O_LARGEFILE)); + std::vector<int> fds; - if (fd < 0) { - FATAL("failed to open file '%s': %s\n", filename, strerror(errno)); + for (auto fn : filenames) { + int fd = TEMP_FAILURE_RETRY(open(fn.c_str(), flags | O_LARGEFILE)); + + if (fd < 0) { + FATAL("failed to open file '%s': %s\n", fn.c_str(), strerror(errno)); + } + + fds.push_back(fd); } if (ctx->mmap) { - mmap_image_load(fd, ctx, output_needed); + mmap_image_load(fds, ctx, output_needed); } else { - file_image_load(fd, ctx); + file_image_load(fds, ctx); } return true; } -bool image_save(const char *filename, image *ctx) +bool image_save(const std::string& filename, image *ctx) { if (ctx->inplace && ctx->mmap) { return true; /* nothing to do */ } /* TODO: support saving as a sparse file */ - int fd = TEMP_FAILURE_RETRY(open(filename, O_WRONLY | O_CREAT | O_TRUNC, - 0666)); + int fd = TEMP_FAILURE_RETRY(open(filename.c_str(), + O_WRONLY | O_CREAT | O_TRUNC, 0666)); if (fd < 0) { - FATAL("failed to open file '%s: %s'\n", filename, strerror(errno)); + FATAL("failed to open file '%s: %s'\n", filename.c_str(), + strerror(errno)); } if (!android::base::WriteFully(fd, ctx->output, ctx->inp_size)) { FATAL("failed to write to output: %s\n", strerror(errno)); } - TEMP_FAILURE_RETRY(close(fd)); + close(fd); return true; } @@ -347,11 +383,11 @@ static void file_image_ecc_new(image *ctx) } } -bool image_ecc_new(const char *filename, image *ctx) +bool image_ecc_new(const std::string& filename, image *ctx) { assert(ctx->rounds > 0); /* image_load should be called first */ - ctx->fec_filename = filename; + ctx->fec_filename = filename.c_str(); ctx->fec_size = ctx->rounds * ctx->roots * FEC_BLOCKSIZE; if (ctx->mmap) { @@ -363,16 +399,17 @@ bool image_ecc_new(const char *filename, image *ctx) return true; } -bool image_ecc_load(const char *filename, image *ctx) +bool image_ecc_load(const std::string& filename, image *ctx) { - int fd = TEMP_FAILURE_RETRY(open(filename, O_RDONLY)); + int fd = TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY)); if (fd < 0) { - FATAL("failed to open file '%s': %s\n", filename, strerror(errno)); + FATAL("failed to open file '%s': %s\n", filename.c_str(), + strerror(errno)); } if (lseek64(fd, -FEC_BLOCKSIZE, SEEK_END) < 0) { - FATAL("failed to seek to header in '%s': %s\n", filename, + FATAL("failed to seek to header in '%s': %s\n", filename.c_str(), strerror(errno)); } @@ -383,27 +420,29 @@ bool image_ecc_load(const char *filename, image *ctx) if (!android::base::ReadFully(fd, header, sizeof(header))) { FATAL("failed to read %zd bytes from '%s': %s\n", sizeof(header), - filename, strerror(errno)); + filename.c_str(), strerror(errno)); } if (p->magic != FEC_MAGIC) { - FATAL("invalid magic in '%s': %08x\n", filename, p->magic); + FATAL("invalid magic in '%s': %08x\n", filename.c_str(), p->magic); } if (p->version != FEC_VERSION) { - FATAL("unsupported version in '%s': %u\n", filename, p->version); + FATAL("unsupported version in '%s': %u\n", filename.c_str(), + p->version); } if (p->size != sizeof(fec_header)) { - FATAL("unexpected header size in '%s': %u\n", filename, p->size); + FATAL("unexpected header size in '%s': %u\n", filename.c_str(), + p->size); } if (p->roots == 0 || p->roots >= FEC_RSM) { - FATAL("invalid roots in '%s': %u\n", filename, p->roots); + FATAL("invalid roots in '%s': %u\n", filename.c_str(), p->roots); } if (p->fec_size % p->roots || p->fec_size % FEC_BLOCKSIZE) { - FATAL("invalid length in '%s': %u\n", filename, p->fec_size); + FATAL("invalid length in '%s': %u\n", filename.c_str(), p->fec_size); } ctx->roots = (int)p->roots; @@ -416,19 +455,19 @@ bool image_ecc_load(const char *filename, image *ctx) } if (p->fec_size != ctx->fec_size) { - FATAL("inconsistent header in '%s'\n", filename); + FATAL("inconsistent header in '%s'\n", filename.c_str()); } if (lseek64(fd, 0, SEEK_SET) < 0) { - FATAL("failed to rewind '%s': %s", filename, strerror(errno)); + FATAL("failed to rewind '%s': %s", filename.c_str(), strerror(errno)); } if (!ctx->mmap && !android::base::ReadFully(fd, ctx->fec, ctx->fec_size)) { FATAL("failed to read %u bytes from '%s': %s\n", ctx->fec_size, - filename, strerror(errno)); + filename.c_str(), strerror(errno)); } - TEMP_FAILURE_RETRY(close(fd)); + close(fd); uint8_t hash[SHA256_DIGEST_LENGTH]; SHA256(ctx->fec, ctx->fec_size, hash); @@ -483,7 +522,7 @@ bool image_ecc_save(image *ctx) FATAL("failed to write to output: %s\n", strerror(errno)); } - TEMP_FAILURE_RETRY(close(fd)); + close(fd); } return true; diff --git a/verity/fec/image.h b/verity/fec/image.h index f235eb58..f0211fdf 100644 --- a/verity/fec/image.h +++ b/verity/fec/image.h @@ -18,6 +18,8 @@ #define __FEC_H__ #include <utils/Compat.h> +#include <string> +#include <vector> #include <fec/io.h> #include <fec/ecc.h> @@ -77,12 +79,12 @@ struct image_proc_ctx { void *rs; }; -extern bool image_load(const char *filename, image *ctx, +extern bool image_load(const std::vector<std::string>& filename, image *ctx, bool output_needed); -extern bool image_save(const char *filename, image *ctx); +extern bool image_save(const std::string& filename, image *ctx); -extern bool image_ecc_new(const char *filename, image *ctx); -extern bool image_ecc_load(const char *filename, image *ctx); +extern bool image_ecc_new(const std::string& filename, image *ctx); +extern bool image_ecc_load(const std::string& filename, image *ctx); extern bool image_ecc_save(image *ctx); extern bool image_process(image_proc_func f, image *ctx); diff --git a/verity/fec/main.cpp b/verity/fec/main.cpp index ee844f55..50d807e2 100644 --- a/verity/fec/main.cpp +++ b/verity/fec/main.cpp @@ -28,9 +28,8 @@ extern "C" { #include <stdbool.h> #include <stdlib.h> #include <string.h> + #include <android-base/file.h> -#include <fec/io.h> -#include <fec/ecc.h> #include "image.h" enum { @@ -141,7 +140,7 @@ static int print_size(image& ctx) return 0; } -static int get_start(int mode, const char *filename) +static int get_start(int mode, const std::string& filename) { fec::io fh(filename, O_RDONLY, FEC_VERITY_DISABLE); @@ -170,14 +169,14 @@ static int get_start(int mode, const char *filename) return 0; } -static int encode(image& ctx, const char *inp_filename, - const char *fec_filename) +static int encode(image& ctx, const std::vector<std::string>& inp_filenames, + const std::string& fec_filename) { if (ctx.inplace) { FATAL("invalid parameters: inplace can only used when decoding\n"); } - if (!image_load(inp_filename, &ctx, false)) { + if (!image_load(inp_filenames, &ctx, false)) { FATAL("failed to read input\n"); } @@ -185,8 +184,14 @@ static int encode(image& ctx, const char *inp_filename, FATAL("failed to allocate ecc\n"); } - INFO("encoding RS(255, %d) for '%s' to '%s'\n", ctx.rs_n, inp_filename, - fec_filename); + INFO("encoding RS(255, %d) to '%s' for input files:\n", ctx.rs_n, + fec_filename.c_str()); + + size_t n = 1; + + for (auto fn : inp_filenames) { + INFO("\t%zu: '%s'\n", n++, fn.c_str()); + } if (ctx.verbose) { INFO("\traw fec size: %u\n", ctx.fec_size); @@ -206,28 +211,31 @@ static int encode(image& ctx, const char *inp_filename, return 0; } -static int decode(image& ctx, const char *inp_filename, - const char *fec_filename, const char *out_filename) +static int decode(image& ctx, const std::vector<std::string>& inp_filenames, + const std::string& fec_filename, std::string& out_filename) { + const std::string& inp_filename = inp_filenames.front(); + if (ctx.inplace && ctx.sparse) { FATAL("invalid parameters: inplace cannot be used with sparse " "files\n"); } if (!image_ecc_load(fec_filename, &ctx) || - !image_load(inp_filename, &ctx, !!out_filename)) { + !image_load(inp_filenames, &ctx, !out_filename.empty())) { FATAL("failed to read input\n"); } if (ctx.inplace) { - INFO("correcting '%s' using RS(255, %d) from '%s'\n", inp_filename, - ctx.rs_n, fec_filename); + INFO("correcting '%s' using RS(255, %d) from '%s'\n", + inp_filename.c_str(), ctx.rs_n, fec_filename.c_str()); out_filename = inp_filename; } else { INFO("decoding '%s' to '%s' using RS(255, %d) from '%s'\n", - inp_filename, out_filename ? out_filename : "<none>", ctx.rs_n, - fec_filename); + inp_filename.c_str(), + out_filename.empty() ? out_filename.c_str() : "<none>", ctx.rs_n, + fec_filename.c_str()); } if (ctx.verbose) { @@ -246,7 +254,7 @@ static int decode(image& ctx, const char *inp_filename, INFO("no errors found\n"); } - if (out_filename && !image_save(out_filename, &ctx)) { + if (!out_filename.empty() && !image_save(out_filename, &ctx)) { FATAL("failed to write output\n"); } @@ -256,9 +264,9 @@ static int decode(image& ctx, const char *inp_filename, int main(int argc, char **argv) { - char *fec_filename = NULL; - char *inp_filename = NULL; - char *out_filename = NULL; + std::string fec_filename; + std::string out_filename; + std::vector<std::string> inp_filenames; int mode = MODE_ENCODE; image ctx; @@ -327,14 +335,14 @@ int main(int argc, char **argv) return usage(); } mode = MODE_GETECCSTART; - inp_filename = optarg; + inp_filenames.push_back(optarg); break; case 'V': if (mode != MODE_ENCODE) { return usage(); } mode = MODE_GETVERITYSTART; - inp_filename = optarg; + inp_filenames.push_back(optarg); break; case 'v': ctx.verbose = true; @@ -352,19 +360,29 @@ int main(int argc, char **argv) assert(ctx.roots > 0 && ctx.roots < FEC_RSM); /* check for input / output parameters */ - if (mode == MODE_ENCODE || mode == MODE_DECODE) { + if (mode == MODE_ENCODE) { + /* allow multiple input files */ + for (int i = 0; i < (argc - 1); ++i) { + inp_filenames.push_back(argv[i]); + } + + if (inp_filenames.empty()) { + return usage(); + } + + /* the last one is the output file */ + fec_filename = argv[argc - 1]; + } else if (mode == MODE_DECODE) { if (argc < 2 || argc > 3) { return usage(); } else if (argc == 3) { - if (mode != MODE_DECODE || ctx.inplace) { + if (ctx.inplace) { return usage(); } out_filename = argv[2]; - } else { - out_filename = NULL; } - inp_filename = argv[0]; + inp_filenames.push_back(argv[0]); fec_filename = argv[1]; } @@ -373,11 +391,11 @@ int main(int argc, char **argv) return print_size(ctx); case MODE_GETECCSTART: case MODE_GETVERITYSTART: - return get_start(mode, inp_filename); + return get_start(mode, inp_filenames.front()); case MODE_ENCODE: - return encode(ctx, inp_filename, fec_filename); + return encode(ctx, inp_filenames, fec_filename); case MODE_DECODE: - return decode(ctx, inp_filename, fec_filename, out_filename); + return decode(ctx, inp_filenames, fec_filename, out_filename); default: abort(); } |