Upgrade libarchive and bsdtar to 1.3.1.
[dragonfly.git] / contrib / libarchive / archive_read_support_compression_none.c
1 /*-
2  * Copyright (c) 2003-2004 Tim Kientzle
3  * All rights reserved.
4  *
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.
14  *
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.
25  */
26
27 #include "archive_platform.h"
28 __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_none.c,v 1.6 2005/02/13 23:29:54 kientzle Exp $");
29
30 #include <errno.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34
35 #include "archive.h"
36 #include "archive_private.h"
37
38 struct archive_decompress_none {
39         char            *buffer;
40         size_t           buffer_size;
41         char            *next;          /* Current read location. */
42         size_t           avail;         /* Bytes in my buffer. */
43         const char      *client_buff;   /* Client buffer information. */
44         size_t           client_total;
45         const char      *client_next;
46         size_t           client_avail;
47         char             end_of_file;
48         char             fatal;
49 };
50
51 /*
52  * Size of internal buffer used for combining short reads.  This is
53  * also an upper limit on the size of a read request.  Recall,
54  * however, that we can (and will!) return blocks of data larger than
55  * this.  The read semantics are: you ask for a minimum, I give you a
56  * pointer to my best-effort match and tell you how much data is
57  * there.  It could be less than you asked for, it could be much more.
58  * For example, a client might use mmap() to "read" the entire file as
59  * a single block.  In that case, I will return that entire block to
60  * my clients.
61  */
62 #define BUFFER_SIZE     65536
63
64 static int      archive_decompressor_none_bid(const void *, size_t);
65 static int      archive_decompressor_none_finish(struct archive *);
66 static int      archive_decompressor_none_init(struct archive *,
67                     const void *, size_t);
68 static ssize_t  archive_decompressor_none_read_ahead(struct archive *,
69                     const void **, size_t);
70 static ssize_t  archive_decompressor_none_read_consume(struct archive *,
71                     size_t);
72
73 int
74 archive_read_support_compression_none(struct archive *a)
75 {
76         return (__archive_read_register_compression(a,
77                     archive_decompressor_none_bid,
78                     archive_decompressor_none_init));
79 }
80
81 /*
82  * Try to detect an "uncompressed" archive.
83  */
84 static int
85 archive_decompressor_none_bid(const void *buff, size_t len)
86 {
87         (void)buff;
88         (void)len;
89
90         return (1); /* Default: We'll take it if noone else does. */
91 }
92
93 static int
94 archive_decompressor_none_init(struct archive *a, const void *buff, size_t n)
95 {
96         struct archive_decompress_none  *state;
97
98         a->compression_code = ARCHIVE_COMPRESSION_NONE;
99         a->compression_name = "none";
100
101         state = (struct archive_decompress_none *)malloc(sizeof(*state));
102         if (!state) {
103                 archive_set_error(a, ENOMEM, "Can't allocate input data");
104                 return (ARCHIVE_FATAL);
105         }
106         memset(state, 0, sizeof(*state));
107
108         state->buffer_size = BUFFER_SIZE;
109         state->buffer = malloc(state->buffer_size);
110         state->next = state->buffer;
111         if (state->buffer == NULL) {
112                 free(state);
113                 archive_set_error(a, ENOMEM, "Can't allocate input buffer");
114                 return (ARCHIVE_FATAL);
115         }
116
117         /* Save reference to first block of data. */
118         state->client_buff = buff;
119         state->client_total = n;
120         state->client_next = state->client_buff;
121         state->client_avail = state->client_total;
122
123         a->compression_data = state;
124         a->compression_read_ahead = archive_decompressor_none_read_ahead;
125         a->compression_read_consume = archive_decompressor_none_read_consume;
126         a->compression_finish = archive_decompressor_none_finish;
127
128         return (ARCHIVE_OK);
129 }
130
131 /*
132  * We just pass through pointers to the client buffer if we can.
133  * If the client buffer is short, then we copy stuff to our internal
134  * buffer to combine reads.
135  */
136 static ssize_t
137 archive_decompressor_none_read_ahead(struct archive *a, const void **buff,
138     size_t min)
139 {
140         struct archive_decompress_none *state;
141         ssize_t bytes_read;
142
143         state = a->compression_data;
144         if (state->fatal)
145                 return (-1);
146
147         /*
148          * Don't make special efforts to handle requests larger than
149          * the copy buffer.
150          */
151         if (min > state->buffer_size)
152                 min = state->buffer_size;
153
154         /*
155          * Try to satisfy the request directly from the client
156          * buffer.  We can do this if all of the data in the copy
157          * buffer was copied from the current client buffer.  This
158          * also covers the case where the copy buffer is empty and
159          * the client buffer has all the data we need.
160          */
161         if (state->client_total >= state->client_avail + state->avail
162             && state->client_avail + state->avail >= min) {
163                 state->client_avail += state->avail;
164                 state->client_next -= state->avail;
165                 state->avail = 0;
166                 state->next = state->buffer;
167                 *buff = state->client_next;
168                 return (state->client_avail);
169         }
170
171         /*
172          * If we can't use client buffer, we'll have to use copy buffer.
173          */
174
175         /* Move data forward in copy buffer if necessary. */
176         if (state->next > state->buffer &&
177             state->next + min > state->buffer + state->buffer_size) {
178                 if (state->avail > 0)
179                         memmove(state->buffer, state->next, state->avail);
180                 state->next = state->buffer;
181         }
182
183         /* Collect data in copy buffer to fulfill request. */
184         while (state->avail < min) {
185                 /* Copy data from client buffer to our copy buffer. */
186                 if (state->client_avail > 0) {
187                         /* First estimate: copy to fill rest of buffer. */
188                         size_t tocopy = (state->buffer + state->buffer_size)
189                             - (state->next + state->avail);
190                         /* Don't copy more than is available. */
191                         if (tocopy > state->client_avail)
192                                 tocopy = state->client_avail;
193                         memcpy(state->next + state->avail, state->client_next,
194                             tocopy);
195                         state->client_next += tocopy;
196                         state->client_avail -= tocopy;
197                         state->avail += tocopy;
198                 } else {
199                         /* There is no more client data: fetch more. */
200                         /*
201                          * It seems to me that const void ** and const
202                          * char ** should be compatible, but they
203                          * aren't, hence the cast.
204                          */
205                         bytes_read = (a->client_reader)(a, a->client_data,
206                             (const void **)&state->client_buff);
207                         if (bytes_read < 0) {           /* Read error. */
208                                 state->client_total = state->client_avail = 0;
209                                 state->client_next = state->client_buff = NULL;
210                                 state->fatal = 1;
211                                 return (-1);
212                         }
213                         if (bytes_read == 0) {          /* End-of-file. */
214                                 state->client_total = state->client_avail = 0;
215                                 state->client_next = state->client_buff = NULL;
216                                 state->end_of_file = 1;
217                                 break;
218                         }
219                         a->raw_position += bytes_read;
220                         state->client_total = bytes_read;
221                         state->client_avail = state->client_total;
222                         state->client_next = state->client_buff;
223                 }
224         }
225
226         *buff = state->next;
227         return (state->avail);
228 }
229
230 /*
231  * Mark the appropriate data as used.  Note that the request here will
232  * often be much smaller than the size of the previous read_ahead
233  * request.
234  */
235 static ssize_t
236 archive_decompressor_none_read_consume(struct archive *a, size_t request)
237 {
238         struct archive_decompress_none *state;
239
240         state = a->compression_data;
241         if (state->avail > 0) {
242                 /* Read came from copy buffer. */
243                 state->next += request;
244                 state->avail -= request;
245         } else {
246                 /* Read came from client buffer. */
247                 state->client_next += request;
248                 state->client_avail -= request;
249         }
250         a->file_position += request;
251         return (request);
252 }
253
254 static int
255 archive_decompressor_none_finish(struct archive *a)
256 {
257         struct archive_decompress_none  *state;
258
259         state = a->compression_data;
260         free(state->buffer);
261         free(state);
262         a->compression_data = NULL;
263         if (a->client_closer != NULL)
264                 return ((a->client_closer)(a, a->client_data));
265         return (ARCHIVE_OK);
266 }