2
* Copyright (c) 2003-2004 Tim Kientzle
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer
10
* in this position and unchanged.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
#include "archive_platform.h"
28
__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_compression_none.c,v 1.8 2005/06/01 15:52:39 kientzle Exp $");
35
#include "archive_private.h"
37
static int archive_compressor_none_finish(struct archive *a);
38
static int archive_compressor_none_init(struct archive *);
39
static int archive_compressor_none_write(struct archive *, const void *,
45
char *next; /* Current insert location */
46
ssize_t avail; /* Free space left in buffer */
50
archive_write_set_compression_none(struct archive *a)
52
__archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, "archive_write_set_compression_none");
53
a->compression_init = &archive_compressor_none_init;
54
a->compression_code = ARCHIVE_COMPRESSION_NONE;
55
a->compression_name = "none";
63
archive_compressor_none_init(struct archive *a)
66
struct archive_none *state;
68
a->compression_code = ARCHIVE_COMPRESSION_NONE;
69
a->compression_name = "none";
71
if (a->client_opener != NULL) {
72
ret = (a->client_opener)(a, a->client_data);
77
state = (struct archive_none *)malloc(sizeof(*state));
79
archive_set_error(a, ENOMEM,
80
"Can't allocate data for output buffering");
81
return (ARCHIVE_FATAL);
83
memset(state, 0, sizeof(*state));
85
state->buffer_size = a->bytes_per_block;
86
state->buffer = malloc(state->buffer_size);
88
if (state->buffer == NULL) {
89
archive_set_error(a, ENOMEM,
90
"Can't allocate output buffer");
92
return (ARCHIVE_FATAL);
95
state->next = state->buffer;
96
state->avail = state->buffer_size;
98
a->compression_data = state;
99
a->compression_write = archive_compressor_none_write;
100
a->compression_finish = archive_compressor_none_finish;
105
* Write data to the stream.
108
archive_compressor_none_write(struct archive *a, const void *vbuff,
112
ssize_t remaining, to_copy;
113
ssize_t bytes_written;
114
struct archive_none *state;
116
state = a->compression_data;
118
if (a->client_writer == NULL) {
119
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
120
"No write callback is registered? "
121
"This is probably an internal programming error.");
122
return (ARCHIVE_FATAL);
126
while (remaining > 0) {
128
* If we have a full output block, write it and reset the
131
if (state->avail == 0) {
132
bytes_written = (a->client_writer)(a, a->client_data,
133
state->buffer, state->buffer_size);
134
if (bytes_written <= 0)
135
return (ARCHIVE_FATAL);
136
/* XXX TODO: if bytes_written < state->buffer_size */
137
a->raw_position += bytes_written;
138
state->next = state->buffer;
139
state->avail = state->buffer_size;
142
/* Now we have space in the buffer; copy new data into it. */
143
to_copy = (remaining > state->avail) ?
144
state->avail : remaining;
145
memcpy(state->next, buff, to_copy);
146
state->next += to_copy;
147
state->avail -= to_copy;
149
remaining -= to_copy;
151
a->file_position += length;
157
* Finish the compression.
160
archive_compressor_none_finish(struct archive *a)
162
ssize_t block_length;
163
ssize_t target_block_length;
164
ssize_t bytes_written;
167
struct archive_none *state;
169
state = a->compression_data;
170
ret = ret2 = ARCHIVE_OK;
171
if (a->client_writer == NULL) {
172
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
173
"No write callback is registered? "
174
"This is probably an internal programming error.");
175
return (ARCHIVE_FATAL);
178
/* If there's pending data, pad and write the last block */
179
if (state->next != state->buffer) {
180
block_length = state->buffer_size - state->avail;
182
/* Tricky calculation to determine size of last block */
183
target_block_length = block_length;
184
if (a->bytes_in_last_block <= 0)
185
/* Default or Zero: pad to full block */
186
target_block_length = a->bytes_per_block;
188
/* Round to next multiple of bytes_in_last_block. */
189
target_block_length = a->bytes_in_last_block *
190
( (block_length + a->bytes_in_last_block - 1) /
191
a->bytes_in_last_block);
192
if (target_block_length > a->bytes_per_block)
193
target_block_length = a->bytes_per_block;
194
if (block_length < target_block_length) {
195
memset(state->next, 0,
196
target_block_length - block_length);
197
block_length = target_block_length;
199
bytes_written = (a->client_writer)(a, a->client_data,
200
state->buffer, block_length);
201
if (bytes_written <= 0)
204
a->raw_position += bytes_written;
209
/* Close the output */
210
if (a->client_closer != NULL)
211
ret2 = (a->client_closer)(a, a->client_data);
215
a->compression_data = NULL;
217
return (ret != ARCHIVE_OK ? ret : ret2);