Import libarchive-2.5.5.
[dragonfly.git] / contrib / libarchive-1.3.1 / libarchive / archive_write_set_compression_none.c
blob7c3b51f6fa92eb0d4502fcb4d0e7a13ae63bc18a
1 /*-
2 * Copyright (c) 2003-2004 Tim Kientzle
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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 $");
30 #include <errno.h>
31 #include <stdlib.h>
32 #include <string.h>
34 #include "archive.h"
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 *,
40 size_t);
42 struct archive_none {
43 char *buffer;
44 ssize_t buffer_size;
45 char *next; /* Current insert location */
46 ssize_t avail; /* Free space left in buffer */
49 int
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";
56 return (0);
60 * Setup callback.
62 static int
63 archive_compressor_none_init(struct archive *a)
65 int ret;
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);
73 if (ret != 0)
74 return (ret);
77 state = (struct archive_none *)malloc(sizeof(*state));
78 if (state == NULL) {
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");
91 free(state);
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;
101 return (ARCHIVE_OK);
105 * Write data to the stream.
107 static int
108 archive_compressor_none_write(struct archive *a, const void *vbuff,
109 size_t length)
111 const char *buff;
112 ssize_t remaining, to_copy;
113 ssize_t bytes_written;
114 struct archive_none *state;
116 state = a->compression_data;
117 buff = vbuff;
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);
125 remaining = length;
126 while (remaining > 0) {
128 * If we have a full output block, write it and reset the
129 * output buffer.
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;
148 buff += to_copy;
149 remaining -= to_copy;
151 a->file_position += length;
152 return (ARCHIVE_OK);
157 * Finish the compression.
159 static int
160 archive_compressor_none_finish(struct archive *a)
162 ssize_t block_length;
163 ssize_t target_block_length;
164 ssize_t bytes_written;
165 int ret;
166 int ret2;
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;
187 else
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)
202 ret = ARCHIVE_FATAL;
203 else {
204 a->raw_position += bytes_written;
205 ret = ARCHIVE_OK;
209 /* Close the output */
210 if (a->client_closer != NULL)
211 ret2 = (a->client_closer)(a, a->client_data);
213 free(state->buffer);
214 free(state);
215 a->compression_data = NULL;
217 return (ret != ARCHIVE_OK ? ret : ret2);