/* * Finish the compression. */ static int archive_compressor_bzip2_close(struct archive_write_filter *f) { struct private_data *data = (struct private_data *)f->data; int ret, r1; /* Finish compression cycle. */ ret = drive_compressor(f, data, 1); if (ret == ARCHIVE_OK) { /* Write the last block */ ret = __archive_write_filter(f->next_filter, data->compressed, data->compressed_buffer_size - data->stream.avail_out); } switch (BZ2_bzCompressEnd(&(data->stream))) { case BZ_OK: break; default: archive_set_error(f->archive, ARCHIVE_ERRNO_PROGRAMMER, "Failed to clean up compressor"); ret = ARCHIVE_FATAL; } r1 = __archive_write_close_filter(f->next_filter); return (r1 < ret ? r1 : ret); }
/* * Open the archive using the current settings. */ int archive_write_open(struct archive *_a, void *client_data, archive_open_callback *opener, archive_write_callback *writer, archive_close_callback *closer) { struct archive_write *a = (struct archive_write *)_a; struct archive_write_filter *client_filter; int ret, r1; archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, "archive_write_open"); archive_clear_error(&a->archive); a->client_writer = writer; a->client_opener = opener; a->client_closer = closer; a->client_data = client_data; client_filter = __archive_write_allocate_filter(_a); client_filter->open = archive_write_client_open; client_filter->write = archive_write_client_write; client_filter->close = archive_write_client_close; ret = __archive_write_open_filter(a->filter_first); if (ret < ARCHIVE_WARN) { r1 = __archive_write_close_filter(a->filter_first); return (r1 < ret ? r1 : ret); } a->archive.state = ARCHIVE_STATE_HEADER; if (a->format_init) ret = (a->format_init)(a); return (ret); }
/* * Finish the compression... */ static int archive_compressor_xz_close(struct archive_write_filter *f) { struct private_data *data = (struct private_data *)f->data; int ret, r1; ret = drive_compressor(f, data, 1); if (ret == ARCHIVE_OK) { data->total_out += data->compressed_buffer_size - data->stream.avail_out; ret = __archive_write_filter(f->next_filter, data->compressed, data->compressed_buffer_size - data->stream.avail_out); if (f->code == ARCHIVE_FILTER_LZIP && ret == ARCHIVE_OK) { archive_le32enc(data->compressed, data->crc32); archive_le64enc(data->compressed+4, data->total_in); archive_le64enc(data->compressed+12, data->total_out + 20); ret = __archive_write_filter(f->next_filter, data->compressed, 20); } } lzma_end(&(data->stream)); r1 = __archive_write_close_filter(f->next_filter); return (r1 < ret ? r1 : ret); }
/* * Finish the compression. */ static int archive_filter_lz4_close(struct archive_write_filter *f) { struct private_data *data = (struct private_data *)f->data; int ret, r1; /* Finish compression cycle. */ ret = (int)lz4_write_one_block(f, NULL, 0); if (ret >= 0) { /* * Write the last block and the end of the stream data. */ /* Write End Of Stream. */ memset(data->out, 0, 4); data->out += 4; /* Write Stream checksum if needed. */ if (data->stream_checksum) { unsigned int checksum; checksum = __archive_xxhash.XXH32_digest( data->xxh32_state); data->xxh32_state = NULL; archive_le32enc(data->out, checksum); data->out += 4; } ret = __archive_write_filter(f->next_filter, data->out_buffer, data->out - data->out_buffer); } r1 = __archive_write_close_filter(f->next_filter); return (r1 < ret ? r1 : ret); }
/* * Close a filter. */ int __archive_write_close_filter(struct archive_write_filter *f) { if (f->close != NULL) return (f->close)(f); if (f->next_filter != NULL) return (__archive_write_close_filter(f->next_filter)); return (ARCHIVE_OK); }
/* * Finish the compression... */ static int archive_compressor_program_close(struct archive_write_filter *f) { struct private_data *data = (struct private_data *)f->data; int ret, r1, status; ssize_t bytes_read; ret = 0; close(data->child_stdin); data->child_stdin = -1; fcntl(data->child_stdout, F_SETFL, 0); for (;;) { do { bytes_read = read(data->child_stdout, data->child_buf + data->child_buf_avail, data->child_buf_len - data->child_buf_avail); } while (bytes_read == -1 && errno == EINTR); if (bytes_read == 0 || (bytes_read == -1 && errno == EPIPE)) break; if (bytes_read == -1) { archive_set_error(f->archive, errno, "Read from filter failed unexpectedly."); ret = ARCHIVE_FATAL; goto cleanup; } data->child_buf_avail += bytes_read; ret = __archive_write_filter(f->next_filter, data->child_buf, data->child_buf_avail); if (ret != ARCHIVE_OK) { ret = ARCHIVE_FATAL; goto cleanup; } data->child_buf_avail = 0; } cleanup: /* Shut down the child. */ if (data->child_stdin != -1) close(data->child_stdin); if (data->child_stdout != -1) close(data->child_stdout); while (waitpid(data->child, &status, 0) == -1 && errno == EINTR) continue; if (status != 0) { archive_set_error(f->archive, EIO, "Filter exited with failure."); ret = ARCHIVE_FATAL; } r1 = __archive_write_close_filter(f->next_filter); return (r1 < ret ? r1 : ret); }
/* * Close out the archive. */ static int _archive_write_close(struct archive *_a) { struct archive_write *a = (struct archive_write *)_a; int r = ARCHIVE_OK, r1 = ARCHIVE_OK; archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_write_close"); if (a->archive.state == ARCHIVE_STATE_NEW || a->archive.state == ARCHIVE_STATE_CLOSED) return (ARCHIVE_OK); /* Okay to close() when not open. */ archive_clear_error(&a->archive); /* Finish the last entry if a finish callback is specified */ if (a->archive.state == ARCHIVE_STATE_DATA && a->format_finish_entry != NULL) r = ((a->format_finish_entry)(a)); /* Finish off the archive. */ /* TODO: have format closers invoke compression close. */ if (a->format_close != NULL) { r1 = (a->format_close)(a); if (r1 < r) r = r1; } /* Finish the compression and close the stream. */ r1 = __archive_write_close_filter(a->filter_first); if (r1 < r) r = r1; if (a->archive.state != ARCHIVE_STATE_FATAL) a->archive.state = ARCHIVE_STATE_CLOSED; return (r); }
/* * Finish the filtering... */ int __archive_write_program_close(struct archive_write_filter *f, struct archive_write_program_data *data) { int ret, r1, status; ssize_t bytes_read; if (data->child == 0) return __archive_write_close_filter(f->next_filter); ret = 0; close(data->child_stdin); data->child_stdin = -1; fcntl(data->child_stdout, F_SETFL, 0); for (;;) { do { bytes_read = read(data->child_stdout, data->child_buf + data->child_buf_avail, data->child_buf_len - data->child_buf_avail); } while (bytes_read == -1 && errno == EINTR); if (bytes_read == 0 || (bytes_read == -1 && errno == EPIPE)) break; if (bytes_read == -1) { archive_set_error(f->archive, errno, "Error reading from program: %s", data->program_name); ret = ARCHIVE_FATAL; goto cleanup; } data->child_buf_avail += bytes_read; ret = __archive_write_filter(f->next_filter, data->child_buf, data->child_buf_avail); if (ret != ARCHIVE_OK) { ret = ARCHIVE_FATAL; goto cleanup; } data->child_buf_avail = 0; } cleanup: /* Shut down the child. */ if (data->child_stdin != -1) close(data->child_stdin); if (data->child_stdout != -1) close(data->child_stdout); while (waitpid(data->child, &status, 0) == -1 && errno == EINTR) continue; #if defined(_WIN32) && !defined(__CYGWIN__) CloseHandle(data->child); #endif data->child = 0; if (status != 0) { archive_set_error(f->archive, EIO, "Error closing program: %s", data->program_name); ret = ARCHIVE_FATAL; } r1 = __archive_write_close_filter(f->next_filter); return (r1 < ret ? r1 : ret); }