From 8af3cf74df03f7528f9e2605ec7896a5daf0f711 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Jan 2015 13:43:55 +0100 Subject: import: support downloading bzip2-encoded images This way, we can import CoreOS images unmodified. --- src/import/import-job.c | 54 ++++++++++++++++++++++++++++++++++++++++++++----- src/import/import-job.h | 3 +++ src/import/import.c | 5 ++++- 3 files changed, 56 insertions(+), 6 deletions(-) (limited to 'src/import') diff --git a/src/import/import-job.c b/src/import/import-job.c index 322aa1a18c..337a5c5a22 100644 --- a/src/import/import-job.c +++ b/src/import/import-job.c @@ -37,6 +37,8 @@ ImportJob* import_job_unref(ImportJob *j) { lzma_end(&j->xz); else if (j->compressed == IMPORT_JOB_GZIP) inflateEnd(&j->gzip); + else if (j->compressed == IMPORT_JOB_BZIP2) + BZ2_bzDecompressEnd(&j->bzip2); if (j->checksum_context) gcry_md_close(j->checksum_context); @@ -178,7 +180,9 @@ static int import_job_write_uncompressed(ImportJob *j, void *p, size_t sz) { assert(j); assert(p); - assert(sz > 0); + + if (sz <= 0) + return 0; if (j->written_uncompressed + sz < j->written_uncompressed) { log_error("File too large, overflow"); @@ -209,7 +213,7 @@ static int import_job_write_uncompressed(ImportJob *j, void *p, size_t sz) { if (!GREEDY_REALLOC(j->payload, j->payload_allocated, j->payload_size + sz)) return log_oom(); - memcpy((uint8_t*) j->payload + j->payload_size, p, sz); + memcpy(j->payload + j->payload_size, p, sz); j->payload_size += sz; } @@ -223,7 +227,9 @@ static int import_job_write_compressed(ImportJob *j, void *p, size_t sz) { assert(j); assert(p); - assert(sz > 0); + + if (sz <= 0) + return 0; if (j->written_compressed + sz < j->written_compressed) { log_error("File too large, overflow"); @@ -300,6 +306,29 @@ static int import_job_write_compressed(ImportJob *j, void *p, size_t sz) { break; + case IMPORT_JOB_BZIP2: + j->bzip2.next_in = p; + j->bzip2.avail_in = sz; + + while (j->bzip2.avail_in > 0) { + uint8_t buffer[16 * 1024]; + + j->bzip2.next_out = (char*) buffer; + j->bzip2.avail_out = sizeof(buffer); + + r = BZ2_bzDecompress(&j->bzip2); + if (r != BZ_OK && r != BZ_STREAM_END) { + log_error("Decompression error."); + return -EIO; + } + + r = import_job_write_uncompressed(j, buffer, sizeof(buffer) - j->bzip2.avail_out); + if (r < 0) + return r; + } + + break; + default: assert_not_reached("Unknown compression"); } @@ -350,6 +379,9 @@ static int import_job_detect_compression(ImportJob *j) { static const uint8_t gzip_signature[] = { 0x1f, 0x8b }; + static const uint8_t bzip2_signature[] = { + 'B', 'Z', 'h' + }; _cleanup_free_ uint8_t *stub = NULL; size_t stub_size; @@ -358,18 +390,23 @@ static int import_job_detect_compression(ImportJob *j) { assert(j); - if (j->payload_size < MAX(sizeof(xz_signature), sizeof(gzip_signature))) + if (j->payload_size < MAX3(sizeof(xz_signature), + sizeof(gzip_signature), + sizeof(bzip2_signature))) return 0; if (memcmp(j->payload, xz_signature, sizeof(xz_signature)) == 0) j->compressed = IMPORT_JOB_XZ; else if (memcmp(j->payload, gzip_signature, sizeof(gzip_signature)) == 0) j->compressed = IMPORT_JOB_GZIP; + else if (memcmp(j->payload, bzip2_signature, sizeof(bzip2_signature)) == 0) + j->compressed = IMPORT_JOB_BZIP2; else j->compressed = IMPORT_JOB_UNCOMPRESSED; log_debug("Stream is XZ compressed: %s", yes_no(j->compressed == IMPORT_JOB_XZ)); log_debug("Stream is GZIP compressed: %s", yes_no(j->compressed == IMPORT_JOB_GZIP)); + log_debug("Stream is BZIP2 compressed: %s", yes_no(j->compressed == IMPORT_JOB_BZIP2)); if (j->compressed == IMPORT_JOB_XZ) { lzma_ret xzr; @@ -387,6 +424,13 @@ static int import_job_detect_compression(ImportJob *j) { return -EIO; } } + if (j->compressed == IMPORT_JOB_BZIP2) { + r = BZ2_bzDecompressInit(&j->bzip2, 0, 0); + if (r != BZ_OK) { + log_error("Failed to initialize bzip2 decoder."); + return -EIO; + } + } r = import_job_open_disk(j); if (r < 0) @@ -427,7 +471,7 @@ static size_t import_job_write_callback(void *contents, size_t size, size_t nmem goto fail; } - memcpy((uint8_t*) j->payload + j->payload_size, contents, sz); + memcpy(j->payload + j->payload_size, contents, sz); j->payload_size += sz; r = import_job_detect_compression(j); diff --git a/src/import/import-job.h b/src/import/import-job.h index a9b58e6339..b10b0ec0d9 100644 --- a/src/import/import-job.h +++ b/src/import/import-job.h @@ -23,6 +23,7 @@ #include #include +#include #include #include "macro.h" @@ -49,6 +50,7 @@ typedef enum ImportJobCompression { IMPORT_JOB_UNCOMPRESSED, IMPORT_JOB_XZ, IMPORT_JOB_GZIP, + IMPORT_JOB_BZIP2, _IMPORT_JOB_COMPRESSION_MAX, _IMPORT_JOB_COMPRESSION_INVALID = -1, } ImportJobCompression; @@ -89,6 +91,7 @@ struct ImportJob { ImportJobCompression compressed; lzma_stream xz; z_stream gzip; + bz_stream bzip2; unsigned progress_percent; usec_t start_usec; diff --git a/src/import/import.c b/src/import/import.c index 0c215c6484..b3ebb35357 100644 --- a/src/import/import.c +++ b/src/import/import.c @@ -51,10 +51,12 @@ static int strip_tar_suffixes(const char *name, char **ret) { char *s; e = endswith(name, ".tar"); + if (!e) + e = endswith(name, ".tar.xz"); if (!e) e = endswith(name, ".tar.gz"); if (!e) - e = endswith(name, ".tar.xz"); + e = endswith(name, ".tar.bz2"); if (!e) e = endswith(name, ".tgz"); if (!e) @@ -162,6 +164,7 @@ static int strip_raw_suffixes(const char *p, char **ret) { static const char suffixes[] = ".xz\0" ".gz\0" + ".bz2\0" ".raw\0" ".qcow2\0" ".img\0" -- cgit v1.2.3-54-g00ecf