2 * Copyright (c) 2007 Joerg Sonnenberger
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 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include "archive_platform.h"
27 __FBSDID("$FreeBSD$");
29 #ifdef HAVE_SYS_WAIT_H
30 # include <sys/wait.h>
52 #include "archive_private.h"
53 #include "archive_read_private.h"
55 #include "filter_fork.h"
57 struct archive_decompress_program
{
60 int child_stdin
, child_stdout
;
63 char *child_out_buf_next
;
64 size_t child_out_buf_len
, child_out_buf_avail
;
66 const char *child_in_buf
;
67 size_t child_in_buf_avail
;
70 static int archive_decompressor_program_bid(const void *, size_t);
71 static int archive_decompressor_program_finish(struct archive_read
*);
72 static int archive_decompressor_program_init(struct archive_read
*,
73 const void *, size_t);
74 static ssize_t
archive_decompressor_program_read_ahead(struct archive_read
*,
75 const void **, size_t);
76 static ssize_t
archive_decompressor_program_read_consume(struct archive_read
*,
80 archive_read_support_compression_program(struct archive
*_a
, const char *cmd
)
82 struct archive_read
*a
= (struct archive_read
*)_a
;
83 struct decompressor_t
*decompressor
;
85 if (cmd
== NULL
|| *cmd
== '\0')
86 return (ARCHIVE_WARN
);
88 decompressor
= __archive_read_register_compression(a
,
89 archive_decompressor_program_bid
,
90 archive_decompressor_program_init
);
91 if (decompressor
== NULL
)
92 return (ARCHIVE_WARN
);
94 decompressor
->config
= strdup(cmd
);
99 * If the user used us to register, they must really want us to
100 * handle it, so this module always bids INT_MAX.
103 archive_decompressor_program_bid(const void *buff
, size_t len
)
105 (void)buff
; /* UNUSED */
106 (void)len
; /* UNUSED */
108 return (INT_MAX
); /* Default: We'll take it. */
112 child_read(struct archive_read
*a
, char *buf
, size_t buf_len
)
114 struct archive_decompress_program
*state
= a
->decompressor
->data
;
115 ssize_t ret
, requested
;
117 if (state
->child_stdout
== -1)
124 requested
= buf_len
> SSIZE_MAX
? SSIZE_MAX
: buf_len
;
127 ret
= read(state
->child_stdout
, buf
, requested
);
128 } while (ret
== -1 && errno
== EINTR
);
132 if (ret
== 0 || (ret
== -1 && errno
== EPIPE
)) {
133 close(state
->child_stdout
);
134 state
->child_stdout
= -1;
137 if (ret
== -1 && errno
!= EAGAIN
)
140 if (state
->child_in_buf_avail
== 0) {
141 ret
= (a
->client_reader
)(&a
->archive
,
142 a
->client_data
, (const void **)&state
->child_in_buf
);
145 close(state
->child_stdin
);
146 state
->child_stdin
= -1;
147 fcntl(state
->child_stdout
, F_SETFL
, 0);
151 close(state
->child_stdin
);
152 state
->child_stdin
= -1;
153 fcntl(state
->child_stdout
, F_SETFL
, 0);
156 state
->child_in_buf_avail
= ret
;
160 ret
= write(state
->child_stdin
, state
->child_in_buf
,
161 state
->child_in_buf_avail
);
162 } while (ret
== -1 && errno
== EINTR
);
165 state
->child_in_buf
+= ret
;
166 state
->child_in_buf_avail
-= ret
;
168 } else if (ret
== -1 && errno
== EAGAIN
) {
169 __archive_check_child(state
->child_stdin
, state
->child_stdout
);
171 } else if (ret
== 0 || (ret
== -1 && errno
== EPIPE
)) {
172 close(state
->child_stdin
);
173 state
->child_stdout
= -1;
174 fcntl(state
->child_stdout
, F_SETFL
, 0);
177 close(state
->child_stdin
);
178 state
->child_stdin
= -1;
179 fcntl(state
->child_stdout
, F_SETFL
, 0);
185 archive_decompressor_program_init(struct archive_read
*a
, const void *buff
, size_t n
)
187 struct archive_decompress_program
*state
;
188 const char *cmd
= a
->decompressor
->config
;
189 const char *prefix
= "Program: ";
192 state
= (struct archive_decompress_program
*)malloc(sizeof(*state
));
194 archive_set_error(&a
->archive
, ENOMEM
,
195 "Can't allocate input data");
196 return (ARCHIVE_FATAL
);
199 a
->archive
.compression_code
= ARCHIVE_COMPRESSION_PROGRAM
;
200 state
->description
= (char *)malloc(strlen(prefix
) + strlen(cmd
) + 1);
201 strcpy(state
->description
, prefix
);
202 strcat(state
->description
, cmd
);
203 a
->archive
.compression_name
= state
->description
;
205 state
->child_out_buf_next
= state
->child_out_buf
= malloc(65536);
206 if (!state
->child_out_buf
) {
208 archive_set_error(&a
->archive
, ENOMEM
,
209 "Can't allocate filter buffer");
210 return (ARCHIVE_FATAL
);
212 state
->child_out_buf_len
= 65536;
213 state
->child_out_buf_avail
= 0;
215 state
->child_in_buf
= buff
;
216 state
->child_in_buf_avail
= n
;
218 if ((state
->child
= __archive_create_child(cmd
,
219 &state
->child_stdin
, &state
->child_stdout
)) == -1) {
220 free(state
->child_out_buf
);
222 archive_set_error(&a
->archive
, EINVAL
,
223 "Can't initialise filter");
224 return (ARCHIVE_FATAL
);
227 a
->decompressor
->data
= state
;
228 a
->decompressor
->read_ahead
= archive_decompressor_program_read_ahead
;
229 a
->decompressor
->consume
= archive_decompressor_program_read_consume
;
230 a
->decompressor
->skip
= NULL
;
231 a
->decompressor
->finish
= archive_decompressor_program_finish
;
233 /* XXX Check that we can read at least one byte? */
238 archive_decompressor_program_read_ahead(struct archive_read
*a
, const void **buff
,
241 struct archive_decompress_program
*state
;
244 state
= (struct archive_decompress_program
*)a
->decompressor
->data
;
246 if (min
> state
->child_out_buf_len
)
247 min
= state
->child_out_buf_len
;
249 while (state
->child_stdout
!= -1 && min
> state
->child_out_buf_avail
) {
250 if (state
->child_out_buf
!= state
->child_out_buf_next
) {
251 memmove(state
->child_out_buf
, state
->child_out_buf_next
,
252 state
->child_out_buf_avail
);
253 state
->child_out_buf_next
= state
->child_out_buf
;
256 bytes_read
= child_read(a
,
257 state
->child_out_buf
+ state
->child_out_buf_avail
,
258 state
->child_out_buf_len
- state
->child_out_buf_avail
);
259 if (bytes_read
== -1)
263 state
->child_out_buf_avail
+= bytes_read
;
264 a
->archive
.raw_position
+= bytes_read
;
267 *buff
= state
->child_out_buf_next
;
268 return (state
->child_out_buf_avail
);
272 archive_decompressor_program_read_consume(struct archive_read
*a
, size_t request
)
274 struct archive_decompress_program
*state
;
276 state
= (struct archive_decompress_program
*)a
->decompressor
->data
;
278 state
->child_out_buf_next
+= request
;
279 state
->child_out_buf_avail
-= request
;
281 a
->archive
.file_position
+= request
;
286 archive_decompressor_program_finish(struct archive_read
*a
)
288 struct archive_decompress_program
*state
;
291 state
= (struct archive_decompress_program
*)a
->decompressor
->data
;
293 /* Release our configuration data. */
294 free(a
->decompressor
->config
);
295 a
->decompressor
->config
= NULL
;
297 /* Shut down the child. */
298 if (state
->child_stdin
!= -1)
299 close(state
->child_stdin
);
300 if (state
->child_stdout
!= -1)
301 close(state
->child_stdout
);
302 while (waitpid(state
->child
, &status
, 0) == -1 && errno
== EINTR
)
305 /* Release our private data. */
306 free(state
->child_out_buf
);
307 free(state
->description
);
309 a
->decompressor
->data
= NULL
;