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
);