X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=verity%2Ffec%2Fimage.cpp;h=4a70a02f9ab6030525110488bcad787285842834;hb=8bad827700bae35005872f3e6d674c5144fda8ff;hp=95bc88ee06e8286631d417b5419a4750d10d946a;hpb=6ccb30917e16d709c269e75c5d1ab85e34eb52e1;p=android-x86%2Fsystem-extras.git diff --git a/verity/fec/image.cpp b/verity/fec/image.cpp index 95bc88ee..4a70a02f 100644 --- a/verity/fec/image.cpp +++ b/verity/fec/image.cpp @@ -51,24 +51,7 @@ void image_init(image *ctx) memset(ctx, 0, sizeof(*ctx)); } -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)); - } - - if (ctx->fec_mmap_addr) { - munmap(ctx->fec_mmap_addr, FEC_BLOCKSIZE + ctx->fec_size); - TEMP_FAILURE_RETRY(close(ctx->fec_fd)); - } - - if (!ctx->inplace && ctx->output) { - delete[] ctx->output; - } -} - -static void file_image_free(image *ctx) +void image_free(image *ctx) { assert(ctx->input == ctx->output); @@ -79,19 +62,11 @@ static void file_image_free(image *ctx) if (ctx->fec) { delete[] ctx->fec; } -} - -void image_free(image *ctx) -{ - if (ctx->mmap) { - mmap_image_free(ctx); - } else { - file_image_free(ctx); - } image_init(ctx); } +#ifdef IMAGE_NO_SPARSE static uint64_t get_size(int fd) { struct stat st; @@ -114,6 +89,7 @@ static uint64_t get_size(int fd) return size; } +#endif static void calculate_rounds(uint64_t size, image *ctx) { @@ -129,56 +105,6 @@ 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) -{ - calculate_rounds(get_size(fd), ctx); - - /* check that we can memory map the file; on 32-bit platforms we are - limited to encoding at most 4 GiB files */ - if (ctx->inp_size > SIZE_MAX) { - FATAL("cannot mmap %" PRIu64 " bytes\n", ctx->inp_size); - } - - if (ctx->verbose) { - INFO("memory mapping '%s' (size %" PRIu64 ")\n", ctx->fec_filename, - ctx->inp_size); - } - - int flags = PROT_READ; - - if (ctx->inplace) { - flags |= PROT_WRITE; - } - - void *p = mmap(NULL, (size_t)ctx->inp_size, flags, MAP_SHARED, fd, 0); - - if (p == MAP_FAILED) { - FATAL("failed to mmap '%s' (size %" PRIu64 "): %s\n", - ctx->fec_filename, ctx->inp_size, strerror(errno)); - } - - ctx->inp_fd = fd; - ctx->input = (uint8_t *)p; - - if (ctx->inplace) { - ctx->output = ctx->input; - } else if (output_needed) { - if (ctx->verbose) { - INFO("allocating %" PRIu64 " bytes of memory\n", ctx->inp_size); - } - - ctx->output = new uint8_t[ctx->inp_size]; - - if (!ctx->output) { - FATAL("failed to allocate memory\n"); - } - - memcpy(ctx->output, ctx->input, ctx->inp_size); - } - - /* fd is closed in mmap_image_free */ -} - #ifndef IMAGE_NO_SPARSE static int process_chunk(void *priv, const void *data, int len) { @@ -194,33 +120,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& fds, image *ctx) { - uint64_t len = 0; + uint64_t size = 0; +#ifndef IMAGE_NO_SPARSE + std::vector 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 +170,32 @@ 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& filenames, image *ctx) { assert(ctx->roots > 0 && ctx->roots < FEC_RSM); ctx->rs_n = FEC_RSM - ctx->roots; @@ -259,83 +206,49 @@ 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 fds; - if (fd < 0) { - FATAL("failed to open file '%s': %s\n", filename, strerror(errno)); - } + for (const auto& fn : filenames) { + int fd = TEMP_FAILURE_RETRY(open(fn.c_str(), flags | O_LARGEFILE)); - if (ctx->mmap) { - mmap_image_load(fd, ctx, output_needed); - } else { - file_image_load(fd, ctx); + if (fd < 0) { + FATAL("failed to open file '%s': %s\n", fn.c_str(), strerror(errno)); + } + + fds.push_back(fd); } + 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; } -static void mmap_image_ecc_new(image *ctx) +bool image_ecc_new(const std::string& filename, image *ctx) { - if (ctx->verbose) { - INFO("mmaping '%s' (size %u)\n", ctx->fec_filename, ctx->fec_size); - } - - int fd = TEMP_FAILURE_RETRY(open(ctx->fec_filename, - O_RDWR | O_CREAT, 0666)); - - if (fd < 0) { - FATAL("failed to open file '%s': %s\n", ctx->fec_filename, - strerror(errno)); - } - - assert(sizeof(fec_header) <= FEC_BLOCKSIZE); - size_t fec_size = FEC_BLOCKSIZE + ctx->fec_size; - - if (ftruncate(fd, fec_size) == -1) { - FATAL("failed to ftruncate file '%s': %s\n", ctx->fec_filename, - strerror(errno)); - } - - if (ctx->verbose) { - INFO("memory mapping '%s' (size %zu)\n", ctx->fec_filename, fec_size); - } - - void *p = mmap(NULL, fec_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - - if (p == MAP_FAILED) { - FATAL("failed to mmap '%s' (size %zu): %s\n", ctx->fec_filename, - fec_size, strerror(errno)); - } + assert(ctx->rounds > 0); /* image_load should be called first */ - ctx->fec_fd = fd; - ctx->fec_mmap_addr = (uint8_t *)p; - ctx->fec = ctx->fec_mmap_addr; -} + ctx->fec_filename = filename.c_str(); + ctx->fec_size = ctx->rounds * ctx->roots * FEC_BLOCKSIZE; -static void file_image_ecc_new(image *ctx) -{ if (ctx->verbose) { INFO("allocating %u bytes of memory\n", ctx->fec_size); } @@ -345,34 +258,21 @@ static void file_image_ecc_new(image *ctx) if (!ctx->fec) { FATAL("failed to allocate %u bytes\n", ctx->fec_size); } -} - -bool image_ecc_new(const char *filename, image *ctx) -{ - assert(ctx->rounds > 0); /* image_load should be called first */ - - ctx->fec_filename = filename; - ctx->fec_size = ctx->rounds * ctx->roots * FEC_BLOCKSIZE; - - if (ctx->mmap) { - mmap_image_ecc_new(ctx); - } else { - file_image_ecc_new(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 +283,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 +318,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)) { + if (!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); @@ -447,10 +349,6 @@ bool image_ecc_save(image *ctx) uint8_t header[FEC_BLOCKSIZE]; uint8_t *p = header; - if (ctx->mmap) { - p = (uint8_t *)&ctx->fec_mmap_addr[ctx->fec_size]; - } - memset(p, 0, FEC_BLOCKSIZE); fec_header *f = (fec_header *)p; @@ -467,25 +365,23 @@ bool image_ecc_save(image *ctx) /* store a copy of the fec_header at the end of the header block */ memcpy(&p[sizeof(header) - sizeof(fec_header)], p, sizeof(fec_header)); - if (!ctx->mmap) { - assert(ctx->fec_filename); + assert(ctx->fec_filename); - int fd = TEMP_FAILURE_RETRY(open(ctx->fec_filename, - O_WRONLY | O_CREAT | O_TRUNC, 0666)); - - if (fd < 0) { - FATAL("failed to open file '%s': %s\n", ctx->fec_filename, - strerror(errno)); - } + int fd = TEMP_FAILURE_RETRY(open(ctx->fec_filename, + O_WRONLY | O_CREAT | O_TRUNC, 0666)); - if (!android::base::WriteFully(fd, ctx->fec, ctx->fec_size) || - !android::base::WriteFully(fd, header, sizeof(header))) { - FATAL("failed to write to output: %s\n", strerror(errno)); - } + if (fd < 0) { + FATAL("failed to open file '%s': %s\n", ctx->fec_filename, + strerror(errno)); + } - TEMP_FAILURE_RETRY(close(fd)); + if (!android::base::WriteFully(fd, ctx->fec, ctx->fec_size) || + !android::base::WriteFully(fd, header, sizeof(header))) { + FATAL("failed to write to output: %s\n", strerror(errno)); } + close(fd); + return true; }