static int raw_import_process(RawImport *i) { ssize_t l; int r; assert(i); assert(i->buffer_size < sizeof(i->buffer)); l = read(i->input_fd, i->buffer + i->buffer_size, sizeof(i->buffer) - i->buffer_size); if (l < 0) { if (errno == EAGAIN) return 0; r = log_error_errno(errno, "Failed to read input file: %m"); goto finish; } if (l == 0) { if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) { log_error("Premature end of file."); r = -EIO; goto finish; } r = raw_import_finish(i); goto finish; } i->buffer_size += l; if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) { r = import_uncompress_detect(&i->compress, i->buffer, i->buffer_size); if (r < 0) { log_error_errno(r, "Failed to detect file compression: %m"); goto finish; } if (r == 0) /* Need more data */ return 0; r = raw_import_open_disk(i); if (r < 0) goto finish; r = raw_import_try_reflink(i); if (r < 0) goto finish; if (r > 0) { r = raw_import_finish(i); goto finish; } } r = import_uncompress(&i->compress, i->buffer, i->buffer_size, raw_import_write, i); if (r < 0) { log_error_errno(r, "Failed to decode and write: %m"); goto finish; } i->written_compressed += i->buffer_size; i->buffer_size = 0; raw_import_report_progress(i); return 0; finish: if (i->on_finished) i->on_finished(i, r, i->userdata); else sd_event_exit(i->event, r); return 0; }
int import_uncompress(ImportCompress *c, const void *data, size_t size, ImportCompressCallback callback, void *userdata) { int r; assert(c); assert(callback); r = import_uncompress_detect(c, data, size); if (r <= 0) return r; if (c->encoding) return -EINVAL; if (size <= 0) return 1; assert(data); switch (c->type) { case IMPORT_COMPRESS_UNCOMPRESSED: r = callback(data, size, userdata); if (r < 0) return r; break; case IMPORT_COMPRESS_XZ: c->xz.next_in = data; c->xz.avail_in = size; while (c->xz.avail_in > 0) { uint8_t buffer[16 * 1024]; lzma_ret lzr; c->xz.next_out = buffer; c->xz.avail_out = sizeof(buffer); lzr = lzma_code(&c->xz, LZMA_RUN); if (lzr != LZMA_OK && lzr != LZMA_STREAM_END) return -EIO; r = callback(buffer, sizeof(buffer) - c->xz.avail_out, userdata); if (r < 0) return r; } break; case IMPORT_COMPRESS_GZIP: c->gzip.next_in = (void*) data; c->gzip.avail_in = size; while (c->gzip.avail_in > 0) { uint8_t buffer[16 * 1024]; c->gzip.next_out = buffer; c->gzip.avail_out = sizeof(buffer); r = inflate(&c->gzip, Z_NO_FLUSH); if (r != Z_OK && r != Z_STREAM_END) return -EIO; r = callback(buffer, sizeof(buffer) - c->gzip.avail_out, userdata); if (r < 0) return r; } break; case IMPORT_COMPRESS_BZIP2: c->bzip2.next_in = (void*) data; c->bzip2.avail_in = size; while (c->bzip2.avail_in > 0) { uint8_t buffer[16 * 1024]; c->bzip2.next_out = (char*) buffer; c->bzip2.avail_out = sizeof(buffer); r = BZ2_bzDecompress(&c->bzip2); if (r != BZ_OK && r != BZ_STREAM_END) return -EIO; r = callback(buffer, sizeof(buffer) - c->bzip2.avail_out, userdata); if (r < 0) return r; } break; default: assert_not_reached("Unknown compression"); } return 1; }