1c09f92d2SPeter Avalos /*-
259bf7050SPeter Avalos * Copyright (c) 2011-2012 Michihiro NAKAJIMA
3c09f92d2SPeter Avalos * All rights reserved.
4c09f92d2SPeter Avalos *
5c09f92d2SPeter Avalos * Redistribution and use in source and binary forms, with or without
6c09f92d2SPeter Avalos * modification, are permitted provided that the following conditions
7c09f92d2SPeter Avalos * are met:
8c09f92d2SPeter Avalos * 1. Redistributions of source code must retain the above copyright
9c09f92d2SPeter Avalos * notice, this list of conditions and the following disclaimer.
10c09f92d2SPeter Avalos * 2. Redistributions in binary form must reproduce the above copyright
11c09f92d2SPeter Avalos * notice, this list of conditions and the following disclaimer in the
12c09f92d2SPeter Avalos * documentation and/or other materials provided with the distribution.
13c09f92d2SPeter Avalos *
14c09f92d2SPeter Avalos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15c09f92d2SPeter Avalos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16c09f92d2SPeter Avalos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17c09f92d2SPeter Avalos * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18c09f92d2SPeter Avalos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19c09f92d2SPeter Avalos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20c09f92d2SPeter Avalos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21c09f92d2SPeter Avalos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22c09f92d2SPeter Avalos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23c09f92d2SPeter Avalos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24c09f92d2SPeter Avalos */
25c09f92d2SPeter Avalos
26c09f92d2SPeter Avalos #include "archive_platform.h"
27c09f92d2SPeter Avalos __FBSDID("$FreeBSD$");
28c09f92d2SPeter Avalos
29c09f92d2SPeter Avalos #ifdef HAVE_ERRNO_H
30c09f92d2SPeter Avalos #include <errno.h>
31c09f92d2SPeter Avalos #endif
32c09f92d2SPeter Avalos #include <stdlib.h>
33c09f92d2SPeter Avalos #ifdef HAVE_BZLIB_H
34c09f92d2SPeter Avalos #include <bzlib.h>
35c09f92d2SPeter Avalos #endif
36c09f92d2SPeter Avalos #if HAVE_LZMA_H
37c09f92d2SPeter Avalos #include <lzma.h>
38c09f92d2SPeter Avalos #endif
39c09f92d2SPeter Avalos #ifdef HAVE_ZLIB_H
40c09f92d2SPeter Avalos #include <zlib.h>
41c09f92d2SPeter Avalos #endif
42c09f92d2SPeter Avalos
43c09f92d2SPeter Avalos #include "archive.h"
44c09f92d2SPeter Avalos #ifndef HAVE_ZLIB_H
45c09f92d2SPeter Avalos #include "archive_crc32.h"
46c09f92d2SPeter Avalos #endif
47c09f92d2SPeter Avalos #include "archive_endian.h"
48c09f92d2SPeter Avalos #include "archive_entry.h"
49c09f92d2SPeter Avalos #include "archive_entry_locale.h"
50c09f92d2SPeter Avalos #include "archive_ppmd7_private.h"
51c09f92d2SPeter Avalos #include "archive_private.h"
52c09f92d2SPeter Avalos #include "archive_rb.h"
53c09f92d2SPeter Avalos #include "archive_string.h"
54c09f92d2SPeter Avalos #include "archive_write_private.h"
55085658deSDaniel Fojt #include "archive_write_set_format_private.h"
56c09f92d2SPeter Avalos
57c09f92d2SPeter Avalos /*
58c09f92d2SPeter Avalos * Codec ID
59c09f92d2SPeter Avalos */
60c09f92d2SPeter Avalos #define _7Z_COPY 0
61c09f92d2SPeter Avalos #define _7Z_LZMA1 0x030101
62c09f92d2SPeter Avalos #define _7Z_LZMA2 0x21
63c09f92d2SPeter Avalos #define _7Z_DEFLATE 0x040108
64c09f92d2SPeter Avalos #define _7Z_BZIP2 0x040202
65c09f92d2SPeter Avalos #define _7Z_PPMD 0x030401
66c09f92d2SPeter Avalos
67c09f92d2SPeter Avalos /*
68c09f92d2SPeter Avalos * 7-Zip header property IDs.
69c09f92d2SPeter Avalos */
70c09f92d2SPeter Avalos #define kEnd 0x00
71c09f92d2SPeter Avalos #define kHeader 0x01
72c09f92d2SPeter Avalos #define kArchiveProperties 0x02
73c09f92d2SPeter Avalos #define kAdditionalStreamsInfo 0x03
74c09f92d2SPeter Avalos #define kMainStreamsInfo 0x04
75c09f92d2SPeter Avalos #define kFilesInfo 0x05
76c09f92d2SPeter Avalos #define kPackInfo 0x06
77c09f92d2SPeter Avalos #define kUnPackInfo 0x07
78c09f92d2SPeter Avalos #define kSubStreamsInfo 0x08
79c09f92d2SPeter Avalos #define kSize 0x09
80c09f92d2SPeter Avalos #define kCRC 0x0A
81c09f92d2SPeter Avalos #define kFolder 0x0B
82c09f92d2SPeter Avalos #define kCodersUnPackSize 0x0C
83c09f92d2SPeter Avalos #define kNumUnPackStream 0x0D
84c09f92d2SPeter Avalos #define kEmptyStream 0x0E
85c09f92d2SPeter Avalos #define kEmptyFile 0x0F
86c09f92d2SPeter Avalos #define kAnti 0x10
87c09f92d2SPeter Avalos #define kName 0x11
88c09f92d2SPeter Avalos #define kCTime 0x12
89c09f92d2SPeter Avalos #define kATime 0x13
90c09f92d2SPeter Avalos #define kMTime 0x14
91c09f92d2SPeter Avalos #define kAttributes 0x15
92c09f92d2SPeter Avalos #define kEncodedHeader 0x17
93c09f92d2SPeter Avalos
94c09f92d2SPeter Avalos enum la_zaction {
95c09f92d2SPeter Avalos ARCHIVE_Z_FINISH,
96c09f92d2SPeter Avalos ARCHIVE_Z_RUN
97c09f92d2SPeter Avalos };
98c09f92d2SPeter Avalos
99c09f92d2SPeter Avalos /*
100c09f92d2SPeter Avalos * A stream object of universal compressor.
101c09f92d2SPeter Avalos */
102c09f92d2SPeter Avalos struct la_zstream {
103c09f92d2SPeter Avalos const uint8_t *next_in;
104c09f92d2SPeter Avalos size_t avail_in;
105c09f92d2SPeter Avalos uint64_t total_in;
106c09f92d2SPeter Avalos
107c09f92d2SPeter Avalos uint8_t *next_out;
108c09f92d2SPeter Avalos size_t avail_out;
109c09f92d2SPeter Avalos uint64_t total_out;
110c09f92d2SPeter Avalos
111c09f92d2SPeter Avalos uint32_t prop_size;
112c09f92d2SPeter Avalos uint8_t *props;
113c09f92d2SPeter Avalos
114c09f92d2SPeter Avalos int valid;
115c09f92d2SPeter Avalos void *real_stream;
116c09f92d2SPeter Avalos int (*code) (struct archive *a,
117c09f92d2SPeter Avalos struct la_zstream *lastrm,
118c09f92d2SPeter Avalos enum la_zaction action);
119c09f92d2SPeter Avalos int (*end)(struct archive *a,
120c09f92d2SPeter Avalos struct la_zstream *lastrm);
121c09f92d2SPeter Avalos };
122c09f92d2SPeter Avalos
123c09f92d2SPeter Avalos #define PPMD7_DEFAULT_ORDER 6
124c09f92d2SPeter Avalos #define PPMD7_DEFAULT_MEM_SIZE (1 << 24)
125c09f92d2SPeter Avalos
126c09f92d2SPeter Avalos struct ppmd_stream {
127c09f92d2SPeter Avalos int stat;
128c09f92d2SPeter Avalos CPpmd7 ppmd7_context;
129c09f92d2SPeter Avalos CPpmd7z_RangeEnc range_enc;
130c09f92d2SPeter Avalos IByteOut byteout;
131c09f92d2SPeter Avalos uint8_t *buff;
132c09f92d2SPeter Avalos uint8_t *buff_ptr;
133c09f92d2SPeter Avalos uint8_t *buff_end;
134c09f92d2SPeter Avalos size_t buff_bytes;
135c09f92d2SPeter Avalos };
136c09f92d2SPeter Avalos
137c09f92d2SPeter Avalos struct coder {
138c09f92d2SPeter Avalos unsigned codec;
139c09f92d2SPeter Avalos size_t prop_size;
140c09f92d2SPeter Avalos uint8_t *props;
141c09f92d2SPeter Avalos };
142c09f92d2SPeter Avalos
143c09f92d2SPeter Avalos struct file {
144c09f92d2SPeter Avalos struct archive_rb_node rbnode;
145c09f92d2SPeter Avalos
146c09f92d2SPeter Avalos struct file *next;
147c09f92d2SPeter Avalos unsigned name_len;
148c09f92d2SPeter Avalos uint8_t *utf16name;/* UTF16-LE name. */
149c09f92d2SPeter Avalos uint64_t size;
150c09f92d2SPeter Avalos unsigned flg;
151c09f92d2SPeter Avalos #define MTIME_IS_SET (1<<0)
152c09f92d2SPeter Avalos #define ATIME_IS_SET (1<<1)
153c09f92d2SPeter Avalos #define CTIME_IS_SET (1<<2)
154c09f92d2SPeter Avalos #define CRC32_IS_SET (1<<3)
155c09f92d2SPeter Avalos #define HAS_STREAM (1<<4)
156c09f92d2SPeter Avalos
157c09f92d2SPeter Avalos struct {
158c09f92d2SPeter Avalos time_t time;
159c09f92d2SPeter Avalos long time_ns;
160c09f92d2SPeter Avalos } times[3];
161c09f92d2SPeter Avalos #define MTIME 0
162c09f92d2SPeter Avalos #define ATIME 1
163c09f92d2SPeter Avalos #define CTIME 2
164c09f92d2SPeter Avalos
165c09f92d2SPeter Avalos mode_t mode;
166c09f92d2SPeter Avalos uint32_t crc32;
167c09f92d2SPeter Avalos
168085658deSDaniel Fojt signed int dir:1;
169c09f92d2SPeter Avalos };
170c09f92d2SPeter Avalos
171c09f92d2SPeter Avalos struct _7zip {
172c09f92d2SPeter Avalos int temp_fd;
173c09f92d2SPeter Avalos uint64_t temp_offset;
174c09f92d2SPeter Avalos
175c09f92d2SPeter Avalos struct file *cur_file;
176c09f92d2SPeter Avalos size_t total_number_entry;
177c09f92d2SPeter Avalos size_t total_number_nonempty_entry;
178c09f92d2SPeter Avalos size_t total_number_empty_entry;
179c09f92d2SPeter Avalos size_t total_number_dir_entry;
180c09f92d2SPeter Avalos size_t total_bytes_entry_name;
181c09f92d2SPeter Avalos size_t total_number_time_defined[3];
182c09f92d2SPeter Avalos uint64_t total_bytes_compressed;
183c09f92d2SPeter Avalos uint64_t total_bytes_uncompressed;
184c09f92d2SPeter Avalos uint64_t entry_bytes_remaining;
185c09f92d2SPeter Avalos uint32_t entry_crc32;
186c09f92d2SPeter Avalos uint32_t precode_crc32;
187c09f92d2SPeter Avalos uint32_t encoded_crc32;
188c09f92d2SPeter Avalos int crc32flg;
189c09f92d2SPeter Avalos #define PRECODE_CRC32 1
190c09f92d2SPeter Avalos #define ENCODED_CRC32 2
191c09f92d2SPeter Avalos
192c09f92d2SPeter Avalos unsigned opt_compression;
193c09f92d2SPeter Avalos int opt_compression_level;
194c09f92d2SPeter Avalos
195c09f92d2SPeter Avalos struct la_zstream stream;
196c09f92d2SPeter Avalos struct coder coder;
197c09f92d2SPeter Avalos
198c09f92d2SPeter Avalos struct archive_string_conv *sconv;
199c09f92d2SPeter Avalos
200c09f92d2SPeter Avalos /*
201c09f92d2SPeter Avalos * Compressed data buffer.
202c09f92d2SPeter Avalos */
20359bf7050SPeter Avalos unsigned char wbuff[512 * 20 * 6];
204c09f92d2SPeter Avalos size_t wbuff_remaining;
205c09f92d2SPeter Avalos
206c09f92d2SPeter Avalos /*
207c09f92d2SPeter Avalos * The list of the file entries which has its contents is used to
208c09f92d2SPeter Avalos * manage struct file objects.
209e95abc47Szrj * We use 'next' (a member of struct file) to chain.
210c09f92d2SPeter Avalos */
211c09f92d2SPeter Avalos struct {
212c09f92d2SPeter Avalos struct file *first;
213c09f92d2SPeter Avalos struct file **last;
214c09f92d2SPeter Avalos } file_list, empty_list;
215c09f92d2SPeter Avalos struct archive_rb_tree rbtree;/* for empty files */
216c09f92d2SPeter Avalos };
217c09f92d2SPeter Avalos
218c09f92d2SPeter Avalos static int _7z_options(struct archive_write *,
219c09f92d2SPeter Avalos const char *, const char *);
220c09f92d2SPeter Avalos static int _7z_write_header(struct archive_write *,
221c09f92d2SPeter Avalos struct archive_entry *);
222c09f92d2SPeter Avalos static ssize_t _7z_write_data(struct archive_write *,
223c09f92d2SPeter Avalos const void *, size_t);
224c09f92d2SPeter Avalos static int _7z_finish_entry(struct archive_write *);
225c09f92d2SPeter Avalos static int _7z_close(struct archive_write *);
226c09f92d2SPeter Avalos static int _7z_free(struct archive_write *);
227c09f92d2SPeter Avalos static int file_cmp_node(const struct archive_rb_node *,
228c09f92d2SPeter Avalos const struct archive_rb_node *);
229c09f92d2SPeter Avalos static int file_cmp_key(const struct archive_rb_node *, const void *);
230c09f92d2SPeter Avalos static int file_new(struct archive_write *a, struct archive_entry *,
231c09f92d2SPeter Avalos struct file **);
232c09f92d2SPeter Avalos static void file_free(struct file *);
233c09f92d2SPeter Avalos static void file_register(struct _7zip *, struct file *);
234c09f92d2SPeter Avalos static void file_register_empty(struct _7zip *, struct file *);
235c09f92d2SPeter Avalos static void file_init_register(struct _7zip *);
236c09f92d2SPeter Avalos static void file_init_register_empty(struct _7zip *);
237c09f92d2SPeter Avalos static void file_free_register(struct _7zip *);
238c09f92d2SPeter Avalos static ssize_t compress_out(struct archive_write *, const void *, size_t ,
239c09f92d2SPeter Avalos enum la_zaction);
240c09f92d2SPeter Avalos static int compression_init_encoder_copy(struct archive *,
241c09f92d2SPeter Avalos struct la_zstream *);
242c09f92d2SPeter Avalos static int compression_code_copy(struct archive *,
243c09f92d2SPeter Avalos struct la_zstream *, enum la_zaction);
244c09f92d2SPeter Avalos static int compression_end_copy(struct archive *, struct la_zstream *);
245c09f92d2SPeter Avalos static int compression_init_encoder_deflate(struct archive *,
246c09f92d2SPeter Avalos struct la_zstream *, int, int);
247c09f92d2SPeter Avalos #ifdef HAVE_ZLIB_H
248c09f92d2SPeter Avalos static int compression_code_deflate(struct archive *,
249c09f92d2SPeter Avalos struct la_zstream *, enum la_zaction);
250c09f92d2SPeter Avalos static int compression_end_deflate(struct archive *, struct la_zstream *);
251c09f92d2SPeter Avalos #endif
252c09f92d2SPeter Avalos static int compression_init_encoder_bzip2(struct archive *,
253c09f92d2SPeter Avalos struct la_zstream *, int);
254c09f92d2SPeter Avalos #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
255c09f92d2SPeter Avalos static int compression_code_bzip2(struct archive *,
256c09f92d2SPeter Avalos struct la_zstream *, enum la_zaction);
257c09f92d2SPeter Avalos static int compression_end_bzip2(struct archive *, struct la_zstream *);
258c09f92d2SPeter Avalos #endif
259c09f92d2SPeter Avalos static int compression_init_encoder_lzma1(struct archive *,
260c09f92d2SPeter Avalos struct la_zstream *, int);
261c09f92d2SPeter Avalos static int compression_init_encoder_lzma2(struct archive *,
262c09f92d2SPeter Avalos struct la_zstream *, int);
263c09f92d2SPeter Avalos #if defined(HAVE_LZMA_H)
264c09f92d2SPeter Avalos static int compression_code_lzma(struct archive *,
265c09f92d2SPeter Avalos struct la_zstream *, enum la_zaction);
266c09f92d2SPeter Avalos static int compression_end_lzma(struct archive *, struct la_zstream *);
267c09f92d2SPeter Avalos #endif
268c09f92d2SPeter Avalos static int compression_init_encoder_ppmd(struct archive *,
269c09f92d2SPeter Avalos struct la_zstream *, unsigned, uint32_t);
270c09f92d2SPeter Avalos static int compression_code_ppmd(struct archive *,
271c09f92d2SPeter Avalos struct la_zstream *, enum la_zaction);
272c09f92d2SPeter Avalos static int compression_end_ppmd(struct archive *, struct la_zstream *);
273c09f92d2SPeter Avalos static int _7z_compression_init_encoder(struct archive_write *, unsigned,
274c09f92d2SPeter Avalos int);
275c09f92d2SPeter Avalos static int compression_code(struct archive *,
276c09f92d2SPeter Avalos struct la_zstream *, enum la_zaction);
277c09f92d2SPeter Avalos static int compression_end(struct archive *,
278c09f92d2SPeter Avalos struct la_zstream *);
279c09f92d2SPeter Avalos static int enc_uint64(struct archive_write *, uint64_t);
280c09f92d2SPeter Avalos static int make_header(struct archive_write *, uint64_t, uint64_t,
281c09f92d2SPeter Avalos uint64_t, int, struct coder *);
282c09f92d2SPeter Avalos static int make_streamsInfo(struct archive_write *, uint64_t, uint64_t,
283c09f92d2SPeter Avalos uint64_t, int, struct coder *, int, uint32_t);
284c09f92d2SPeter Avalos
285c09f92d2SPeter Avalos int
archive_write_set_format_7zip(struct archive * _a)286c09f92d2SPeter Avalos archive_write_set_format_7zip(struct archive *_a)
287c09f92d2SPeter Avalos {
288c09f92d2SPeter Avalos static const struct archive_rb_tree_ops rb_ops = {
289c09f92d2SPeter Avalos file_cmp_node, file_cmp_key
290c09f92d2SPeter Avalos };
291c09f92d2SPeter Avalos struct archive_write *a = (struct archive_write *)_a;
292c09f92d2SPeter Avalos struct _7zip *zip;
293c09f92d2SPeter Avalos
294c09f92d2SPeter Avalos archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
295c09f92d2SPeter Avalos ARCHIVE_STATE_NEW, "archive_write_set_format_7zip");
296c09f92d2SPeter Avalos
297c09f92d2SPeter Avalos /* If another format was already registered, unregister it. */
298c09f92d2SPeter Avalos if (a->format_free != NULL)
299c09f92d2SPeter Avalos (a->format_free)(a);
300c09f92d2SPeter Avalos
301c09f92d2SPeter Avalos zip = calloc(1, sizeof(*zip));
302c09f92d2SPeter Avalos if (zip == NULL) {
303c09f92d2SPeter Avalos archive_set_error(&a->archive, ENOMEM,
304c09f92d2SPeter Avalos "Can't allocate 7-Zip data");
305c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
306c09f92d2SPeter Avalos }
307c09f92d2SPeter Avalos zip->temp_fd = -1;
308c09f92d2SPeter Avalos __archive_rb_tree_init(&(zip->rbtree), &rb_ops);
309c09f92d2SPeter Avalos file_init_register(zip);
310c09f92d2SPeter Avalos file_init_register_empty(zip);
311c09f92d2SPeter Avalos
312c09f92d2SPeter Avalos /* Set default compression type and its level. */
313c09f92d2SPeter Avalos #if HAVE_LZMA_H
314c09f92d2SPeter Avalos zip->opt_compression = _7Z_LZMA1;
315c09f92d2SPeter Avalos #elif defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
316c09f92d2SPeter Avalos zip->opt_compression = _7Z_BZIP2;
317c09f92d2SPeter Avalos #elif defined(HAVE_ZLIB_H)
318c09f92d2SPeter Avalos zip->opt_compression = _7Z_DEFLATE;
319c09f92d2SPeter Avalos #else
320c09f92d2SPeter Avalos zip->opt_compression = _7Z_COPY;
321c09f92d2SPeter Avalos #endif
322c09f92d2SPeter Avalos zip->opt_compression_level = 6;
323c09f92d2SPeter Avalos
324c09f92d2SPeter Avalos a->format_data = zip;
325c09f92d2SPeter Avalos
326c09f92d2SPeter Avalos a->format_name = "7zip";
327c09f92d2SPeter Avalos a->format_options = _7z_options;
328c09f92d2SPeter Avalos a->format_write_header = _7z_write_header;
329c09f92d2SPeter Avalos a->format_write_data = _7z_write_data;
330c09f92d2SPeter Avalos a->format_finish_entry = _7z_finish_entry;
331c09f92d2SPeter Avalos a->format_close = _7z_close;
332c09f92d2SPeter Avalos a->format_free = _7z_free;
333c09f92d2SPeter Avalos a->archive.archive_format = ARCHIVE_FORMAT_7ZIP;
334c09f92d2SPeter Avalos a->archive.archive_format_name = "7zip";
335c09f92d2SPeter Avalos
336c09f92d2SPeter Avalos return (ARCHIVE_OK);
337c09f92d2SPeter Avalos }
338c09f92d2SPeter Avalos
339c09f92d2SPeter Avalos static int
_7z_options(struct archive_write * a,const char * key,const char * value)340c09f92d2SPeter Avalos _7z_options(struct archive_write *a, const char *key, const char *value)
341c09f92d2SPeter Avalos {
342c09f92d2SPeter Avalos struct _7zip *zip;
343c09f92d2SPeter Avalos
344c09f92d2SPeter Avalos zip = (struct _7zip *)a->format_data;
345c09f92d2SPeter Avalos
346c09f92d2SPeter Avalos if (strcmp(key, "compression") == 0) {
347c09f92d2SPeter Avalos const char *name = NULL;
348c09f92d2SPeter Avalos
349c09f92d2SPeter Avalos if (value == NULL || strcmp(value, "copy") == 0 ||
350c09f92d2SPeter Avalos strcmp(value, "COPY") == 0 ||
351c09f92d2SPeter Avalos strcmp(value, "store") == 0 ||
352c09f92d2SPeter Avalos strcmp(value, "STORE") == 0)
353c09f92d2SPeter Avalos zip->opt_compression = _7Z_COPY;
354c09f92d2SPeter Avalos else if (strcmp(value, "deflate") == 0 ||
355c09f92d2SPeter Avalos strcmp(value, "DEFLATE") == 0)
356c09f92d2SPeter Avalos #if HAVE_ZLIB_H
357c09f92d2SPeter Avalos zip->opt_compression = _7Z_DEFLATE;
358c09f92d2SPeter Avalos #else
359c09f92d2SPeter Avalos name = "deflate";
360c09f92d2SPeter Avalos #endif
361c09f92d2SPeter Avalos else if (strcmp(value, "bzip2") == 0 ||
362c09f92d2SPeter Avalos strcmp(value, "BZIP2") == 0)
363c09f92d2SPeter Avalos #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
364c09f92d2SPeter Avalos zip->opt_compression = _7Z_BZIP2;
365c09f92d2SPeter Avalos #else
366c09f92d2SPeter Avalos name = "bzip2";
367c09f92d2SPeter Avalos #endif
368c09f92d2SPeter Avalos else if (strcmp(value, "lzma1") == 0 ||
369c09f92d2SPeter Avalos strcmp(value, "LZMA1") == 0)
370c09f92d2SPeter Avalos #if HAVE_LZMA_H
371c09f92d2SPeter Avalos zip->opt_compression = _7Z_LZMA1;
372c09f92d2SPeter Avalos #else
373c09f92d2SPeter Avalos name = "lzma1";
374c09f92d2SPeter Avalos #endif
375c09f92d2SPeter Avalos else if (strcmp(value, "lzma2") == 0 ||
376c09f92d2SPeter Avalos strcmp(value, "LZMA2") == 0)
377c09f92d2SPeter Avalos #if HAVE_LZMA_H
378c09f92d2SPeter Avalos zip->opt_compression = _7Z_LZMA2;
379c09f92d2SPeter Avalos #else
380c09f92d2SPeter Avalos name = "lzma2";
381c09f92d2SPeter Avalos #endif
382c09f92d2SPeter Avalos else if (strcmp(value, "ppmd") == 0 ||
383c09f92d2SPeter Avalos strcmp(value, "PPMD") == 0 ||
384c09f92d2SPeter Avalos strcmp(value, "PPMd") == 0)
385c09f92d2SPeter Avalos zip->opt_compression = _7Z_PPMD;
386c09f92d2SPeter Avalos else {
387c09f92d2SPeter Avalos archive_set_error(&(a->archive),
388c09f92d2SPeter Avalos ARCHIVE_ERRNO_MISC,
389d4d8193eSPeter Avalos "Unknown compression name: `%s'",
390c09f92d2SPeter Avalos value);
391c09f92d2SPeter Avalos return (ARCHIVE_FAILED);
392c09f92d2SPeter Avalos }
393c09f92d2SPeter Avalos if (name != NULL) {
394c09f92d2SPeter Avalos archive_set_error(&(a->archive),
395c09f92d2SPeter Avalos ARCHIVE_ERRNO_MISC,
396c09f92d2SPeter Avalos "`%s' compression not supported "
397c09f92d2SPeter Avalos "on this platform",
398c09f92d2SPeter Avalos name);
399c09f92d2SPeter Avalos return (ARCHIVE_FAILED);
400c09f92d2SPeter Avalos }
401c09f92d2SPeter Avalos return (ARCHIVE_OK);
402c09f92d2SPeter Avalos }
403c09f92d2SPeter Avalos if (strcmp(key, "compression-level") == 0) {
404c09f92d2SPeter Avalos if (value == NULL ||
405c09f92d2SPeter Avalos !(value[0] >= '0' && value[0] <= '9') ||
406c09f92d2SPeter Avalos value[1] != '\0') {
407c09f92d2SPeter Avalos archive_set_error(&(a->archive),
408c09f92d2SPeter Avalos ARCHIVE_ERRNO_MISC,
409d4d8193eSPeter Avalos "Illegal value `%s'",
410c09f92d2SPeter Avalos value);
411c09f92d2SPeter Avalos return (ARCHIVE_FAILED);
412c09f92d2SPeter Avalos }
413c09f92d2SPeter Avalos zip->opt_compression_level = value[0] - '0';
414c09f92d2SPeter Avalos return (ARCHIVE_OK);
415c09f92d2SPeter Avalos }
416c09f92d2SPeter Avalos
41759bf7050SPeter Avalos /* Note: The "warn" return is just to inform the options
41859bf7050SPeter Avalos * supervisor that we didn't handle it. It will generate
41959bf7050SPeter Avalos * a suitable error if no one used this option. */
42059bf7050SPeter Avalos return (ARCHIVE_WARN);
421c09f92d2SPeter Avalos }
422c09f92d2SPeter Avalos
423c09f92d2SPeter Avalos static int
_7z_write_header(struct archive_write * a,struct archive_entry * entry)424c09f92d2SPeter Avalos _7z_write_header(struct archive_write *a, struct archive_entry *entry)
425c09f92d2SPeter Avalos {
426c09f92d2SPeter Avalos struct _7zip *zip;
427c09f92d2SPeter Avalos struct file *file;
428c09f92d2SPeter Avalos int r;
429c09f92d2SPeter Avalos
430c09f92d2SPeter Avalos zip = (struct _7zip *)a->format_data;
431c09f92d2SPeter Avalos zip->cur_file = NULL;
432c09f92d2SPeter Avalos zip->entry_bytes_remaining = 0;
433c09f92d2SPeter Avalos
434c09f92d2SPeter Avalos if (zip->sconv == NULL) {
435c09f92d2SPeter Avalos zip->sconv = archive_string_conversion_to_charset(
436c09f92d2SPeter Avalos &a->archive, "UTF-16LE", 1);
437c09f92d2SPeter Avalos if (zip->sconv == NULL)
438c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
439c09f92d2SPeter Avalos }
440c09f92d2SPeter Avalos
441c09f92d2SPeter Avalos r = file_new(a, entry, &file);
442c09f92d2SPeter Avalos if (r < ARCHIVE_WARN) {
443085658deSDaniel Fojt if (file != NULL)
444c09f92d2SPeter Avalos file_free(file);
445c09f92d2SPeter Avalos return (r);
446c09f92d2SPeter Avalos }
447d4d8193eSPeter Avalos if (file->size == 0 && file->dir) {
448d4d8193eSPeter Avalos if (!__archive_rb_tree_insert_node(&(zip->rbtree),
449d4d8193eSPeter Avalos (struct archive_rb_node *)file)) {
450d4d8193eSPeter Avalos /* We have already had the same file. */
451d4d8193eSPeter Avalos file_free(file);
452d4d8193eSPeter Avalos return (ARCHIVE_OK);
453d4d8193eSPeter Avalos }
454d4d8193eSPeter Avalos }
455c09f92d2SPeter Avalos
456c09f92d2SPeter Avalos if (file->flg & MTIME_IS_SET)
457c09f92d2SPeter Avalos zip->total_number_time_defined[MTIME]++;
458c09f92d2SPeter Avalos if (file->flg & CTIME_IS_SET)
459c09f92d2SPeter Avalos zip->total_number_time_defined[CTIME]++;
460c09f92d2SPeter Avalos if (file->flg & ATIME_IS_SET)
461c09f92d2SPeter Avalos zip->total_number_time_defined[ATIME]++;
462c09f92d2SPeter Avalos
463c09f92d2SPeter Avalos zip->total_number_entry++;
464c09f92d2SPeter Avalos zip->total_bytes_entry_name += file->name_len + 2;
465c09f92d2SPeter Avalos if (file->size == 0) {
466c09f92d2SPeter Avalos /* Count up the number of empty files. */
467c09f92d2SPeter Avalos zip->total_number_empty_entry++;
468c09f92d2SPeter Avalos if (file->dir)
469c09f92d2SPeter Avalos zip->total_number_dir_entry++;
470c09f92d2SPeter Avalos else
471c09f92d2SPeter Avalos file_register_empty(zip, file);
472c09f92d2SPeter Avalos return (r);
473c09f92d2SPeter Avalos }
474c09f92d2SPeter Avalos
475c09f92d2SPeter Avalos /*
476c09f92d2SPeter Avalos * Init compression.
477c09f92d2SPeter Avalos */
478c09f92d2SPeter Avalos if ((zip->total_number_entry - zip->total_number_empty_entry) == 1) {
479c09f92d2SPeter Avalos r = _7z_compression_init_encoder(a, zip->opt_compression,
480c09f92d2SPeter Avalos zip->opt_compression_level);
481c09f92d2SPeter Avalos if (r < 0) {
482c09f92d2SPeter Avalos file_free(file);
483c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
484c09f92d2SPeter Avalos }
485c09f92d2SPeter Avalos }
486c09f92d2SPeter Avalos
487c09f92d2SPeter Avalos /* Register a non-empty file. */
488c09f92d2SPeter Avalos file_register(zip, file);
489c09f92d2SPeter Avalos
490c09f92d2SPeter Avalos /*
491c09f92d2SPeter Avalos * Set the current file to cur_file to read its contents.
492c09f92d2SPeter Avalos */
493c09f92d2SPeter Avalos zip->cur_file = file;
494c09f92d2SPeter Avalos
495c09f92d2SPeter Avalos
496c09f92d2SPeter Avalos /* Save a offset of current file in temporary file. */
497c09f92d2SPeter Avalos zip->entry_bytes_remaining = file->size;
498c09f92d2SPeter Avalos zip->entry_crc32 = 0;
499c09f92d2SPeter Avalos
500c09f92d2SPeter Avalos /*
501c09f92d2SPeter Avalos * Store a symbolic link name as file contents.
502c09f92d2SPeter Avalos */
503c09f92d2SPeter Avalos if (archive_entry_filetype(entry) == AE_IFLNK) {
504c09f92d2SPeter Avalos ssize_t bytes;
505c09f92d2SPeter Avalos const void *p = (const void *)archive_entry_symlink(entry);
50659bf7050SPeter Avalos bytes = compress_out(a, p, (size_t)file->size, ARCHIVE_Z_RUN);
507c09f92d2SPeter Avalos if (bytes < 0)
508c09f92d2SPeter Avalos return ((int)bytes);
509d4d8193eSPeter Avalos zip->entry_crc32 = crc32(zip->entry_crc32, p, (unsigned)bytes);
510c09f92d2SPeter Avalos zip->entry_bytes_remaining -= bytes;
511c09f92d2SPeter Avalos }
512c09f92d2SPeter Avalos
513c09f92d2SPeter Avalos return (r);
514c09f92d2SPeter Avalos }
515c09f92d2SPeter Avalos
516c09f92d2SPeter Avalos /*
517c09f92d2SPeter Avalos * Write data to a temporary file.
518c09f92d2SPeter Avalos */
519c09f92d2SPeter Avalos static int
write_to_temp(struct archive_write * a,const void * buff,size_t s)520c09f92d2SPeter Avalos write_to_temp(struct archive_write *a, const void *buff, size_t s)
521c09f92d2SPeter Avalos {
522c09f92d2SPeter Avalos struct _7zip *zip;
52359bf7050SPeter Avalos const unsigned char *p;
524c09f92d2SPeter Avalos ssize_t ws;
525c09f92d2SPeter Avalos
526c09f92d2SPeter Avalos zip = (struct _7zip *)a->format_data;
527c09f92d2SPeter Avalos
528c09f92d2SPeter Avalos /*
529c09f92d2SPeter Avalos * Open a temporary file.
530c09f92d2SPeter Avalos */
531c09f92d2SPeter Avalos if (zip->temp_fd == -1) {
532c09f92d2SPeter Avalos zip->temp_offset = 0;
533c09f92d2SPeter Avalos zip->temp_fd = __archive_mktemp(NULL);
534c09f92d2SPeter Avalos if (zip->temp_fd < 0) {
535c09f92d2SPeter Avalos archive_set_error(&a->archive, errno,
536c09f92d2SPeter Avalos "Couldn't create temporary file");
537c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
538c09f92d2SPeter Avalos }
539c09f92d2SPeter Avalos }
540c09f92d2SPeter Avalos
54159bf7050SPeter Avalos p = (const unsigned char *)buff;
542c09f92d2SPeter Avalos while (s) {
543c09f92d2SPeter Avalos ws = write(zip->temp_fd, p, s);
544c09f92d2SPeter Avalos if (ws < 0) {
545c09f92d2SPeter Avalos archive_set_error(&(a->archive), errno,
546c09f92d2SPeter Avalos "fwrite function failed");
547c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
548c09f92d2SPeter Avalos }
549c09f92d2SPeter Avalos s -= ws;
550c09f92d2SPeter Avalos p += ws;
551c09f92d2SPeter Avalos zip->temp_offset += ws;
552c09f92d2SPeter Avalos }
553c09f92d2SPeter Avalos return (ARCHIVE_OK);
554c09f92d2SPeter Avalos }
555c09f92d2SPeter Avalos
556c09f92d2SPeter Avalos static ssize_t
compress_out(struct archive_write * a,const void * buff,size_t s,enum la_zaction run)557c09f92d2SPeter Avalos compress_out(struct archive_write *a, const void *buff, size_t s,
558c09f92d2SPeter Avalos enum la_zaction run)
559c09f92d2SPeter Avalos {
560c09f92d2SPeter Avalos struct _7zip *zip = (struct _7zip *)a->format_data;
561c09f92d2SPeter Avalos int r;
562c09f92d2SPeter Avalos
563c09f92d2SPeter Avalos if (run == ARCHIVE_Z_FINISH && zip->stream.total_in == 0 && s == 0)
564c09f92d2SPeter Avalos return (0);
565c09f92d2SPeter Avalos
566c09f92d2SPeter Avalos if ((zip->crc32flg & PRECODE_CRC32) && s)
567d4d8193eSPeter Avalos zip->precode_crc32 = crc32(zip->precode_crc32, buff,
568d4d8193eSPeter Avalos (unsigned)s);
569c09f92d2SPeter Avalos zip->stream.next_in = (const unsigned char *)buff;
570c09f92d2SPeter Avalos zip->stream.avail_in = s;
571d4d8193eSPeter Avalos for (;;) {
572c09f92d2SPeter Avalos /* Compress file data. */
573c09f92d2SPeter Avalos r = compression_code(&(a->archive), &(zip->stream), run);
574c09f92d2SPeter Avalos if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
575c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
576c09f92d2SPeter Avalos if (zip->stream.avail_out == 0) {
577c09f92d2SPeter Avalos if (write_to_temp(a, zip->wbuff, sizeof(zip->wbuff))
578c09f92d2SPeter Avalos != ARCHIVE_OK)
579c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
580c09f92d2SPeter Avalos zip->stream.next_out = zip->wbuff;
581c09f92d2SPeter Avalos zip->stream.avail_out = sizeof(zip->wbuff);
582c09f92d2SPeter Avalos if (zip->crc32flg & ENCODED_CRC32)
583c09f92d2SPeter Avalos zip->encoded_crc32 = crc32(zip->encoded_crc32,
584c09f92d2SPeter Avalos zip->wbuff, sizeof(zip->wbuff));
585d4d8193eSPeter Avalos if (run == ARCHIVE_Z_FINISH && r != ARCHIVE_EOF)
586d4d8193eSPeter Avalos continue;
587c09f92d2SPeter Avalos }
588d4d8193eSPeter Avalos if (zip->stream.avail_in == 0)
589d4d8193eSPeter Avalos break;
590d4d8193eSPeter Avalos }
591c09f92d2SPeter Avalos if (run == ARCHIVE_Z_FINISH) {
592c09f92d2SPeter Avalos uint64_t bytes = sizeof(zip->wbuff) - zip->stream.avail_out;
59359bf7050SPeter Avalos if (write_to_temp(a, zip->wbuff, (size_t)bytes) != ARCHIVE_OK)
594c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
595c09f92d2SPeter Avalos if ((zip->crc32flg & ENCODED_CRC32) && bytes)
596c09f92d2SPeter Avalos zip->encoded_crc32 = crc32(zip->encoded_crc32,
59759bf7050SPeter Avalos zip->wbuff, (unsigned)bytes);
598c09f92d2SPeter Avalos }
599c09f92d2SPeter Avalos
600c09f92d2SPeter Avalos return (s);
601c09f92d2SPeter Avalos }
602c09f92d2SPeter Avalos
603c09f92d2SPeter Avalos static ssize_t
_7z_write_data(struct archive_write * a,const void * buff,size_t s)604c09f92d2SPeter Avalos _7z_write_data(struct archive_write *a, const void *buff, size_t s)
605c09f92d2SPeter Avalos {
606c09f92d2SPeter Avalos struct _7zip *zip;
607c09f92d2SPeter Avalos ssize_t bytes;
608c09f92d2SPeter Avalos
609c09f92d2SPeter Avalos zip = (struct _7zip *)a->format_data;
610c09f92d2SPeter Avalos
611c09f92d2SPeter Avalos if (s > zip->entry_bytes_remaining)
61259bf7050SPeter Avalos s = (size_t)zip->entry_bytes_remaining;
613c09f92d2SPeter Avalos if (s == 0 || zip->cur_file == NULL)
614c09f92d2SPeter Avalos return (0);
615c09f92d2SPeter Avalos bytes = compress_out(a, buff, s, ARCHIVE_Z_RUN);
616c09f92d2SPeter Avalos if (bytes < 0)
617c09f92d2SPeter Avalos return (bytes);
618d4d8193eSPeter Avalos zip->entry_crc32 = crc32(zip->entry_crc32, buff, (unsigned)bytes);
619c09f92d2SPeter Avalos zip->entry_bytes_remaining -= bytes;
620c09f92d2SPeter Avalos return (bytes);
621c09f92d2SPeter Avalos }
622c09f92d2SPeter Avalos
623c09f92d2SPeter Avalos static int
_7z_finish_entry(struct archive_write * a)624c09f92d2SPeter Avalos _7z_finish_entry(struct archive_write *a)
625c09f92d2SPeter Avalos {
626c09f92d2SPeter Avalos struct _7zip *zip;
627c09f92d2SPeter Avalos size_t s;
628c09f92d2SPeter Avalos ssize_t r;
629c09f92d2SPeter Avalos
630c09f92d2SPeter Avalos zip = (struct _7zip *)a->format_data;
631c09f92d2SPeter Avalos if (zip->cur_file == NULL)
632c09f92d2SPeter Avalos return (ARCHIVE_OK);
633c09f92d2SPeter Avalos
634c09f92d2SPeter Avalos while (zip->entry_bytes_remaining > 0) {
63559bf7050SPeter Avalos s = (size_t)zip->entry_bytes_remaining;
636c09f92d2SPeter Avalos if (s > a->null_length)
637c09f92d2SPeter Avalos s = a->null_length;
638c09f92d2SPeter Avalos r = _7z_write_data(a, a->nulls, s);
639c09f92d2SPeter Avalos if (r < 0)
640d4d8193eSPeter Avalos return ((int)r);
641c09f92d2SPeter Avalos }
642c09f92d2SPeter Avalos zip->total_bytes_compressed += zip->stream.total_in;
643c09f92d2SPeter Avalos zip->total_bytes_uncompressed += zip->stream.total_out;
644c09f92d2SPeter Avalos zip->cur_file->crc32 = zip->entry_crc32;
645c09f92d2SPeter Avalos zip->cur_file = NULL;
646c09f92d2SPeter Avalos
647c09f92d2SPeter Avalos return (ARCHIVE_OK);
648c09f92d2SPeter Avalos }
649c09f92d2SPeter Avalos
650c09f92d2SPeter Avalos static int
flush_wbuff(struct archive_write * a)651c09f92d2SPeter Avalos flush_wbuff(struct archive_write *a)
652c09f92d2SPeter Avalos {
653c09f92d2SPeter Avalos struct _7zip *zip;
654c09f92d2SPeter Avalos int r;
655c09f92d2SPeter Avalos size_t s;
656c09f92d2SPeter Avalos
657c09f92d2SPeter Avalos zip = (struct _7zip *)a->format_data;
658c09f92d2SPeter Avalos s = sizeof(zip->wbuff) - zip->wbuff_remaining;
659c09f92d2SPeter Avalos r = __archive_write_output(a, zip->wbuff, s);
660c09f92d2SPeter Avalos if (r != ARCHIVE_OK)
661c09f92d2SPeter Avalos return (r);
662c09f92d2SPeter Avalos zip->wbuff_remaining = sizeof(zip->wbuff);
663c09f92d2SPeter Avalos return (r);
664c09f92d2SPeter Avalos }
665c09f92d2SPeter Avalos
666c09f92d2SPeter Avalos static int
copy_out(struct archive_write * a,uint64_t offset,uint64_t length)667c09f92d2SPeter Avalos copy_out(struct archive_write *a, uint64_t offset, uint64_t length)
668c09f92d2SPeter Avalos {
669c09f92d2SPeter Avalos struct _7zip *zip;
670c09f92d2SPeter Avalos int r;
671c09f92d2SPeter Avalos
672c09f92d2SPeter Avalos zip = (struct _7zip *)a->format_data;
673c09f92d2SPeter Avalos if (zip->temp_offset > 0 &&
674c09f92d2SPeter Avalos lseek(zip->temp_fd, offset, SEEK_SET) < 0) {
675c09f92d2SPeter Avalos archive_set_error(&(a->archive), errno, "lseek failed");
676c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
677c09f92d2SPeter Avalos }
678c09f92d2SPeter Avalos while (length) {
679c09f92d2SPeter Avalos size_t rsize;
680c09f92d2SPeter Avalos ssize_t rs;
681c09f92d2SPeter Avalos unsigned char *wb;
682c09f92d2SPeter Avalos
683c09f92d2SPeter Avalos if (length > zip->wbuff_remaining)
684c09f92d2SPeter Avalos rsize = zip->wbuff_remaining;
685c09f92d2SPeter Avalos else
686c09f92d2SPeter Avalos rsize = (size_t)length;
687c09f92d2SPeter Avalos wb = zip->wbuff + (sizeof(zip->wbuff) - zip->wbuff_remaining);
688c09f92d2SPeter Avalos rs = read(zip->temp_fd, wb, rsize);
689c09f92d2SPeter Avalos if (rs < 0) {
690c09f92d2SPeter Avalos archive_set_error(&(a->archive), errno,
691c09f92d2SPeter Avalos "Can't read temporary file(%jd)",
692c09f92d2SPeter Avalos (intmax_t)rs);
693c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
694c09f92d2SPeter Avalos }
695c09f92d2SPeter Avalos if (rs == 0) {
696c09f92d2SPeter Avalos archive_set_error(&(a->archive), 0,
697c09f92d2SPeter Avalos "Truncated 7-Zip archive");
698c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
699c09f92d2SPeter Avalos }
700c09f92d2SPeter Avalos zip->wbuff_remaining -= rs;
701c09f92d2SPeter Avalos length -= rs;
702c09f92d2SPeter Avalos if (zip->wbuff_remaining == 0) {
703c09f92d2SPeter Avalos r = flush_wbuff(a);
704c09f92d2SPeter Avalos if (r != ARCHIVE_OK)
705c09f92d2SPeter Avalos return (r);
706c09f92d2SPeter Avalos }
707c09f92d2SPeter Avalos }
708c09f92d2SPeter Avalos return (ARCHIVE_OK);
709c09f92d2SPeter Avalos }
710c09f92d2SPeter Avalos
711c09f92d2SPeter Avalos static int
_7z_close(struct archive_write * a)712c09f92d2SPeter Avalos _7z_close(struct archive_write *a)
713c09f92d2SPeter Avalos {
714c09f92d2SPeter Avalos struct _7zip *zip;
715c09f92d2SPeter Avalos unsigned char *wb;
716c09f92d2SPeter Avalos uint64_t header_offset, header_size, header_unpacksize;
717c09f92d2SPeter Avalos uint64_t length;
718c09f92d2SPeter Avalos uint32_t header_crc32;
719c09f92d2SPeter Avalos int r;
720c09f92d2SPeter Avalos
721c09f92d2SPeter Avalos zip = (struct _7zip *)a->format_data;
722c09f92d2SPeter Avalos
723c09f92d2SPeter Avalos if (zip->total_number_entry > 0) {
724c09f92d2SPeter Avalos struct archive_rb_node *n;
725c09f92d2SPeter Avalos uint64_t data_offset, data_size, data_unpacksize;
726c09f92d2SPeter Avalos unsigned header_compression;
727c09f92d2SPeter Avalos
728c09f92d2SPeter Avalos r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH);
729c09f92d2SPeter Avalos if (r < 0)
730c09f92d2SPeter Avalos return (r);
731c09f92d2SPeter Avalos data_offset = 0;
732c09f92d2SPeter Avalos data_size = zip->stream.total_out;
733c09f92d2SPeter Avalos data_unpacksize = zip->stream.total_in;
734c09f92d2SPeter Avalos zip->coder.codec = zip->opt_compression;
735c09f92d2SPeter Avalos zip->coder.prop_size = zip->stream.prop_size;
736c09f92d2SPeter Avalos zip->coder.props = zip->stream.props;
737c09f92d2SPeter Avalos zip->stream.prop_size = 0;
738c09f92d2SPeter Avalos zip->stream.props = NULL;
739c09f92d2SPeter Avalos zip->total_number_nonempty_entry =
740c09f92d2SPeter Avalos zip->total_number_entry - zip->total_number_empty_entry;
741c09f92d2SPeter Avalos
742c09f92d2SPeter Avalos /* Connect an empty file list. */
74359bf7050SPeter Avalos if (zip->empty_list.first != NULL) {
744c09f92d2SPeter Avalos *zip->file_list.last = zip->empty_list.first;
745c09f92d2SPeter Avalos zip->file_list.last = zip->empty_list.last;
74659bf7050SPeter Avalos }
747c09f92d2SPeter Avalos /* Connect a directory file list. */
748c09f92d2SPeter Avalos ARCHIVE_RB_TREE_FOREACH(n, &(zip->rbtree)) {
749c09f92d2SPeter Avalos file_register(zip, (struct file *)n);
750c09f92d2SPeter Avalos }
751c09f92d2SPeter Avalos
752c09f92d2SPeter Avalos /*
753c09f92d2SPeter Avalos * NOTE: 7z command supports just LZMA1, LZMA2 and COPY for
754c09f92d2SPeter Avalos * the compression type for encoding the header.
755c09f92d2SPeter Avalos */
756c09f92d2SPeter Avalos #if HAVE_LZMA_H
757c09f92d2SPeter Avalos header_compression = _7Z_LZMA1;
758*50f8aa9cSAntonio Huete Jimenez if(zip->opt_compression == _7Z_LZMA2 ||
759*50f8aa9cSAntonio Huete Jimenez zip->opt_compression == _7Z_COPY)
760*50f8aa9cSAntonio Huete Jimenez header_compression = zip->opt_compression;
761*50f8aa9cSAntonio Huete Jimenez
762c09f92d2SPeter Avalos /* If the stored file is only one, do not encode the header.
763c09f92d2SPeter Avalos * This is the same way 7z command does. */
764c09f92d2SPeter Avalos if (zip->total_number_entry == 1)
765c09f92d2SPeter Avalos header_compression = _7Z_COPY;
766c09f92d2SPeter Avalos #else
767c09f92d2SPeter Avalos header_compression = _7Z_COPY;
768c09f92d2SPeter Avalos #endif
769*50f8aa9cSAntonio Huete Jimenez r = _7z_compression_init_encoder(a, header_compression,
770*50f8aa9cSAntonio Huete Jimenez zip->opt_compression_level);
771c09f92d2SPeter Avalos if (r < 0)
772c09f92d2SPeter Avalos return (r);
773c09f92d2SPeter Avalos zip->crc32flg = PRECODE_CRC32;
774c09f92d2SPeter Avalos zip->precode_crc32 = 0;
775c09f92d2SPeter Avalos r = make_header(a, data_offset, data_size, data_unpacksize,
776c09f92d2SPeter Avalos 1, &(zip->coder));
777c09f92d2SPeter Avalos if (r < 0)
778c09f92d2SPeter Avalos return (r);
779c09f92d2SPeter Avalos r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH);
780c09f92d2SPeter Avalos if (r < 0)
781c09f92d2SPeter Avalos return (r);
782c09f92d2SPeter Avalos header_offset = data_offset + data_size;
783c09f92d2SPeter Avalos header_size = zip->stream.total_out;
784c09f92d2SPeter Avalos header_crc32 = zip->precode_crc32;
785c09f92d2SPeter Avalos header_unpacksize = zip->stream.total_in;
786c09f92d2SPeter Avalos
787c09f92d2SPeter Avalos if (header_compression != _7Z_COPY) {
788c09f92d2SPeter Avalos /*
789c09f92d2SPeter Avalos * Encode the header in order to reduce the size
790c09f92d2SPeter Avalos * of the archive.
791c09f92d2SPeter Avalos */
792c09f92d2SPeter Avalos free(zip->coder.props);
793c09f92d2SPeter Avalos zip->coder.codec = header_compression;
794c09f92d2SPeter Avalos zip->coder.prop_size = zip->stream.prop_size;
795c09f92d2SPeter Avalos zip->coder.props = zip->stream.props;
796c09f92d2SPeter Avalos zip->stream.prop_size = 0;
797c09f92d2SPeter Avalos zip->stream.props = NULL;
798c09f92d2SPeter Avalos
799c09f92d2SPeter Avalos r = _7z_compression_init_encoder(a, _7Z_COPY, 0);
800c09f92d2SPeter Avalos if (r < 0)
801c09f92d2SPeter Avalos return (r);
802c09f92d2SPeter Avalos zip->crc32flg = ENCODED_CRC32;
803c09f92d2SPeter Avalos zip->encoded_crc32 = 0;
804c09f92d2SPeter Avalos
805c09f92d2SPeter Avalos /*
806c09f92d2SPeter Avalos * Make EncodedHeader.
807c09f92d2SPeter Avalos */
808c09f92d2SPeter Avalos r = enc_uint64(a, kEncodedHeader);
809c09f92d2SPeter Avalos if (r < 0)
810c09f92d2SPeter Avalos return (r);
811c09f92d2SPeter Avalos r = make_streamsInfo(a, header_offset, header_size,
812c09f92d2SPeter Avalos header_unpacksize, 1, &(zip->coder), 0,
813c09f92d2SPeter Avalos header_crc32);
814c09f92d2SPeter Avalos if (r < 0)
815c09f92d2SPeter Avalos return (r);
816c09f92d2SPeter Avalos r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH);
817c09f92d2SPeter Avalos if (r < 0)
818c09f92d2SPeter Avalos return (r);
819c09f92d2SPeter Avalos header_offset = header_offset + header_size;
820c09f92d2SPeter Avalos header_size = zip->stream.total_out;
821c09f92d2SPeter Avalos header_crc32 = zip->encoded_crc32;
822c09f92d2SPeter Avalos }
823c09f92d2SPeter Avalos zip->crc32flg = 0;
824c09f92d2SPeter Avalos } else {
825c09f92d2SPeter Avalos header_offset = header_size = 0;
826c09f92d2SPeter Avalos header_crc32 = 0;
827c09f92d2SPeter Avalos }
828c09f92d2SPeter Avalos
829c09f92d2SPeter Avalos length = zip->temp_offset;
830c09f92d2SPeter Avalos
831c09f92d2SPeter Avalos /*
832c09f92d2SPeter Avalos * Make the zip header on wbuff(write buffer).
833c09f92d2SPeter Avalos */
834c09f92d2SPeter Avalos wb = zip->wbuff;
835c09f92d2SPeter Avalos zip->wbuff_remaining = sizeof(zip->wbuff);
836c09f92d2SPeter Avalos memcpy(&wb[0], "7z\xBC\xAF\x27\x1C", 6);
837c09f92d2SPeter Avalos wb[6] = 0;/* Major version. */
838c09f92d2SPeter Avalos wb[7] = 3;/* Minor version. */
839c09f92d2SPeter Avalos archive_le64enc(&wb[12], header_offset);/* Next Header Offset */
840c09f92d2SPeter Avalos archive_le64enc(&wb[20], header_size);/* Next Header Size */
841c09f92d2SPeter Avalos archive_le32enc(&wb[28], header_crc32);/* Next Header CRC */
842c09f92d2SPeter Avalos archive_le32enc(&wb[8], crc32(0, &wb[12], 20));/* Start Header CRC */
843c09f92d2SPeter Avalos zip->wbuff_remaining -= 32;
844c09f92d2SPeter Avalos
845c09f92d2SPeter Avalos /*
846c09f92d2SPeter Avalos * Read all file contents and an encoded header from the temporary
847c09f92d2SPeter Avalos * file and write out it.
848c09f92d2SPeter Avalos */
849c09f92d2SPeter Avalos r = copy_out(a, 0, length);
850c09f92d2SPeter Avalos if (r != ARCHIVE_OK)
851c09f92d2SPeter Avalos return (r);
852c09f92d2SPeter Avalos r = flush_wbuff(a);
853c09f92d2SPeter Avalos return (r);
854c09f92d2SPeter Avalos }
855c09f92d2SPeter Avalos
856c09f92d2SPeter Avalos /*
857c09f92d2SPeter Avalos * Encode 64 bits value into 7-Zip's encoded UINT64 value.
858c09f92d2SPeter Avalos */
859c09f92d2SPeter Avalos static int
enc_uint64(struct archive_write * a,uint64_t val)860c09f92d2SPeter Avalos enc_uint64(struct archive_write *a, uint64_t val)
861c09f92d2SPeter Avalos {
862c09f92d2SPeter Avalos unsigned mask = 0x80;
863c09f92d2SPeter Avalos uint8_t numdata[9];
864c09f92d2SPeter Avalos int i;
865c09f92d2SPeter Avalos
866c09f92d2SPeter Avalos numdata[0] = 0;
86759bf7050SPeter Avalos for (i = 1; i < (int)sizeof(numdata); i++) {
868c09f92d2SPeter Avalos if (val < mask) {
869c09f92d2SPeter Avalos numdata[0] |= (uint8_t)val;
870c09f92d2SPeter Avalos break;
871c09f92d2SPeter Avalos }
872c09f92d2SPeter Avalos numdata[i] = (uint8_t)val;
873c09f92d2SPeter Avalos val >>= 8;
874c09f92d2SPeter Avalos numdata[0] |= mask;
875c09f92d2SPeter Avalos mask >>= 1;
876c09f92d2SPeter Avalos }
877d4d8193eSPeter Avalos return ((int)compress_out(a, numdata, i, ARCHIVE_Z_RUN));
878c09f92d2SPeter Avalos }
879c09f92d2SPeter Avalos
880c09f92d2SPeter Avalos static int
make_substreamsInfo(struct archive_write * a,struct coder * coders)881c09f92d2SPeter Avalos make_substreamsInfo(struct archive_write *a, struct coder *coders)
882c09f92d2SPeter Avalos {
883c09f92d2SPeter Avalos struct _7zip *zip = (struct _7zip *)a->format_data;
884c09f92d2SPeter Avalos struct file *file;
885c09f92d2SPeter Avalos int r;
886c09f92d2SPeter Avalos
887c09f92d2SPeter Avalos /*
888c09f92d2SPeter Avalos * Make SubStreamsInfo.
889c09f92d2SPeter Avalos */
890c09f92d2SPeter Avalos r = enc_uint64(a, kSubStreamsInfo);
891c09f92d2SPeter Avalos if (r < 0)
892c09f92d2SPeter Avalos return (r);
893c09f92d2SPeter Avalos
894c09f92d2SPeter Avalos if (zip->total_number_nonempty_entry > 1 && coders->codec != _7Z_COPY) {
895c09f92d2SPeter Avalos /*
896c09f92d2SPeter Avalos * Make NumUnPackStream.
897c09f92d2SPeter Avalos */
898c09f92d2SPeter Avalos r = enc_uint64(a, kNumUnPackStream);
899c09f92d2SPeter Avalos if (r < 0)
900c09f92d2SPeter Avalos return (r);
901c09f92d2SPeter Avalos
902c09f92d2SPeter Avalos /* Write numUnpackStreams */
903c09f92d2SPeter Avalos r = enc_uint64(a, zip->total_number_nonempty_entry);
904c09f92d2SPeter Avalos if (r < 0)
905c09f92d2SPeter Avalos return (r);
906c09f92d2SPeter Avalos
907c09f92d2SPeter Avalos /*
908c09f92d2SPeter Avalos * Make kSize.
909c09f92d2SPeter Avalos */
910c09f92d2SPeter Avalos r = enc_uint64(a, kSize);
911c09f92d2SPeter Avalos if (r < 0)
912c09f92d2SPeter Avalos return (r);
913c09f92d2SPeter Avalos file = zip->file_list.first;
914c09f92d2SPeter Avalos for (;file != NULL; file = file->next) {
915c09f92d2SPeter Avalos if (file->next == NULL ||
916c09f92d2SPeter Avalos file->next->size == 0)
917c09f92d2SPeter Avalos break;
918c09f92d2SPeter Avalos r = enc_uint64(a, file->size);
919c09f92d2SPeter Avalos if (r < 0)
920c09f92d2SPeter Avalos return (r);
921c09f92d2SPeter Avalos }
922c09f92d2SPeter Avalos }
923c09f92d2SPeter Avalos
924c09f92d2SPeter Avalos /*
925c09f92d2SPeter Avalos * Make CRC.
926c09f92d2SPeter Avalos */
927c09f92d2SPeter Avalos r = enc_uint64(a, kCRC);
928c09f92d2SPeter Avalos if (r < 0)
929c09f92d2SPeter Avalos return (r);
930c09f92d2SPeter Avalos
931c09f92d2SPeter Avalos
932c09f92d2SPeter Avalos /* All are defined */
933c09f92d2SPeter Avalos r = enc_uint64(a, 1);
934c09f92d2SPeter Avalos if (r < 0)
935c09f92d2SPeter Avalos return (r);
936c09f92d2SPeter Avalos file = zip->file_list.first;
937c09f92d2SPeter Avalos for (;file != NULL; file = file->next) {
938c09f92d2SPeter Avalos uint8_t crc[4];
939c09f92d2SPeter Avalos if (file->size == 0)
940c09f92d2SPeter Avalos break;
941c09f92d2SPeter Avalos archive_le32enc(crc, file->crc32);
942d4d8193eSPeter Avalos r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN);
943c09f92d2SPeter Avalos if (r < 0)
944c09f92d2SPeter Avalos return (r);
945c09f92d2SPeter Avalos }
946c09f92d2SPeter Avalos
947c09f92d2SPeter Avalos /* Write End. */
948c09f92d2SPeter Avalos r = enc_uint64(a, kEnd);
949c09f92d2SPeter Avalos if (r < 0)
950c09f92d2SPeter Avalos return (r);
951c09f92d2SPeter Avalos return (ARCHIVE_OK);
952c09f92d2SPeter Avalos }
953c09f92d2SPeter Avalos
954c09f92d2SPeter Avalos static int
make_streamsInfo(struct archive_write * a,uint64_t offset,uint64_t pack_size,uint64_t unpack_size,int num_coder,struct coder * coders,int substrm,uint32_t header_crc)955c09f92d2SPeter Avalos make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size,
956c09f92d2SPeter Avalos uint64_t unpack_size, int num_coder, struct coder *coders, int substrm,
957c09f92d2SPeter Avalos uint32_t header_crc)
958c09f92d2SPeter Avalos {
959c09f92d2SPeter Avalos struct _7zip *zip = (struct _7zip *)a->format_data;
960c09f92d2SPeter Avalos uint8_t codec_buff[8];
961c09f92d2SPeter Avalos int numFolders, fi;
962c09f92d2SPeter Avalos int codec_size;
963c09f92d2SPeter Avalos int i, r;
964c09f92d2SPeter Avalos
965c09f92d2SPeter Avalos if (coders->codec == _7Z_COPY)
966d4d8193eSPeter Avalos numFolders = (int)zip->total_number_nonempty_entry;
967c09f92d2SPeter Avalos else
968c09f92d2SPeter Avalos numFolders = 1;
969c09f92d2SPeter Avalos
970c09f92d2SPeter Avalos /*
971c09f92d2SPeter Avalos * Make PackInfo.
972c09f92d2SPeter Avalos */
973c09f92d2SPeter Avalos r = enc_uint64(a, kPackInfo);
974c09f92d2SPeter Avalos if (r < 0)
975c09f92d2SPeter Avalos return (r);
976c09f92d2SPeter Avalos
977c09f92d2SPeter Avalos /* Write PackPos. */
978c09f92d2SPeter Avalos r = enc_uint64(a, offset);
979c09f92d2SPeter Avalos if (r < 0)
980c09f92d2SPeter Avalos return (r);
981c09f92d2SPeter Avalos
982c09f92d2SPeter Avalos /* Write NumPackStreams. */
983c09f92d2SPeter Avalos r = enc_uint64(a, numFolders);
984c09f92d2SPeter Avalos if (r < 0)
985c09f92d2SPeter Avalos return (r);
986c09f92d2SPeter Avalos
987c09f92d2SPeter Avalos /* Make Size. */
988c09f92d2SPeter Avalos r = enc_uint64(a, kSize);
989c09f92d2SPeter Avalos if (r < 0)
990c09f92d2SPeter Avalos return (r);
991c09f92d2SPeter Avalos
992c09f92d2SPeter Avalos if (numFolders > 1) {
993c09f92d2SPeter Avalos struct file *file = zip->file_list.first;
994c09f92d2SPeter Avalos for (;file != NULL; file = file->next) {
995c09f92d2SPeter Avalos if (file->size == 0)
996c09f92d2SPeter Avalos break;
997c09f92d2SPeter Avalos r = enc_uint64(a, file->size);
998c09f92d2SPeter Avalos if (r < 0)
999c09f92d2SPeter Avalos return (r);
1000c09f92d2SPeter Avalos }
1001c09f92d2SPeter Avalos } else {
1002c09f92d2SPeter Avalos /* Write size. */
1003c09f92d2SPeter Avalos r = enc_uint64(a, pack_size);
1004c09f92d2SPeter Avalos if (r < 0)
1005c09f92d2SPeter Avalos return (r);
1006c09f92d2SPeter Avalos }
1007c09f92d2SPeter Avalos
1008c09f92d2SPeter Avalos r = enc_uint64(a, kEnd);
1009c09f92d2SPeter Avalos if (r < 0)
1010c09f92d2SPeter Avalos return (r);
1011c09f92d2SPeter Avalos
1012c09f92d2SPeter Avalos /*
1013c09f92d2SPeter Avalos * Make UnPackInfo.
1014c09f92d2SPeter Avalos */
1015c09f92d2SPeter Avalos r = enc_uint64(a, kUnPackInfo);
1016c09f92d2SPeter Avalos if (r < 0)
1017c09f92d2SPeter Avalos return (r);
1018c09f92d2SPeter Avalos
1019c09f92d2SPeter Avalos /*
1020c09f92d2SPeter Avalos * Make Folder.
1021c09f92d2SPeter Avalos */
1022c09f92d2SPeter Avalos r = enc_uint64(a, kFolder);
1023c09f92d2SPeter Avalos if (r < 0)
1024c09f92d2SPeter Avalos return (r);
1025c09f92d2SPeter Avalos
1026c09f92d2SPeter Avalos /* Write NumFolders. */
1027c09f92d2SPeter Avalos r = enc_uint64(a, numFolders);
1028c09f92d2SPeter Avalos if (r < 0)
1029c09f92d2SPeter Avalos return (r);
1030c09f92d2SPeter Avalos
1031c09f92d2SPeter Avalos /* Write External. */
1032c09f92d2SPeter Avalos r = enc_uint64(a, 0);
1033c09f92d2SPeter Avalos if (r < 0)
1034c09f92d2SPeter Avalos return (r);
1035c09f92d2SPeter Avalos
1036c09f92d2SPeter Avalos for (fi = 0; fi < numFolders; fi++) {
1037c09f92d2SPeter Avalos /* Write NumCoders. */
1038c09f92d2SPeter Avalos r = enc_uint64(a, num_coder);
1039c09f92d2SPeter Avalos if (r < 0)
1040c09f92d2SPeter Avalos return (r);
1041c09f92d2SPeter Avalos
1042c09f92d2SPeter Avalos for (i = 0; i < num_coder; i++) {
1043c09f92d2SPeter Avalos unsigned codec_id = coders[i].codec;
1044c09f92d2SPeter Avalos
1045c09f92d2SPeter Avalos /* Write Codec flag. */
1046c09f92d2SPeter Avalos archive_be64enc(codec_buff, codec_id);
1047c09f92d2SPeter Avalos for (codec_size = 8; codec_size > 0; codec_size--) {
1048c09f92d2SPeter Avalos if (codec_buff[8 - codec_size])
1049c09f92d2SPeter Avalos break;
1050c09f92d2SPeter Avalos }
1051c09f92d2SPeter Avalos if (codec_size == 0)
1052c09f92d2SPeter Avalos codec_size = 1;
1053c09f92d2SPeter Avalos if (coders[i].prop_size)
1054c09f92d2SPeter Avalos r = enc_uint64(a, codec_size | 0x20);
1055c09f92d2SPeter Avalos else
1056c09f92d2SPeter Avalos r = enc_uint64(a, codec_size);
1057c09f92d2SPeter Avalos if (r < 0)
1058c09f92d2SPeter Avalos return (r);
1059c09f92d2SPeter Avalos
1060c09f92d2SPeter Avalos /* Write Codec ID. */
1061c09f92d2SPeter Avalos codec_size &= 0x0f;
1062d4d8193eSPeter Avalos r = (int)compress_out(a, &codec_buff[8-codec_size],
1063c09f92d2SPeter Avalos codec_size, ARCHIVE_Z_RUN);
1064c09f92d2SPeter Avalos if (r < 0)
1065c09f92d2SPeter Avalos return (r);
1066c09f92d2SPeter Avalos
1067c09f92d2SPeter Avalos if (coders[i].prop_size) {
1068c09f92d2SPeter Avalos /* Write Codec property size. */
1069c09f92d2SPeter Avalos r = enc_uint64(a, coders[i].prop_size);
1070c09f92d2SPeter Avalos if (r < 0)
1071c09f92d2SPeter Avalos return (r);
1072c09f92d2SPeter Avalos
1073c09f92d2SPeter Avalos /* Write Codec properties. */
1074d4d8193eSPeter Avalos r = (int)compress_out(a, coders[i].props,
1075c09f92d2SPeter Avalos coders[i].prop_size, ARCHIVE_Z_RUN);
1076c09f92d2SPeter Avalos if (r < 0)
1077c09f92d2SPeter Avalos return (r);
1078c09f92d2SPeter Avalos }
1079c09f92d2SPeter Avalos }
1080c09f92d2SPeter Avalos }
1081c09f92d2SPeter Avalos
1082c09f92d2SPeter Avalos /*
1083c09f92d2SPeter Avalos * Make CodersUnPackSize.
1084c09f92d2SPeter Avalos */
1085c09f92d2SPeter Avalos r = enc_uint64(a, kCodersUnPackSize);
1086c09f92d2SPeter Avalos if (r < 0)
1087c09f92d2SPeter Avalos return (r);
1088c09f92d2SPeter Avalos
1089c09f92d2SPeter Avalos if (numFolders > 1) {
1090c09f92d2SPeter Avalos struct file *file = zip->file_list.first;
1091c09f92d2SPeter Avalos for (;file != NULL; file = file->next) {
1092c09f92d2SPeter Avalos if (file->size == 0)
1093c09f92d2SPeter Avalos break;
1094c09f92d2SPeter Avalos r = enc_uint64(a, file->size);
1095c09f92d2SPeter Avalos if (r < 0)
1096c09f92d2SPeter Avalos return (r);
1097c09f92d2SPeter Avalos }
1098c09f92d2SPeter Avalos
1099c09f92d2SPeter Avalos } else {
1100c09f92d2SPeter Avalos /* Write UnPackSize. */
1101c09f92d2SPeter Avalos r = enc_uint64(a, unpack_size);
1102c09f92d2SPeter Avalos if (r < 0)
1103c09f92d2SPeter Avalos return (r);
1104c09f92d2SPeter Avalos }
1105c09f92d2SPeter Avalos
1106c09f92d2SPeter Avalos if (!substrm) {
1107c09f92d2SPeter Avalos uint8_t crc[4];
1108c09f92d2SPeter Avalos /*
1109c09f92d2SPeter Avalos * Make CRC.
1110c09f92d2SPeter Avalos */
1111c09f92d2SPeter Avalos r = enc_uint64(a, kCRC);
1112c09f92d2SPeter Avalos if (r < 0)
1113c09f92d2SPeter Avalos return (r);
1114c09f92d2SPeter Avalos
1115c09f92d2SPeter Avalos /* All are defined */
1116c09f92d2SPeter Avalos r = enc_uint64(a, 1);
1117c09f92d2SPeter Avalos if (r < 0)
1118c09f92d2SPeter Avalos return (r);
1119c09f92d2SPeter Avalos archive_le32enc(crc, header_crc);
1120d4d8193eSPeter Avalos r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN);
1121c09f92d2SPeter Avalos if (r < 0)
1122c09f92d2SPeter Avalos return (r);
1123c09f92d2SPeter Avalos }
1124c09f92d2SPeter Avalos
1125c09f92d2SPeter Avalos /* Write End. */
1126c09f92d2SPeter Avalos r = enc_uint64(a, kEnd);
1127c09f92d2SPeter Avalos if (r < 0)
1128c09f92d2SPeter Avalos return (r);
1129c09f92d2SPeter Avalos
1130c09f92d2SPeter Avalos if (substrm) {
1131c09f92d2SPeter Avalos /*
1132c09f92d2SPeter Avalos * Make SubStreamsInfo.
1133c09f92d2SPeter Avalos */
1134c09f92d2SPeter Avalos r = make_substreamsInfo(a, coders);
1135c09f92d2SPeter Avalos if (r < 0)
1136c09f92d2SPeter Avalos return (r);
1137c09f92d2SPeter Avalos }
1138c09f92d2SPeter Avalos
1139c09f92d2SPeter Avalos
1140c09f92d2SPeter Avalos /* Write End. */
1141c09f92d2SPeter Avalos r = enc_uint64(a, kEnd);
1142c09f92d2SPeter Avalos if (r < 0)
1143c09f92d2SPeter Avalos return (r);
1144c09f92d2SPeter Avalos
1145c09f92d2SPeter Avalos return (ARCHIVE_OK);
1146c09f92d2SPeter Avalos }
1147c09f92d2SPeter Avalos
1148c09f92d2SPeter Avalos
1149c09f92d2SPeter Avalos #define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
1150c09f92d2SPeter Avalos static uint64_t
utcToFiletime(time_t t,long ns)115159bf7050SPeter Avalos utcToFiletime(time_t t, long ns)
1152c09f92d2SPeter Avalos {
1153c09f92d2SPeter Avalos uint64_t fileTime;
1154c09f92d2SPeter Avalos
115559bf7050SPeter Avalos fileTime = t;
1156c09f92d2SPeter Avalos fileTime *= 10000000;
1157c09f92d2SPeter Avalos fileTime += ns / 100;
1158c09f92d2SPeter Avalos fileTime += EPOC_TIME;
1159c09f92d2SPeter Avalos return (fileTime);
1160c09f92d2SPeter Avalos }
1161c09f92d2SPeter Avalos
1162c09f92d2SPeter Avalos static int
make_time(struct archive_write * a,uint8_t type,unsigned flg,int ti)1163c09f92d2SPeter Avalos make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
1164c09f92d2SPeter Avalos {
1165c09f92d2SPeter Avalos uint8_t filetime[8];
1166c09f92d2SPeter Avalos struct _7zip *zip = (struct _7zip *)a->format_data;
1167c09f92d2SPeter Avalos struct file *file;
1168c09f92d2SPeter Avalos int r;
116959bf7050SPeter Avalos uint8_t b, mask;
1170c09f92d2SPeter Avalos
1171c09f92d2SPeter Avalos /*
1172c09f92d2SPeter Avalos * Make Time Bools.
1173c09f92d2SPeter Avalos */
1174c09f92d2SPeter Avalos if (zip->total_number_time_defined[ti] == zip->total_number_entry) {
1175c09f92d2SPeter Avalos /* Write Time Type. */
1176c09f92d2SPeter Avalos r = enc_uint64(a, type);
1177c09f92d2SPeter Avalos if (r < 0)
1178c09f92d2SPeter Avalos return (r);
1179c09f92d2SPeter Avalos /* Write EmptyStream Size. */
1180c09f92d2SPeter Avalos r = enc_uint64(a, 2 + zip->total_number_entry * 8);
1181c09f92d2SPeter Avalos if (r < 0)
1182c09f92d2SPeter Avalos return (r);
1183c09f92d2SPeter Avalos /* All are defined. */
1184c09f92d2SPeter Avalos r = enc_uint64(a, 1);
1185c09f92d2SPeter Avalos if (r < 0)
1186c09f92d2SPeter Avalos return (r);
1187c09f92d2SPeter Avalos } else {
1188c09f92d2SPeter Avalos if (zip->total_number_time_defined[ti] == 0)
1189c09f92d2SPeter Avalos return (ARCHIVE_OK);
1190c09f92d2SPeter Avalos
1191c09f92d2SPeter Avalos /* Write Time Type. */
1192c09f92d2SPeter Avalos r = enc_uint64(a, type);
1193c09f92d2SPeter Avalos if (r < 0)
1194c09f92d2SPeter Avalos return (r);
1195c09f92d2SPeter Avalos /* Write EmptyStream Size. */
1196c09f92d2SPeter Avalos r = enc_uint64(a, 2 + ((zip->total_number_entry + 7) >> 3)
1197c09f92d2SPeter Avalos + zip->total_number_time_defined[ti] * 8);
1198c09f92d2SPeter Avalos if (r < 0)
1199c09f92d2SPeter Avalos return (r);
1200c09f92d2SPeter Avalos
1201c09f92d2SPeter Avalos /* All are not defined. */
1202c09f92d2SPeter Avalos r = enc_uint64(a, 0);
1203c09f92d2SPeter Avalos if (r < 0)
1204c09f92d2SPeter Avalos return (r);
1205c09f92d2SPeter Avalos
120659bf7050SPeter Avalos b = 0;
1207c09f92d2SPeter Avalos mask = 0x80;
1208c09f92d2SPeter Avalos file = zip->file_list.first;
1209c09f92d2SPeter Avalos for (;file != NULL; file = file->next) {
1210c09f92d2SPeter Avalos if (file->flg & flg)
121159bf7050SPeter Avalos b |= mask;
1212c09f92d2SPeter Avalos mask >>= 1;
1213c09f92d2SPeter Avalos if (mask == 0) {
1214d4d8193eSPeter Avalos r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1215c09f92d2SPeter Avalos if (r < 0)
1216c09f92d2SPeter Avalos return (r);
1217c09f92d2SPeter Avalos mask = 0x80;
121859bf7050SPeter Avalos b = 0;
1219c09f92d2SPeter Avalos }
1220c09f92d2SPeter Avalos }
1221c09f92d2SPeter Avalos if (mask != 0x80) {
1222d4d8193eSPeter Avalos r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1223c09f92d2SPeter Avalos if (r < 0)
1224c09f92d2SPeter Avalos return (r);
1225c09f92d2SPeter Avalos }
1226c09f92d2SPeter Avalos }
1227c09f92d2SPeter Avalos
1228c09f92d2SPeter Avalos /* External. */
1229c09f92d2SPeter Avalos r = enc_uint64(a, 0);
1230c09f92d2SPeter Avalos if (r < 0)
1231c09f92d2SPeter Avalos return (r);
1232c09f92d2SPeter Avalos
1233c09f92d2SPeter Avalos
1234c09f92d2SPeter Avalos /*
1235c09f92d2SPeter Avalos * Make Times.
1236c09f92d2SPeter Avalos */
1237c09f92d2SPeter Avalos file = zip->file_list.first;
1238c09f92d2SPeter Avalos for (;file != NULL; file = file->next) {
1239c09f92d2SPeter Avalos if ((file->flg & flg) == 0)
1240c09f92d2SPeter Avalos continue;
1241c09f92d2SPeter Avalos archive_le64enc(filetime, utcToFiletime(file->times[ti].time,
1242c09f92d2SPeter Avalos file->times[ti].time_ns));
1243d4d8193eSPeter Avalos r = (int)compress_out(a, filetime, 8, ARCHIVE_Z_RUN);
1244c09f92d2SPeter Avalos if (r < 0)
1245c09f92d2SPeter Avalos return (r);
1246c09f92d2SPeter Avalos }
1247c09f92d2SPeter Avalos
1248c09f92d2SPeter Avalos return (ARCHIVE_OK);
1249c09f92d2SPeter Avalos }
1250c09f92d2SPeter Avalos
1251c09f92d2SPeter Avalos static int
make_header(struct archive_write * a,uint64_t offset,uint64_t pack_size,uint64_t unpack_size,int codernum,struct coder * coders)1252c09f92d2SPeter Avalos make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size,
1253c09f92d2SPeter Avalos uint64_t unpack_size, int codernum, struct coder *coders)
1254c09f92d2SPeter Avalos {
1255c09f92d2SPeter Avalos struct _7zip *zip = (struct _7zip *)a->format_data;
1256c09f92d2SPeter Avalos struct file *file;
1257c09f92d2SPeter Avalos int r;
125859bf7050SPeter Avalos uint8_t b, mask;
1259c09f92d2SPeter Avalos
1260c09f92d2SPeter Avalos /*
1261c09f92d2SPeter Avalos * Make FilesInfo.
1262c09f92d2SPeter Avalos */
1263c09f92d2SPeter Avalos r = enc_uint64(a, kHeader);
1264c09f92d2SPeter Avalos if (r < 0)
1265c09f92d2SPeter Avalos return (r);
1266c09f92d2SPeter Avalos
1267c09f92d2SPeter Avalos /*
1268c09f92d2SPeter Avalos * If there are empty files only, do not write MainStreamInfo.
1269c09f92d2SPeter Avalos */
1270c09f92d2SPeter Avalos if (zip->total_number_nonempty_entry) {
1271c09f92d2SPeter Avalos /*
1272c09f92d2SPeter Avalos * Make MainStreamInfo.
1273c09f92d2SPeter Avalos */
1274c09f92d2SPeter Avalos r = enc_uint64(a, kMainStreamsInfo);
1275c09f92d2SPeter Avalos if (r < 0)
1276c09f92d2SPeter Avalos return (r);
1277c09f92d2SPeter Avalos r = make_streamsInfo(a, offset, pack_size, unpack_size,
1278c09f92d2SPeter Avalos codernum, coders, 1, 0);
1279c09f92d2SPeter Avalos if (r < 0)
1280c09f92d2SPeter Avalos return (r);
1281c09f92d2SPeter Avalos }
1282c09f92d2SPeter Avalos
1283c09f92d2SPeter Avalos /*
1284c09f92d2SPeter Avalos * Make FilesInfo.
1285c09f92d2SPeter Avalos */
1286c09f92d2SPeter Avalos r = enc_uint64(a, kFilesInfo);
1287c09f92d2SPeter Avalos if (r < 0)
1288c09f92d2SPeter Avalos return (r);
1289c09f92d2SPeter Avalos
1290c09f92d2SPeter Avalos /* Write numFiles. */
1291c09f92d2SPeter Avalos r = enc_uint64(a, zip->total_number_entry);
1292c09f92d2SPeter Avalos if (r < 0)
1293c09f92d2SPeter Avalos return (r);
1294c09f92d2SPeter Avalos
1295c09f92d2SPeter Avalos if (zip->total_number_empty_entry > 0) {
1296c09f92d2SPeter Avalos /* Make EmptyStream. */
1297c09f92d2SPeter Avalos r = enc_uint64(a, kEmptyStream);
1298c09f92d2SPeter Avalos if (r < 0)
1299c09f92d2SPeter Avalos return (r);
1300c09f92d2SPeter Avalos
1301c09f92d2SPeter Avalos /* Write EmptyStream Size. */
1302c09f92d2SPeter Avalos r = enc_uint64(a, (zip->total_number_entry+7)>>3);
1303c09f92d2SPeter Avalos if (r < 0)
1304c09f92d2SPeter Avalos return (r);
1305c09f92d2SPeter Avalos
130659bf7050SPeter Avalos b = 0;
1307c09f92d2SPeter Avalos mask = 0x80;
1308c09f92d2SPeter Avalos file = zip->file_list.first;
1309c09f92d2SPeter Avalos for (;file != NULL; file = file->next) {
1310c09f92d2SPeter Avalos if (file->size == 0)
131159bf7050SPeter Avalos b |= mask;
1312c09f92d2SPeter Avalos mask >>= 1;
1313c09f92d2SPeter Avalos if (mask == 0) {
1314d4d8193eSPeter Avalos r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1315c09f92d2SPeter Avalos if (r < 0)
1316c09f92d2SPeter Avalos return (r);
1317c09f92d2SPeter Avalos mask = 0x80;
131859bf7050SPeter Avalos b = 0;
1319c09f92d2SPeter Avalos }
1320c09f92d2SPeter Avalos }
1321c09f92d2SPeter Avalos if (mask != 0x80) {
1322d4d8193eSPeter Avalos r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1323c09f92d2SPeter Avalos if (r < 0)
1324c09f92d2SPeter Avalos return (r);
1325c09f92d2SPeter Avalos }
1326c09f92d2SPeter Avalos }
1327c09f92d2SPeter Avalos
1328c09f92d2SPeter Avalos if (zip->total_number_empty_entry > zip->total_number_dir_entry) {
1329c09f92d2SPeter Avalos /* Make EmptyFile. */
1330c09f92d2SPeter Avalos r = enc_uint64(a, kEmptyFile);
1331c09f92d2SPeter Avalos if (r < 0)
1332c09f92d2SPeter Avalos return (r);
1333c09f92d2SPeter Avalos
1334c09f92d2SPeter Avalos /* Write EmptyFile Size. */
1335c09f92d2SPeter Avalos r = enc_uint64(a, (zip->total_number_empty_entry + 7) >> 3);
1336c09f92d2SPeter Avalos if (r < 0)
1337c09f92d2SPeter Avalos return (r);
1338c09f92d2SPeter Avalos
133959bf7050SPeter Avalos b = 0;
1340c09f92d2SPeter Avalos mask = 0x80;
1341c09f92d2SPeter Avalos file = zip->file_list.first;
1342c09f92d2SPeter Avalos for (;file != NULL; file = file->next) {
1343c09f92d2SPeter Avalos if (file->size)
1344c09f92d2SPeter Avalos continue;
1345c09f92d2SPeter Avalos if (!file->dir)
134659bf7050SPeter Avalos b |= mask;
1347c09f92d2SPeter Avalos mask >>= 1;
1348c09f92d2SPeter Avalos if (mask == 0) {
1349d4d8193eSPeter Avalos r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1350c09f92d2SPeter Avalos if (r < 0)
1351c09f92d2SPeter Avalos return (r);
1352c09f92d2SPeter Avalos mask = 0x80;
135359bf7050SPeter Avalos b = 0;
1354c09f92d2SPeter Avalos }
1355c09f92d2SPeter Avalos }
1356c09f92d2SPeter Avalos if (mask != 0x80) {
1357d4d8193eSPeter Avalos r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1358c09f92d2SPeter Avalos if (r < 0)
1359c09f92d2SPeter Avalos return (r);
1360c09f92d2SPeter Avalos }
1361c09f92d2SPeter Avalos }
1362c09f92d2SPeter Avalos
1363c09f92d2SPeter Avalos /* Make Name. */
1364c09f92d2SPeter Avalos r = enc_uint64(a, kName);
1365c09f92d2SPeter Avalos if (r < 0)
1366c09f92d2SPeter Avalos return (r);
1367c09f92d2SPeter Avalos
1368e95abc47Szrj /* Write Name size. */
1369c09f92d2SPeter Avalos r = enc_uint64(a, zip->total_bytes_entry_name+1);
1370c09f92d2SPeter Avalos if (r < 0)
1371c09f92d2SPeter Avalos return (r);
1372c09f92d2SPeter Avalos
1373c09f92d2SPeter Avalos /* Write dmy byte. */
1374c09f92d2SPeter Avalos r = enc_uint64(a, 0);
1375c09f92d2SPeter Avalos if (r < 0)
1376c09f92d2SPeter Avalos return (r);
1377c09f92d2SPeter Avalos
1378c09f92d2SPeter Avalos file = zip->file_list.first;
1379c09f92d2SPeter Avalos for (;file != NULL; file = file->next) {
1380d4d8193eSPeter Avalos r = (int)compress_out(a, file->utf16name, file->name_len+2,
1381c09f92d2SPeter Avalos ARCHIVE_Z_RUN);
1382c09f92d2SPeter Avalos if (r < 0)
1383c09f92d2SPeter Avalos return (r);
1384c09f92d2SPeter Avalos }
1385c09f92d2SPeter Avalos
1386c09f92d2SPeter Avalos /* Make MTime. */
1387c09f92d2SPeter Avalos r = make_time(a, kMTime, MTIME_IS_SET, MTIME);
1388c09f92d2SPeter Avalos if (r < 0)
1389c09f92d2SPeter Avalos return (r);
1390c09f92d2SPeter Avalos
1391c09f92d2SPeter Avalos /* Make CTime. */
1392c09f92d2SPeter Avalos r = make_time(a, kCTime, CTIME_IS_SET, CTIME);
1393c09f92d2SPeter Avalos if (r < 0)
1394c09f92d2SPeter Avalos return (r);
1395c09f92d2SPeter Avalos
1396c09f92d2SPeter Avalos /* Make ATime. */
1397c09f92d2SPeter Avalos r = make_time(a, kATime, ATIME_IS_SET, ATIME);
1398c09f92d2SPeter Avalos if (r < 0)
1399c09f92d2SPeter Avalos return (r);
1400c09f92d2SPeter Avalos
1401c09f92d2SPeter Avalos /* Make Attributes. */
1402c09f92d2SPeter Avalos r = enc_uint64(a, kAttributes);
1403c09f92d2SPeter Avalos if (r < 0)
1404c09f92d2SPeter Avalos return (r);
1405c09f92d2SPeter Avalos
1406c09f92d2SPeter Avalos /* Write Attributes size. */
1407c09f92d2SPeter Avalos r = enc_uint64(a, 2 + zip->total_number_entry * 4);
1408c09f92d2SPeter Avalos if (r < 0)
1409c09f92d2SPeter Avalos return (r);
1410c09f92d2SPeter Avalos
1411c09f92d2SPeter Avalos /* Write "All Are Defined". */
1412c09f92d2SPeter Avalos r = enc_uint64(a, 1);
1413c09f92d2SPeter Avalos if (r < 0)
1414c09f92d2SPeter Avalos return (r);
1415c09f92d2SPeter Avalos
1416c09f92d2SPeter Avalos /* Write dmy byte. */
1417c09f92d2SPeter Avalos r = enc_uint64(a, 0);
1418c09f92d2SPeter Avalos if (r < 0)
1419c09f92d2SPeter Avalos return (r);
1420c09f92d2SPeter Avalos
1421c09f92d2SPeter Avalos file = zip->file_list.first;
1422c09f92d2SPeter Avalos for (;file != NULL; file = file->next) {
1423c09f92d2SPeter Avalos /*
1424c09f92d2SPeter Avalos * High 16bits is unix mode.
1425c09f92d2SPeter Avalos * Low 16bits is Windows attributes.
1426c09f92d2SPeter Avalos */
1427c09f92d2SPeter Avalos uint32_t encattr, attr;
1428c09f92d2SPeter Avalos if (file->dir)
1429c09f92d2SPeter Avalos attr = 0x8010;
1430c09f92d2SPeter Avalos else
1431c09f92d2SPeter Avalos attr = 0x8020;
1432c09f92d2SPeter Avalos if ((file->mode & 0222) == 0)
1433c09f92d2SPeter Avalos attr |= 1;/* Read Only. */
1434c09f92d2SPeter Avalos attr |= ((uint32_t)file->mode) << 16;
1435c09f92d2SPeter Avalos archive_le32enc(&encattr, attr);
1436d4d8193eSPeter Avalos r = (int)compress_out(a, &encattr, 4, ARCHIVE_Z_RUN);
1437c09f92d2SPeter Avalos if (r < 0)
1438c09f92d2SPeter Avalos return (r);
1439c09f92d2SPeter Avalos }
1440c09f92d2SPeter Avalos
1441c09f92d2SPeter Avalos /* Write End. */
1442c09f92d2SPeter Avalos r = enc_uint64(a, kEnd);
1443c09f92d2SPeter Avalos if (r < 0)
1444c09f92d2SPeter Avalos return (r);
1445c09f92d2SPeter Avalos
1446c09f92d2SPeter Avalos /* Write End. */
1447c09f92d2SPeter Avalos r = enc_uint64(a, kEnd);
1448c09f92d2SPeter Avalos if (r < 0)
1449c09f92d2SPeter Avalos return (r);
1450c09f92d2SPeter Avalos
1451c09f92d2SPeter Avalos return (ARCHIVE_OK);
1452c09f92d2SPeter Avalos }
1453c09f92d2SPeter Avalos
1454c09f92d2SPeter Avalos
1455c09f92d2SPeter Avalos static int
_7z_free(struct archive_write * a)1456c09f92d2SPeter Avalos _7z_free(struct archive_write *a)
1457c09f92d2SPeter Avalos {
1458c09f92d2SPeter Avalos struct _7zip *zip = (struct _7zip *)a->format_data;
1459c09f92d2SPeter Avalos
14606b384f39SPeter Avalos /* Close the temporary file. */
14616b384f39SPeter Avalos if (zip->temp_fd >= 0)
14626b384f39SPeter Avalos close(zip->temp_fd);
14636b384f39SPeter Avalos
1464c09f92d2SPeter Avalos file_free_register(zip);
1465c09f92d2SPeter Avalos compression_end(&(a->archive), &(zip->stream));
1466c09f92d2SPeter Avalos free(zip->coder.props);
1467c09f92d2SPeter Avalos free(zip);
1468c09f92d2SPeter Avalos
1469c09f92d2SPeter Avalos return (ARCHIVE_OK);
1470c09f92d2SPeter Avalos }
1471c09f92d2SPeter Avalos
1472c09f92d2SPeter Avalos static int
file_cmp_node(const struct archive_rb_node * n1,const struct archive_rb_node * n2)1473c09f92d2SPeter Avalos file_cmp_node(const struct archive_rb_node *n1,
1474c09f92d2SPeter Avalos const struct archive_rb_node *n2)
1475c09f92d2SPeter Avalos {
147659bf7050SPeter Avalos const struct file *f1 = (const struct file *)n1;
147759bf7050SPeter Avalos const struct file *f2 = (const struct file *)n2;
1478c09f92d2SPeter Avalos
1479c09f92d2SPeter Avalos if (f1->name_len == f2->name_len)
1480c09f92d2SPeter Avalos return (memcmp(f1->utf16name, f2->utf16name, f1->name_len));
1481c09f92d2SPeter Avalos return (f1->name_len > f2->name_len)?1:-1;
1482c09f92d2SPeter Avalos }
1483c09f92d2SPeter Avalos
1484c09f92d2SPeter Avalos static int
file_cmp_key(const struct archive_rb_node * n,const void * key)1485c09f92d2SPeter Avalos file_cmp_key(const struct archive_rb_node *n, const void *key)
1486c09f92d2SPeter Avalos {
148759bf7050SPeter Avalos const struct file *f = (const struct file *)n;
1488c09f92d2SPeter Avalos
1489c09f92d2SPeter Avalos return (f->name_len - *(const char *)key);
1490c09f92d2SPeter Avalos }
1491c09f92d2SPeter Avalos
1492c09f92d2SPeter Avalos static int
file_new(struct archive_write * a,struct archive_entry * entry,struct file ** newfile)1493c09f92d2SPeter Avalos file_new(struct archive_write *a, struct archive_entry *entry,
1494c09f92d2SPeter Avalos struct file **newfile)
1495c09f92d2SPeter Avalos {
1496c09f92d2SPeter Avalos struct _7zip *zip;
1497c09f92d2SPeter Avalos struct file *file;
1498c09f92d2SPeter Avalos const char *u16;
1499c09f92d2SPeter Avalos size_t u16len;
1500c09f92d2SPeter Avalos int ret = ARCHIVE_OK;
1501c09f92d2SPeter Avalos
1502c09f92d2SPeter Avalos zip = (struct _7zip *)a->format_data;
1503c09f92d2SPeter Avalos *newfile = NULL;
1504c09f92d2SPeter Avalos
1505c09f92d2SPeter Avalos file = calloc(1, sizeof(*file));
1506c09f92d2SPeter Avalos if (file == NULL) {
1507c09f92d2SPeter Avalos archive_set_error(&a->archive, ENOMEM,
1508c09f92d2SPeter Avalos "Can't allocate memory");
1509c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
1510c09f92d2SPeter Avalos }
1511c09f92d2SPeter Avalos
1512c09f92d2SPeter Avalos if (0 > archive_entry_pathname_l(entry, &u16, &u16len, zip->sconv)) {
1513c09f92d2SPeter Avalos if (errno == ENOMEM) {
151459bf7050SPeter Avalos free(file);
1515c09f92d2SPeter Avalos archive_set_error(&a->archive, ENOMEM,
1516c09f92d2SPeter Avalos "Can't allocate memory for UTF-16LE");
1517c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
1518c09f92d2SPeter Avalos }
1519c09f92d2SPeter Avalos archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1520c09f92d2SPeter Avalos "A filename cannot be converted to UTF-16LE;"
1521c09f92d2SPeter Avalos "You should disable making Joliet extension");
1522c09f92d2SPeter Avalos ret = ARCHIVE_WARN;
1523c09f92d2SPeter Avalos }
1524c09f92d2SPeter Avalos file->utf16name = malloc(u16len + 2);
1525c09f92d2SPeter Avalos if (file->utf16name == NULL) {
152659bf7050SPeter Avalos free(file);
1527c09f92d2SPeter Avalos archive_set_error(&a->archive, ENOMEM,
1528c09f92d2SPeter Avalos "Can't allocate memory for Name");
1529c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
1530c09f92d2SPeter Avalos }
1531c09f92d2SPeter Avalos memcpy(file->utf16name, u16, u16len);
1532c09f92d2SPeter Avalos file->utf16name[u16len+0] = 0;
1533c09f92d2SPeter Avalos file->utf16name[u16len+1] = 0;
1534d4d8193eSPeter Avalos file->name_len = (unsigned)u16len;
1535c09f92d2SPeter Avalos file->mode = archive_entry_mode(entry);
1536c09f92d2SPeter Avalos if (archive_entry_filetype(entry) == AE_IFREG)
1537c09f92d2SPeter Avalos file->size = archive_entry_size(entry);
1538c09f92d2SPeter Avalos else
1539c09f92d2SPeter Avalos archive_entry_set_size(entry, 0);
1540c09f92d2SPeter Avalos if (archive_entry_filetype(entry) == AE_IFDIR)
1541c09f92d2SPeter Avalos file->dir = 1;
1542c09f92d2SPeter Avalos else if (archive_entry_filetype(entry) == AE_IFLNK)
1543c09f92d2SPeter Avalos file->size = strlen(archive_entry_symlink(entry));
1544c09f92d2SPeter Avalos if (archive_entry_mtime_is_set(entry)) {
1545c09f92d2SPeter Avalos file->flg |= MTIME_IS_SET;
1546c09f92d2SPeter Avalos file->times[MTIME].time = archive_entry_mtime(entry);
1547c09f92d2SPeter Avalos file->times[MTIME].time_ns = archive_entry_mtime_nsec(entry);
1548c09f92d2SPeter Avalos }
1549c09f92d2SPeter Avalos if (archive_entry_atime_is_set(entry)) {
1550c09f92d2SPeter Avalos file->flg |= ATIME_IS_SET;
1551c09f92d2SPeter Avalos file->times[ATIME].time = archive_entry_atime(entry);
1552c09f92d2SPeter Avalos file->times[ATIME].time_ns = archive_entry_atime_nsec(entry);
1553c09f92d2SPeter Avalos }
1554c09f92d2SPeter Avalos if (archive_entry_ctime_is_set(entry)) {
1555c09f92d2SPeter Avalos file->flg |= CTIME_IS_SET;
1556c09f92d2SPeter Avalos file->times[CTIME].time = archive_entry_ctime(entry);
1557c09f92d2SPeter Avalos file->times[CTIME].time_ns = archive_entry_ctime_nsec(entry);
1558c09f92d2SPeter Avalos }
1559c09f92d2SPeter Avalos
1560c09f92d2SPeter Avalos *newfile = file;
1561c09f92d2SPeter Avalos return (ret);
1562c09f92d2SPeter Avalos }
1563c09f92d2SPeter Avalos
1564c09f92d2SPeter Avalos static void
file_free(struct file * file)1565c09f92d2SPeter Avalos file_free(struct file *file)
1566c09f92d2SPeter Avalos {
1567c09f92d2SPeter Avalos free(file->utf16name);
1568c09f92d2SPeter Avalos free(file);
1569c09f92d2SPeter Avalos }
1570c09f92d2SPeter Avalos
1571c09f92d2SPeter Avalos static void
file_register(struct _7zip * zip,struct file * file)1572c09f92d2SPeter Avalos file_register(struct _7zip *zip, struct file *file)
1573c09f92d2SPeter Avalos {
1574c09f92d2SPeter Avalos file->next = NULL;
1575c09f92d2SPeter Avalos *zip->file_list.last = file;
1576c09f92d2SPeter Avalos zip->file_list.last = &(file->next);
1577c09f92d2SPeter Avalos }
1578c09f92d2SPeter Avalos
1579c09f92d2SPeter Avalos static void
file_init_register(struct _7zip * zip)1580c09f92d2SPeter Avalos file_init_register(struct _7zip *zip)
1581c09f92d2SPeter Avalos {
1582c09f92d2SPeter Avalos zip->file_list.first = NULL;
1583c09f92d2SPeter Avalos zip->file_list.last = &(zip->file_list.first);
1584c09f92d2SPeter Avalos }
1585c09f92d2SPeter Avalos
1586c09f92d2SPeter Avalos static void
file_free_register(struct _7zip * zip)1587c09f92d2SPeter Avalos file_free_register(struct _7zip *zip)
1588c09f92d2SPeter Avalos {
1589c09f92d2SPeter Avalos struct file *file, *file_next;
1590c09f92d2SPeter Avalos
1591c09f92d2SPeter Avalos file = zip->file_list.first;
1592c09f92d2SPeter Avalos while (file != NULL) {
1593c09f92d2SPeter Avalos file_next = file->next;
1594c09f92d2SPeter Avalos file_free(file);
1595c09f92d2SPeter Avalos file = file_next;
1596c09f92d2SPeter Avalos }
1597c09f92d2SPeter Avalos }
1598c09f92d2SPeter Avalos
1599c09f92d2SPeter Avalos static void
file_register_empty(struct _7zip * zip,struct file * file)1600c09f92d2SPeter Avalos file_register_empty(struct _7zip *zip, struct file *file)
1601c09f92d2SPeter Avalos {
1602c09f92d2SPeter Avalos file->next = NULL;
1603c09f92d2SPeter Avalos *zip->empty_list.last = file;
1604c09f92d2SPeter Avalos zip->empty_list.last = &(file->next);
1605c09f92d2SPeter Avalos }
1606c09f92d2SPeter Avalos
1607c09f92d2SPeter Avalos static void
file_init_register_empty(struct _7zip * zip)1608c09f92d2SPeter Avalos file_init_register_empty(struct _7zip *zip)
1609c09f92d2SPeter Avalos {
1610c09f92d2SPeter Avalos zip->empty_list.first = NULL;
1611c09f92d2SPeter Avalos zip->empty_list.last = &(zip->empty_list.first);
1612c09f92d2SPeter Avalos }
1613c09f92d2SPeter Avalos
161459bf7050SPeter Avalos #if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\
161559bf7050SPeter Avalos !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
1616c09f92d2SPeter Avalos static int
compression_unsupported_encoder(struct archive * a,struct la_zstream * lastrm,const char * name)1617c09f92d2SPeter Avalos compression_unsupported_encoder(struct archive *a,
1618c09f92d2SPeter Avalos struct la_zstream *lastrm, const char *name)
1619c09f92d2SPeter Avalos {
1620c09f92d2SPeter Avalos
1621c09f92d2SPeter Avalos archive_set_error(a, ARCHIVE_ERRNO_MISC,
1622c09f92d2SPeter Avalos "%s compression not supported on this platform", name);
1623c09f92d2SPeter Avalos lastrm->valid = 0;
1624c09f92d2SPeter Avalos lastrm->real_stream = NULL;
1625c09f92d2SPeter Avalos return (ARCHIVE_FAILED);
1626c09f92d2SPeter Avalos }
1627c09f92d2SPeter Avalos #endif
1628c09f92d2SPeter Avalos
1629c09f92d2SPeter Avalos /*
1630c09f92d2SPeter Avalos * _7_COPY compressor.
1631c09f92d2SPeter Avalos */
1632c09f92d2SPeter Avalos static int
compression_init_encoder_copy(struct archive * a,struct la_zstream * lastrm)1633c09f92d2SPeter Avalos compression_init_encoder_copy(struct archive *a, struct la_zstream *lastrm)
1634c09f92d2SPeter Avalos {
1635c09f92d2SPeter Avalos
1636c09f92d2SPeter Avalos if (lastrm->valid)
1637c09f92d2SPeter Avalos compression_end(a, lastrm);
1638c09f92d2SPeter Avalos lastrm->valid = 1;
1639c09f92d2SPeter Avalos lastrm->code = compression_code_copy;
1640c09f92d2SPeter Avalos lastrm->end = compression_end_copy;
1641c09f92d2SPeter Avalos return (ARCHIVE_OK);
1642c09f92d2SPeter Avalos }
1643c09f92d2SPeter Avalos
1644c09f92d2SPeter Avalos static int
compression_code_copy(struct archive * a,struct la_zstream * lastrm,enum la_zaction action)1645c09f92d2SPeter Avalos compression_code_copy(struct archive *a,
1646c09f92d2SPeter Avalos struct la_zstream *lastrm, enum la_zaction action)
1647c09f92d2SPeter Avalos {
1648c09f92d2SPeter Avalos size_t bytes;
1649c09f92d2SPeter Avalos
1650c09f92d2SPeter Avalos (void)a; /* UNUSED */
1651c09f92d2SPeter Avalos if (lastrm->avail_out > lastrm->avail_in)
1652c09f92d2SPeter Avalos bytes = lastrm->avail_in;
1653c09f92d2SPeter Avalos else
1654c09f92d2SPeter Avalos bytes = lastrm->avail_out;
1655c09f92d2SPeter Avalos if (bytes) {
1656c09f92d2SPeter Avalos memcpy(lastrm->next_out, lastrm->next_in, bytes);
1657c09f92d2SPeter Avalos lastrm->next_in += bytes;
1658c09f92d2SPeter Avalos lastrm->avail_in -= bytes;
1659c09f92d2SPeter Avalos lastrm->total_in += bytes;
1660c09f92d2SPeter Avalos lastrm->next_out += bytes;
1661c09f92d2SPeter Avalos lastrm->avail_out -= bytes;
1662c09f92d2SPeter Avalos lastrm->total_out += bytes;
1663c09f92d2SPeter Avalos }
1664c09f92d2SPeter Avalos if (action == ARCHIVE_Z_FINISH && lastrm->avail_in == 0)
1665c09f92d2SPeter Avalos return (ARCHIVE_EOF);
1666c09f92d2SPeter Avalos return (ARCHIVE_OK);
1667c09f92d2SPeter Avalos }
1668c09f92d2SPeter Avalos
1669c09f92d2SPeter Avalos static int
compression_end_copy(struct archive * a,struct la_zstream * lastrm)1670c09f92d2SPeter Avalos compression_end_copy(struct archive *a, struct la_zstream *lastrm)
1671c09f92d2SPeter Avalos {
1672c09f92d2SPeter Avalos (void)a; /* UNUSED */
1673c09f92d2SPeter Avalos lastrm->valid = 0;
1674c09f92d2SPeter Avalos return (ARCHIVE_OK);
1675c09f92d2SPeter Avalos }
1676c09f92d2SPeter Avalos
1677c09f92d2SPeter Avalos /*
1678c09f92d2SPeter Avalos * _7_DEFLATE compressor.
1679c09f92d2SPeter Avalos */
1680c09f92d2SPeter Avalos #ifdef HAVE_ZLIB_H
1681c09f92d2SPeter Avalos static int
compression_init_encoder_deflate(struct archive * a,struct la_zstream * lastrm,int level,int withheader)1682c09f92d2SPeter Avalos compression_init_encoder_deflate(struct archive *a,
1683c09f92d2SPeter Avalos struct la_zstream *lastrm, int level, int withheader)
1684c09f92d2SPeter Avalos {
1685c09f92d2SPeter Avalos z_stream *strm;
1686c09f92d2SPeter Avalos
1687c09f92d2SPeter Avalos if (lastrm->valid)
1688c09f92d2SPeter Avalos compression_end(a, lastrm);
1689c09f92d2SPeter Avalos strm = calloc(1, sizeof(*strm));
1690c09f92d2SPeter Avalos if (strm == NULL) {
1691c09f92d2SPeter Avalos archive_set_error(a, ENOMEM,
1692c09f92d2SPeter Avalos "Can't allocate memory for gzip stream");
1693c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
1694c09f92d2SPeter Avalos }
1695c09f92d2SPeter Avalos /* zlib.h is not const-correct, so we need this one bit
1696c09f92d2SPeter Avalos * of ugly hackery to convert a const * pointer to
1697c09f92d2SPeter Avalos * a non-const pointer. */
1698c09f92d2SPeter Avalos strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
1699d4d8193eSPeter Avalos strm->avail_in = (uInt)lastrm->avail_in;
170059bf7050SPeter Avalos strm->total_in = (uLong)lastrm->total_in;
1701c09f92d2SPeter Avalos strm->next_out = lastrm->next_out;
1702d4d8193eSPeter Avalos strm->avail_out = (uInt)lastrm->avail_out;
170359bf7050SPeter Avalos strm->total_out = (uLong)lastrm->total_out;
1704c09f92d2SPeter Avalos if (deflateInit2(strm, level, Z_DEFLATED,
1705c09f92d2SPeter Avalos (withheader)?15:-15,
1706c09f92d2SPeter Avalos 8, Z_DEFAULT_STRATEGY) != Z_OK) {
1707c09f92d2SPeter Avalos free(strm);
1708c09f92d2SPeter Avalos lastrm->real_stream = NULL;
1709c09f92d2SPeter Avalos archive_set_error(a, ARCHIVE_ERRNO_MISC,
1710c09f92d2SPeter Avalos "Internal error initializing compression library");
1711c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
1712c09f92d2SPeter Avalos }
1713c09f92d2SPeter Avalos lastrm->real_stream = strm;
1714c09f92d2SPeter Avalos lastrm->valid = 1;
1715c09f92d2SPeter Avalos lastrm->code = compression_code_deflate;
1716c09f92d2SPeter Avalos lastrm->end = compression_end_deflate;
1717c09f92d2SPeter Avalos return (ARCHIVE_OK);
1718c09f92d2SPeter Avalos }
1719c09f92d2SPeter Avalos
1720c09f92d2SPeter Avalos static int
compression_code_deflate(struct archive * a,struct la_zstream * lastrm,enum la_zaction action)1721c09f92d2SPeter Avalos compression_code_deflate(struct archive *a,
1722c09f92d2SPeter Avalos struct la_zstream *lastrm, enum la_zaction action)
1723c09f92d2SPeter Avalos {
1724c09f92d2SPeter Avalos z_stream *strm;
1725c09f92d2SPeter Avalos int r;
1726c09f92d2SPeter Avalos
1727c09f92d2SPeter Avalos strm = (z_stream *)lastrm->real_stream;
1728c09f92d2SPeter Avalos /* zlib.h is not const-correct, so we need this one bit
1729c09f92d2SPeter Avalos * of ugly hackery to convert a const * pointer to
1730c09f92d2SPeter Avalos * a non-const pointer. */
1731c09f92d2SPeter Avalos strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
1732d4d8193eSPeter Avalos strm->avail_in = (uInt)lastrm->avail_in;
173359bf7050SPeter Avalos strm->total_in = (uLong)lastrm->total_in;
1734c09f92d2SPeter Avalos strm->next_out = lastrm->next_out;
1735d4d8193eSPeter Avalos strm->avail_out = (uInt)lastrm->avail_out;
173659bf7050SPeter Avalos strm->total_out = (uLong)lastrm->total_out;
1737c09f92d2SPeter Avalos r = deflate(strm,
1738c09f92d2SPeter Avalos (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH);
1739c09f92d2SPeter Avalos lastrm->next_in = strm->next_in;
1740c09f92d2SPeter Avalos lastrm->avail_in = strm->avail_in;
1741c09f92d2SPeter Avalos lastrm->total_in = strm->total_in;
1742c09f92d2SPeter Avalos lastrm->next_out = strm->next_out;
1743c09f92d2SPeter Avalos lastrm->avail_out = strm->avail_out;
1744c09f92d2SPeter Avalos lastrm->total_out = strm->total_out;
1745c09f92d2SPeter Avalos switch (r) {
1746c09f92d2SPeter Avalos case Z_OK:
1747c09f92d2SPeter Avalos return (ARCHIVE_OK);
1748c09f92d2SPeter Avalos case Z_STREAM_END:
1749c09f92d2SPeter Avalos return (ARCHIVE_EOF);
1750c09f92d2SPeter Avalos default:
1751c09f92d2SPeter Avalos archive_set_error(a, ARCHIVE_ERRNO_MISC,
1752c09f92d2SPeter Avalos "GZip compression failed:"
1753c09f92d2SPeter Avalos " deflate() call returned status %d", r);
1754c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
1755c09f92d2SPeter Avalos }
1756c09f92d2SPeter Avalos }
1757c09f92d2SPeter Avalos
1758c09f92d2SPeter Avalos static int
compression_end_deflate(struct archive * a,struct la_zstream * lastrm)1759c09f92d2SPeter Avalos compression_end_deflate(struct archive *a, struct la_zstream *lastrm)
1760c09f92d2SPeter Avalos {
1761c09f92d2SPeter Avalos z_stream *strm;
1762c09f92d2SPeter Avalos int r;
1763c09f92d2SPeter Avalos
1764c09f92d2SPeter Avalos strm = (z_stream *)lastrm->real_stream;
1765c09f92d2SPeter Avalos r = deflateEnd(strm);
1766c09f92d2SPeter Avalos free(strm);
1767c09f92d2SPeter Avalos lastrm->real_stream = NULL;
1768c09f92d2SPeter Avalos lastrm->valid = 0;
1769c09f92d2SPeter Avalos if (r != Z_OK) {
1770c09f92d2SPeter Avalos archive_set_error(a, ARCHIVE_ERRNO_MISC,
1771c09f92d2SPeter Avalos "Failed to clean up compressor");
1772c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
1773c09f92d2SPeter Avalos }
1774c09f92d2SPeter Avalos return (ARCHIVE_OK);
1775c09f92d2SPeter Avalos }
1776c09f92d2SPeter Avalos #else
1777c09f92d2SPeter Avalos static int
compression_init_encoder_deflate(struct archive * a,struct la_zstream * lastrm,int level,int withheader)1778c09f92d2SPeter Avalos compression_init_encoder_deflate(struct archive *a,
1779c09f92d2SPeter Avalos struct la_zstream *lastrm, int level, int withheader)
1780c09f92d2SPeter Avalos {
1781c09f92d2SPeter Avalos
1782c09f92d2SPeter Avalos (void) level; /* UNUSED */
1783c09f92d2SPeter Avalos (void) withheader; /* UNUSED */
1784c09f92d2SPeter Avalos if (lastrm->valid)
1785c09f92d2SPeter Avalos compression_end(a, lastrm);
1786c09f92d2SPeter Avalos return (compression_unsupported_encoder(a, lastrm, "deflate"));
1787c09f92d2SPeter Avalos }
1788c09f92d2SPeter Avalos #endif
1789c09f92d2SPeter Avalos
1790c09f92d2SPeter Avalos /*
1791c09f92d2SPeter Avalos * _7_BZIP2 compressor.
1792c09f92d2SPeter Avalos */
1793c09f92d2SPeter Avalos #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
1794c09f92d2SPeter Avalos static int
compression_init_encoder_bzip2(struct archive * a,struct la_zstream * lastrm,int level)1795c09f92d2SPeter Avalos compression_init_encoder_bzip2(struct archive *a,
1796c09f92d2SPeter Avalos struct la_zstream *lastrm, int level)
1797c09f92d2SPeter Avalos {
1798c09f92d2SPeter Avalos bz_stream *strm;
1799c09f92d2SPeter Avalos
1800c09f92d2SPeter Avalos if (lastrm->valid)
1801c09f92d2SPeter Avalos compression_end(a, lastrm);
1802c09f92d2SPeter Avalos strm = calloc(1, sizeof(*strm));
1803c09f92d2SPeter Avalos if (strm == NULL) {
1804c09f92d2SPeter Avalos archive_set_error(a, ENOMEM,
1805c09f92d2SPeter Avalos "Can't allocate memory for bzip2 stream");
1806c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
1807c09f92d2SPeter Avalos }
1808c09f92d2SPeter Avalos /* bzlib.h is not const-correct, so we need this one bit
1809c09f92d2SPeter Avalos * of ugly hackery to convert a const * pointer to
1810c09f92d2SPeter Avalos * a non-const pointer. */
1811c09f92d2SPeter Avalos strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
1812c09f92d2SPeter Avalos strm->avail_in = lastrm->avail_in;
1813c09f92d2SPeter Avalos strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
1814c09f92d2SPeter Avalos strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
1815c09f92d2SPeter Avalos strm->next_out = (char *)lastrm->next_out;
1816c09f92d2SPeter Avalos strm->avail_out = lastrm->avail_out;
1817c09f92d2SPeter Avalos strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
1818c09f92d2SPeter Avalos strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
1819c09f92d2SPeter Avalos if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) {
1820c09f92d2SPeter Avalos free(strm);
1821c09f92d2SPeter Avalos lastrm->real_stream = NULL;
1822c09f92d2SPeter Avalos archive_set_error(a, ARCHIVE_ERRNO_MISC,
1823c09f92d2SPeter Avalos "Internal error initializing compression library");
1824c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
1825c09f92d2SPeter Avalos }
1826c09f92d2SPeter Avalos lastrm->real_stream = strm;
1827c09f92d2SPeter Avalos lastrm->valid = 1;
1828c09f92d2SPeter Avalos lastrm->code = compression_code_bzip2;
1829c09f92d2SPeter Avalos lastrm->end = compression_end_bzip2;
1830c09f92d2SPeter Avalos return (ARCHIVE_OK);
1831c09f92d2SPeter Avalos }
1832c09f92d2SPeter Avalos
1833c09f92d2SPeter Avalos static int
compression_code_bzip2(struct archive * a,struct la_zstream * lastrm,enum la_zaction action)1834c09f92d2SPeter Avalos compression_code_bzip2(struct archive *a,
1835c09f92d2SPeter Avalos struct la_zstream *lastrm, enum la_zaction action)
1836c09f92d2SPeter Avalos {
1837c09f92d2SPeter Avalos bz_stream *strm;
1838c09f92d2SPeter Avalos int r;
1839c09f92d2SPeter Avalos
1840c09f92d2SPeter Avalos strm = (bz_stream *)lastrm->real_stream;
1841c09f92d2SPeter Avalos /* bzlib.h is not const-correct, so we need this one bit
1842c09f92d2SPeter Avalos * of ugly hackery to convert a const * pointer to
1843c09f92d2SPeter Avalos * a non-const pointer. */
1844c09f92d2SPeter Avalos strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
1845c09f92d2SPeter Avalos strm->avail_in = lastrm->avail_in;
1846c09f92d2SPeter Avalos strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
1847c09f92d2SPeter Avalos strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
1848c09f92d2SPeter Avalos strm->next_out = (char *)lastrm->next_out;
1849c09f92d2SPeter Avalos strm->avail_out = lastrm->avail_out;
1850c09f92d2SPeter Avalos strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
1851c09f92d2SPeter Avalos strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
1852c09f92d2SPeter Avalos r = BZ2_bzCompress(strm,
1853c09f92d2SPeter Avalos (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN);
1854c09f92d2SPeter Avalos lastrm->next_in = (const unsigned char *)strm->next_in;
1855c09f92d2SPeter Avalos lastrm->avail_in = strm->avail_in;
1856c09f92d2SPeter Avalos lastrm->total_in =
1857c09f92d2SPeter Avalos (((uint64_t)(uint32_t)strm->total_in_hi32) << 32)
1858c09f92d2SPeter Avalos + (uint64_t)(uint32_t)strm->total_in_lo32;
1859c09f92d2SPeter Avalos lastrm->next_out = (unsigned char *)strm->next_out;
1860c09f92d2SPeter Avalos lastrm->avail_out = strm->avail_out;
1861c09f92d2SPeter Avalos lastrm->total_out =
1862c09f92d2SPeter Avalos (((uint64_t)(uint32_t)strm->total_out_hi32) << 32)
1863c09f92d2SPeter Avalos + (uint64_t)(uint32_t)strm->total_out_lo32;
1864c09f92d2SPeter Avalos switch (r) {
1865c09f92d2SPeter Avalos case BZ_RUN_OK: /* Non-finishing */
1866c09f92d2SPeter Avalos case BZ_FINISH_OK: /* Finishing: There's more work to do */
1867c09f92d2SPeter Avalos return (ARCHIVE_OK);
1868c09f92d2SPeter Avalos case BZ_STREAM_END: /* Finishing: all done */
1869c09f92d2SPeter Avalos /* Only occurs in finishing case */
1870c09f92d2SPeter Avalos return (ARCHIVE_EOF);
1871c09f92d2SPeter Avalos default:
1872c09f92d2SPeter Avalos /* Any other return value indicates an error */
1873c09f92d2SPeter Avalos archive_set_error(a, ARCHIVE_ERRNO_MISC,
1874c09f92d2SPeter Avalos "Bzip2 compression failed:"
1875c09f92d2SPeter Avalos " BZ2_bzCompress() call returned status %d", r);
1876c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
1877c09f92d2SPeter Avalos }
1878c09f92d2SPeter Avalos }
1879c09f92d2SPeter Avalos
1880c09f92d2SPeter Avalos static int
compression_end_bzip2(struct archive * a,struct la_zstream * lastrm)1881c09f92d2SPeter Avalos compression_end_bzip2(struct archive *a, struct la_zstream *lastrm)
1882c09f92d2SPeter Avalos {
1883c09f92d2SPeter Avalos bz_stream *strm;
1884c09f92d2SPeter Avalos int r;
1885c09f92d2SPeter Avalos
1886c09f92d2SPeter Avalos strm = (bz_stream *)lastrm->real_stream;
1887c09f92d2SPeter Avalos r = BZ2_bzCompressEnd(strm);
1888c09f92d2SPeter Avalos free(strm);
1889c09f92d2SPeter Avalos lastrm->real_stream = NULL;
1890c09f92d2SPeter Avalos lastrm->valid = 0;
1891c09f92d2SPeter Avalos if (r != BZ_OK) {
1892c09f92d2SPeter Avalos archive_set_error(a, ARCHIVE_ERRNO_MISC,
1893c09f92d2SPeter Avalos "Failed to clean up compressor");
1894c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
1895c09f92d2SPeter Avalos }
1896c09f92d2SPeter Avalos return (ARCHIVE_OK);
1897c09f92d2SPeter Avalos }
1898c09f92d2SPeter Avalos
1899c09f92d2SPeter Avalos #else
1900c09f92d2SPeter Avalos static int
compression_init_encoder_bzip2(struct archive * a,struct la_zstream * lastrm,int level)1901c09f92d2SPeter Avalos compression_init_encoder_bzip2(struct archive *a,
1902c09f92d2SPeter Avalos struct la_zstream *lastrm, int level)
1903c09f92d2SPeter Avalos {
1904c09f92d2SPeter Avalos
1905c09f92d2SPeter Avalos (void) level; /* UNUSED */
1906c09f92d2SPeter Avalos if (lastrm->valid)
1907c09f92d2SPeter Avalos compression_end(a, lastrm);
1908c09f92d2SPeter Avalos return (compression_unsupported_encoder(a, lastrm, "bzip2"));
1909c09f92d2SPeter Avalos }
1910c09f92d2SPeter Avalos #endif
1911c09f92d2SPeter Avalos
1912c09f92d2SPeter Avalos /*
1913c09f92d2SPeter Avalos * _7_LZMA1, _7_LZMA2 compressor.
1914c09f92d2SPeter Avalos */
1915c09f92d2SPeter Avalos #if defined(HAVE_LZMA_H)
1916c09f92d2SPeter Avalos static int
compression_init_encoder_lzma(struct archive * a,struct la_zstream * lastrm,int level,uint64_t filter_id)1917c09f92d2SPeter Avalos compression_init_encoder_lzma(struct archive *a,
1918c09f92d2SPeter Avalos struct la_zstream *lastrm, int level, uint64_t filter_id)
1919c09f92d2SPeter Avalos {
1920c09f92d2SPeter Avalos static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
1921c09f92d2SPeter Avalos lzma_stream *strm;
1922c09f92d2SPeter Avalos lzma_filter *lzmafilters;
1923c09f92d2SPeter Avalos lzma_options_lzma lzma_opt;
1924c09f92d2SPeter Avalos int r;
1925c09f92d2SPeter Avalos
1926c09f92d2SPeter Avalos if (lastrm->valid)
1927c09f92d2SPeter Avalos compression_end(a, lastrm);
1928c09f92d2SPeter Avalos strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2);
1929c09f92d2SPeter Avalos if (strm == NULL) {
1930c09f92d2SPeter Avalos archive_set_error(a, ENOMEM,
1931c09f92d2SPeter Avalos "Can't allocate memory for lzma stream");
1932c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
1933c09f92d2SPeter Avalos }
1934c09f92d2SPeter Avalos lzmafilters = (lzma_filter *)(strm+1);
1935*50f8aa9cSAntonio Huete Jimenez if (level > 9)
1936*50f8aa9cSAntonio Huete Jimenez level = 9;
1937c09f92d2SPeter Avalos if (lzma_lzma_preset(&lzma_opt, level)) {
193859bf7050SPeter Avalos free(strm);
1939c09f92d2SPeter Avalos lastrm->real_stream = NULL;
1940c09f92d2SPeter Avalos archive_set_error(a, ENOMEM,
1941c09f92d2SPeter Avalos "Internal error initializing compression library");
1942c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
1943c09f92d2SPeter Avalos }
1944c09f92d2SPeter Avalos lzmafilters[0].id = filter_id;
1945c09f92d2SPeter Avalos lzmafilters[0].options = &lzma_opt;
1946c09f92d2SPeter Avalos lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
1947c09f92d2SPeter Avalos
1948c09f92d2SPeter Avalos r = lzma_properties_size(&(lastrm->prop_size), lzmafilters);
1949c09f92d2SPeter Avalos if (r != LZMA_OK) {
1950c09f92d2SPeter Avalos free(strm);
1951c09f92d2SPeter Avalos lastrm->real_stream = NULL;
1952c09f92d2SPeter Avalos archive_set_error(a, ARCHIVE_ERRNO_MISC,
1953c09f92d2SPeter Avalos "lzma_properties_size failed");
1954c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
1955c09f92d2SPeter Avalos }
1956c09f92d2SPeter Avalos if (lastrm->prop_size) {
1957c09f92d2SPeter Avalos lastrm->props = malloc(lastrm->prop_size);
1958c09f92d2SPeter Avalos if (lastrm->props == NULL) {
1959c09f92d2SPeter Avalos free(strm);
1960c09f92d2SPeter Avalos lastrm->real_stream = NULL;
1961c09f92d2SPeter Avalos archive_set_error(a, ENOMEM,
1962c09f92d2SPeter Avalos "Cannot allocate memory");
1963c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
1964c09f92d2SPeter Avalos }
1965c09f92d2SPeter Avalos r = lzma_properties_encode(lzmafilters, lastrm->props);
1966c09f92d2SPeter Avalos if (r != LZMA_OK) {
1967c09f92d2SPeter Avalos free(strm);
1968c09f92d2SPeter Avalos lastrm->real_stream = NULL;
1969c09f92d2SPeter Avalos archive_set_error(a, ARCHIVE_ERRNO_MISC,
1970c09f92d2SPeter Avalos "lzma_properties_encode failed");
1971c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
1972c09f92d2SPeter Avalos }
1973c09f92d2SPeter Avalos }
1974c09f92d2SPeter Avalos
1975c09f92d2SPeter Avalos *strm = lzma_init_data;
1976c09f92d2SPeter Avalos r = lzma_raw_encoder(strm, lzmafilters);
1977c09f92d2SPeter Avalos switch (r) {
1978c09f92d2SPeter Avalos case LZMA_OK:
1979c09f92d2SPeter Avalos lastrm->real_stream = strm;
1980c09f92d2SPeter Avalos lastrm->valid = 1;
1981c09f92d2SPeter Avalos lastrm->code = compression_code_lzma;
1982c09f92d2SPeter Avalos lastrm->end = compression_end_lzma;
1983c09f92d2SPeter Avalos r = ARCHIVE_OK;
1984c09f92d2SPeter Avalos break;
1985c09f92d2SPeter Avalos case LZMA_MEM_ERROR:
1986c09f92d2SPeter Avalos free(strm);
1987c09f92d2SPeter Avalos lastrm->real_stream = NULL;
1988c09f92d2SPeter Avalos archive_set_error(a, ENOMEM,
1989c09f92d2SPeter Avalos "Internal error initializing compression library: "
1990c09f92d2SPeter Avalos "Cannot allocate memory");
1991c09f92d2SPeter Avalos r = ARCHIVE_FATAL;
1992c09f92d2SPeter Avalos break;
1993c09f92d2SPeter Avalos default:
1994c09f92d2SPeter Avalos free(strm);
1995c09f92d2SPeter Avalos lastrm->real_stream = NULL;
1996c09f92d2SPeter Avalos archive_set_error(a, ARCHIVE_ERRNO_MISC,
1997c09f92d2SPeter Avalos "Internal error initializing compression library: "
1998c09f92d2SPeter Avalos "It's a bug in liblzma");
1999c09f92d2SPeter Avalos r = ARCHIVE_FATAL;
2000c09f92d2SPeter Avalos break;
2001c09f92d2SPeter Avalos }
2002c09f92d2SPeter Avalos return (r);
2003c09f92d2SPeter Avalos }
2004c09f92d2SPeter Avalos
2005c09f92d2SPeter Avalos static int
compression_init_encoder_lzma1(struct archive * a,struct la_zstream * lastrm,int level)2006c09f92d2SPeter Avalos compression_init_encoder_lzma1(struct archive *a,
2007c09f92d2SPeter Avalos struct la_zstream *lastrm, int level)
2008c09f92d2SPeter Avalos {
2009c09f92d2SPeter Avalos return compression_init_encoder_lzma(a, lastrm, level,
2010c09f92d2SPeter Avalos LZMA_FILTER_LZMA1);
2011c09f92d2SPeter Avalos }
2012c09f92d2SPeter Avalos
2013c09f92d2SPeter Avalos static int
compression_init_encoder_lzma2(struct archive * a,struct la_zstream * lastrm,int level)2014c09f92d2SPeter Avalos compression_init_encoder_lzma2(struct archive *a,
2015c09f92d2SPeter Avalos struct la_zstream *lastrm, int level)
2016c09f92d2SPeter Avalos {
2017c09f92d2SPeter Avalos return compression_init_encoder_lzma(a, lastrm, level,
2018c09f92d2SPeter Avalos LZMA_FILTER_LZMA2);
2019c09f92d2SPeter Avalos }
2020c09f92d2SPeter Avalos
2021c09f92d2SPeter Avalos static int
compression_code_lzma(struct archive * a,struct la_zstream * lastrm,enum la_zaction action)2022c09f92d2SPeter Avalos compression_code_lzma(struct archive *a,
2023c09f92d2SPeter Avalos struct la_zstream *lastrm, enum la_zaction action)
2024c09f92d2SPeter Avalos {
2025c09f92d2SPeter Avalos lzma_stream *strm;
2026c09f92d2SPeter Avalos int r;
2027c09f92d2SPeter Avalos
2028c09f92d2SPeter Avalos strm = (lzma_stream *)lastrm->real_stream;
2029c09f92d2SPeter Avalos strm->next_in = lastrm->next_in;
2030c09f92d2SPeter Avalos strm->avail_in = lastrm->avail_in;
2031c09f92d2SPeter Avalos strm->total_in = lastrm->total_in;
2032c09f92d2SPeter Avalos strm->next_out = lastrm->next_out;
2033c09f92d2SPeter Avalos strm->avail_out = lastrm->avail_out;
2034c09f92d2SPeter Avalos strm->total_out = lastrm->total_out;
2035c09f92d2SPeter Avalos r = lzma_code(strm,
2036c09f92d2SPeter Avalos (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN);
2037c09f92d2SPeter Avalos lastrm->next_in = strm->next_in;
2038c09f92d2SPeter Avalos lastrm->avail_in = strm->avail_in;
2039c09f92d2SPeter Avalos lastrm->total_in = strm->total_in;
2040c09f92d2SPeter Avalos lastrm->next_out = strm->next_out;
2041c09f92d2SPeter Avalos lastrm->avail_out = strm->avail_out;
2042c09f92d2SPeter Avalos lastrm->total_out = strm->total_out;
2043c09f92d2SPeter Avalos switch (r) {
2044c09f92d2SPeter Avalos case LZMA_OK:
2045c09f92d2SPeter Avalos /* Non-finishing case */
2046c09f92d2SPeter Avalos return (ARCHIVE_OK);
2047c09f92d2SPeter Avalos case LZMA_STREAM_END:
2048c09f92d2SPeter Avalos /* This return can only occur in finishing case. */
2049c09f92d2SPeter Avalos return (ARCHIVE_EOF);
2050c09f92d2SPeter Avalos case LZMA_MEMLIMIT_ERROR:
2051c09f92d2SPeter Avalos archive_set_error(a, ENOMEM,
2052c09f92d2SPeter Avalos "lzma compression error:"
2053c09f92d2SPeter Avalos " %ju MiB would have been needed",
2054c09f92d2SPeter Avalos (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1)
2055c09f92d2SPeter Avalos / (1024 * 1024)));
2056c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
2057c09f92d2SPeter Avalos default:
2058c09f92d2SPeter Avalos /* Any other return value indicates an error */
2059c09f92d2SPeter Avalos archive_set_error(a, ARCHIVE_ERRNO_MISC,
2060c09f92d2SPeter Avalos "lzma compression failed:"
2061c09f92d2SPeter Avalos " lzma_code() call returned status %d", r);
2062c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
2063c09f92d2SPeter Avalos }
2064c09f92d2SPeter Avalos }
2065c09f92d2SPeter Avalos
2066c09f92d2SPeter Avalos static int
compression_end_lzma(struct archive * a,struct la_zstream * lastrm)2067c09f92d2SPeter Avalos compression_end_lzma(struct archive *a, struct la_zstream *lastrm)
2068c09f92d2SPeter Avalos {
2069c09f92d2SPeter Avalos lzma_stream *strm;
2070c09f92d2SPeter Avalos
2071c09f92d2SPeter Avalos (void)a; /* UNUSED */
2072c09f92d2SPeter Avalos strm = (lzma_stream *)lastrm->real_stream;
2073c09f92d2SPeter Avalos lzma_end(strm);
2074c09f92d2SPeter Avalos free(strm);
2075c09f92d2SPeter Avalos lastrm->valid = 0;
2076c09f92d2SPeter Avalos lastrm->real_stream = NULL;
2077c09f92d2SPeter Avalos return (ARCHIVE_OK);
2078c09f92d2SPeter Avalos }
2079c09f92d2SPeter Avalos #else
2080c09f92d2SPeter Avalos static int
compression_init_encoder_lzma1(struct archive * a,struct la_zstream * lastrm,int level)2081c09f92d2SPeter Avalos compression_init_encoder_lzma1(struct archive *a,
2082c09f92d2SPeter Avalos struct la_zstream *lastrm, int level)
2083c09f92d2SPeter Avalos {
2084c09f92d2SPeter Avalos
2085c09f92d2SPeter Avalos (void) level; /* UNUSED */
2086c09f92d2SPeter Avalos if (lastrm->valid)
2087c09f92d2SPeter Avalos compression_end(a, lastrm);
2088c09f92d2SPeter Avalos return (compression_unsupported_encoder(a, lastrm, "lzma"));
2089c09f92d2SPeter Avalos }
2090c09f92d2SPeter Avalos static int
compression_init_encoder_lzma2(struct archive * a,struct la_zstream * lastrm,int level)2091c09f92d2SPeter Avalos compression_init_encoder_lzma2(struct archive *a,
2092c09f92d2SPeter Avalos struct la_zstream *lastrm, int level)
2093c09f92d2SPeter Avalos {
2094c09f92d2SPeter Avalos
2095c09f92d2SPeter Avalos (void) level; /* UNUSED */
2096c09f92d2SPeter Avalos if (lastrm->valid)
2097c09f92d2SPeter Avalos compression_end(a, lastrm);
2098c09f92d2SPeter Avalos return (compression_unsupported_encoder(a, lastrm, "lzma"));
2099c09f92d2SPeter Avalos }
2100c09f92d2SPeter Avalos #endif
2101c09f92d2SPeter Avalos
2102c09f92d2SPeter Avalos /*
2103c09f92d2SPeter Avalos * _7_PPMD compressor.
2104c09f92d2SPeter Avalos */
2105c09f92d2SPeter Avalos static void
ppmd_write(void * p,Byte b)2106c09f92d2SPeter Avalos ppmd_write(void *p, Byte b)
2107c09f92d2SPeter Avalos {
2108c09f92d2SPeter Avalos struct archive_write *a = ((IByteOut *)p)->a;
2109c09f92d2SPeter Avalos struct _7zip *zip = (struct _7zip *)(a->format_data);
2110c09f92d2SPeter Avalos struct la_zstream *lastrm = &(zip->stream);
2111c09f92d2SPeter Avalos struct ppmd_stream *strm;
2112c09f92d2SPeter Avalos
2113c09f92d2SPeter Avalos if (lastrm->avail_out) {
2114c09f92d2SPeter Avalos *lastrm->next_out++ = b;
2115c09f92d2SPeter Avalos lastrm->avail_out--;
2116c09f92d2SPeter Avalos lastrm->total_out++;
2117c09f92d2SPeter Avalos return;
2118c09f92d2SPeter Avalos }
2119c09f92d2SPeter Avalos strm = (struct ppmd_stream *)lastrm->real_stream;
2120c09f92d2SPeter Avalos if (strm->buff_ptr < strm->buff_end) {
2121c09f92d2SPeter Avalos *strm->buff_ptr++ = b;
2122c09f92d2SPeter Avalos strm->buff_bytes++;
2123c09f92d2SPeter Avalos }
2124c09f92d2SPeter Avalos }
2125c09f92d2SPeter Avalos
2126c09f92d2SPeter Avalos static int
compression_init_encoder_ppmd(struct archive * a,struct la_zstream * lastrm,unsigned maxOrder,uint32_t msize)2127c09f92d2SPeter Avalos compression_init_encoder_ppmd(struct archive *a,
2128c09f92d2SPeter Avalos struct la_zstream *lastrm, unsigned maxOrder, uint32_t msize)
2129c09f92d2SPeter Avalos {
2130c09f92d2SPeter Avalos struct ppmd_stream *strm;
2131c09f92d2SPeter Avalos uint8_t *props;
2132c09f92d2SPeter Avalos int r;
2133c09f92d2SPeter Avalos
2134c09f92d2SPeter Avalos if (lastrm->valid)
2135c09f92d2SPeter Avalos compression_end(a, lastrm);
2136c09f92d2SPeter Avalos strm = calloc(1, sizeof(*strm));
2137c09f92d2SPeter Avalos if (strm == NULL) {
2138c09f92d2SPeter Avalos archive_set_error(a, ENOMEM,
2139c09f92d2SPeter Avalos "Can't allocate memory for PPMd");
2140c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
2141c09f92d2SPeter Avalos }
2142c09f92d2SPeter Avalos strm->buff = malloc(32);
2143c09f92d2SPeter Avalos if (strm->buff == NULL) {
2144c09f92d2SPeter Avalos free(strm);
2145c09f92d2SPeter Avalos archive_set_error(a, ENOMEM,
2146c09f92d2SPeter Avalos "Can't allocate memory for PPMd");
2147c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
2148c09f92d2SPeter Avalos }
2149c09f92d2SPeter Avalos strm->buff_ptr = strm->buff;
2150c09f92d2SPeter Avalos strm->buff_end = strm->buff + 32;
2151c09f92d2SPeter Avalos
2152c09f92d2SPeter Avalos props = malloc(1+4);
2153c09f92d2SPeter Avalos if (props == NULL) {
2154c09f92d2SPeter Avalos free(strm->buff);
2155c09f92d2SPeter Avalos free(strm);
2156c09f92d2SPeter Avalos archive_set_error(a, ENOMEM,
2157c09f92d2SPeter Avalos "Coludn't allocate memory for PPMd");
2158c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
2159c09f92d2SPeter Avalos }
2160c09f92d2SPeter Avalos props[0] = maxOrder;
2161c09f92d2SPeter Avalos archive_le32enc(props+1, msize);
2162c09f92d2SPeter Avalos __archive_ppmd7_functions.Ppmd7_Construct(&strm->ppmd7_context);
2163c09f92d2SPeter Avalos r = __archive_ppmd7_functions.Ppmd7_Alloc(
2164e95abc47Szrj &strm->ppmd7_context, msize);
2165c09f92d2SPeter Avalos if (r == 0) {
2166c09f92d2SPeter Avalos free(strm->buff);
2167c09f92d2SPeter Avalos free(strm);
2168c09f92d2SPeter Avalos free(props);
2169c09f92d2SPeter Avalos archive_set_error(a, ENOMEM,
2170c09f92d2SPeter Avalos "Coludn't allocate memory for PPMd");
2171c09f92d2SPeter Avalos return (ARCHIVE_FATAL);
2172c09f92d2SPeter Avalos }
2173c09f92d2SPeter Avalos __archive_ppmd7_functions.Ppmd7_Init(&(strm->ppmd7_context), maxOrder);
2174c09f92d2SPeter Avalos strm->byteout.a = (struct archive_write *)a;
2175c09f92d2SPeter Avalos strm->byteout.Write = ppmd_write;
2176c09f92d2SPeter Avalos strm->range_enc.Stream = &(strm->byteout);
2177c09f92d2SPeter Avalos __archive_ppmd7_functions.Ppmd7z_RangeEnc_Init(&(strm->range_enc));
2178c09f92d2SPeter Avalos strm->stat = 0;
2179c09f92d2SPeter Avalos
2180c09f92d2SPeter Avalos lastrm->real_stream = strm;
2181c09f92d2SPeter Avalos lastrm->valid = 1;
2182c09f92d2SPeter Avalos lastrm->code = compression_code_ppmd;
2183c09f92d2SPeter Avalos lastrm->end = compression_end_ppmd;
2184c09f92d2SPeter Avalos lastrm->prop_size = 5;
2185c09f92d2SPeter Avalos lastrm->props = props;
2186c09f92d2SPeter Avalos return (ARCHIVE_OK);
2187c09f92d2SPeter Avalos }
2188c09f92d2SPeter Avalos
2189c09f92d2SPeter Avalos static int
compression_code_ppmd(struct archive * a,struct la_zstream * lastrm,enum la_zaction action)2190c09f92d2SPeter Avalos compression_code_ppmd(struct archive *a,
2191c09f92d2SPeter Avalos struct la_zstream *lastrm, enum la_zaction action)
2192c09f92d2SPeter Avalos {
2193c09f92d2SPeter Avalos struct ppmd_stream *strm;
2194c09f92d2SPeter Avalos
219559bf7050SPeter Avalos (void)a; /* UNUSED */
219659bf7050SPeter Avalos
2197c09f92d2SPeter Avalos strm = (struct ppmd_stream *)lastrm->real_stream;
2198c09f92d2SPeter Avalos
2199c09f92d2SPeter Avalos /* Copy encoded data if there are remaining bytes from previous call. */
2200c09f92d2SPeter Avalos if (strm->buff_bytes) {
2201c09f92d2SPeter Avalos uint8_t *p = strm->buff_ptr - strm->buff_bytes;
2202c09f92d2SPeter Avalos while (lastrm->avail_out && strm->buff_bytes) {
2203c09f92d2SPeter Avalos *lastrm->next_out++ = *p++;
2204c09f92d2SPeter Avalos lastrm->avail_out--;
2205c09f92d2SPeter Avalos lastrm->total_out++;
2206c09f92d2SPeter Avalos strm->buff_bytes--;
2207c09f92d2SPeter Avalos }
2208c09f92d2SPeter Avalos if (strm->buff_bytes)
2209c09f92d2SPeter Avalos return (ARCHIVE_OK);
2210c09f92d2SPeter Avalos if (strm->stat == 1)
2211c09f92d2SPeter Avalos return (ARCHIVE_EOF);
2212c09f92d2SPeter Avalos strm->buff_ptr = strm->buff;
2213c09f92d2SPeter Avalos }
2214c09f92d2SPeter Avalos while (lastrm->avail_in && lastrm->avail_out) {
2215c09f92d2SPeter Avalos __archive_ppmd7_functions.Ppmd7_EncodeSymbol(
2216c09f92d2SPeter Avalos &(strm->ppmd7_context), &(strm->range_enc),
2217c09f92d2SPeter Avalos *lastrm->next_in++);
2218c09f92d2SPeter Avalos lastrm->avail_in--;
2219c09f92d2SPeter Avalos lastrm->total_in++;
2220c09f92d2SPeter Avalos }
2221c09f92d2SPeter Avalos if (lastrm->avail_in == 0 && action == ARCHIVE_Z_FINISH) {
2222c09f92d2SPeter Avalos __archive_ppmd7_functions.Ppmd7z_RangeEnc_FlushData(
2223c09f92d2SPeter Avalos &(strm->range_enc));
2224c09f92d2SPeter Avalos strm->stat = 1;
2225c09f92d2SPeter Avalos /* Return EOF if there are no remaining bytes. */
2226c09f92d2SPeter Avalos if (strm->buff_bytes == 0)
2227c09f92d2SPeter Avalos return (ARCHIVE_EOF);
2228c09f92d2SPeter Avalos }
2229c09f92d2SPeter Avalos return (ARCHIVE_OK);
2230c09f92d2SPeter Avalos }
2231c09f92d2SPeter Avalos
2232c09f92d2SPeter Avalos static int
compression_end_ppmd(struct archive * a,struct la_zstream * lastrm)2233c09f92d2SPeter Avalos compression_end_ppmd(struct archive *a, struct la_zstream *lastrm)
2234c09f92d2SPeter Avalos {
2235c09f92d2SPeter Avalos struct ppmd_stream *strm;
2236c09f92d2SPeter Avalos
223759bf7050SPeter Avalos (void)a; /* UNUSED */
223859bf7050SPeter Avalos
2239c09f92d2SPeter Avalos strm = (struct ppmd_stream *)lastrm->real_stream;
2240e95abc47Szrj __archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context);
2241c09f92d2SPeter Avalos free(strm->buff);
2242c09f92d2SPeter Avalos free(strm);
2243c09f92d2SPeter Avalos lastrm->real_stream = NULL;
2244c09f92d2SPeter Avalos lastrm->valid = 0;
2245c09f92d2SPeter Avalos return (ARCHIVE_OK);
2246c09f92d2SPeter Avalos }
2247c09f92d2SPeter Avalos
2248c09f92d2SPeter Avalos /*
2249c09f92d2SPeter Avalos * Universal compressor initializer.
2250c09f92d2SPeter Avalos */
2251c09f92d2SPeter Avalos static int
_7z_compression_init_encoder(struct archive_write * a,unsigned compression,int compression_level)2252c09f92d2SPeter Avalos _7z_compression_init_encoder(struct archive_write *a, unsigned compression,
2253c09f92d2SPeter Avalos int compression_level)
2254c09f92d2SPeter Avalos {
2255c09f92d2SPeter Avalos struct _7zip *zip;
2256c09f92d2SPeter Avalos int r;
2257c09f92d2SPeter Avalos
2258c09f92d2SPeter Avalos zip = (struct _7zip *)a->format_data;
2259c09f92d2SPeter Avalos switch (compression) {
2260c09f92d2SPeter Avalos case _7Z_DEFLATE:
2261c09f92d2SPeter Avalos r = compression_init_encoder_deflate(
2262c09f92d2SPeter Avalos &(a->archive), &(zip->stream),
2263c09f92d2SPeter Avalos compression_level, 0);
2264c09f92d2SPeter Avalos break;
2265c09f92d2SPeter Avalos case _7Z_BZIP2:
2266c09f92d2SPeter Avalos r = compression_init_encoder_bzip2(
2267c09f92d2SPeter Avalos &(a->archive), &(zip->stream),
2268c09f92d2SPeter Avalos compression_level);
2269c09f92d2SPeter Avalos break;
2270c09f92d2SPeter Avalos case _7Z_LZMA1:
2271c09f92d2SPeter Avalos r = compression_init_encoder_lzma1(
2272c09f92d2SPeter Avalos &(a->archive), &(zip->stream),
2273c09f92d2SPeter Avalos compression_level);
2274c09f92d2SPeter Avalos break;
2275c09f92d2SPeter Avalos case _7Z_LZMA2:
2276c09f92d2SPeter Avalos r = compression_init_encoder_lzma2(
2277c09f92d2SPeter Avalos &(a->archive), &(zip->stream),
2278c09f92d2SPeter Avalos compression_level);
2279c09f92d2SPeter Avalos break;
2280c09f92d2SPeter Avalos case _7Z_PPMD:
2281c09f92d2SPeter Avalos r = compression_init_encoder_ppmd(
2282c09f92d2SPeter Avalos &(a->archive), &(zip->stream),
2283c09f92d2SPeter Avalos PPMD7_DEFAULT_ORDER, PPMD7_DEFAULT_MEM_SIZE);
2284c09f92d2SPeter Avalos break;
2285c09f92d2SPeter Avalos case _7Z_COPY:
2286c09f92d2SPeter Avalos default:
2287c09f92d2SPeter Avalos r = compression_init_encoder_copy(
2288c09f92d2SPeter Avalos &(a->archive), &(zip->stream));
2289c09f92d2SPeter Avalos break;
2290c09f92d2SPeter Avalos }
2291c09f92d2SPeter Avalos if (r == ARCHIVE_OK) {
2292c09f92d2SPeter Avalos zip->stream.total_in = 0;
2293c09f92d2SPeter Avalos zip->stream.next_out = zip->wbuff;
2294c09f92d2SPeter Avalos zip->stream.avail_out = sizeof(zip->wbuff);
2295c09f92d2SPeter Avalos zip->stream.total_out = 0;
2296c09f92d2SPeter Avalos }
2297c09f92d2SPeter Avalos
2298c09f92d2SPeter Avalos return (r);
2299c09f92d2SPeter Avalos }
2300c09f92d2SPeter Avalos
2301c09f92d2SPeter Avalos static int
compression_code(struct archive * a,struct la_zstream * lastrm,enum la_zaction action)2302c09f92d2SPeter Avalos compression_code(struct archive *a, struct la_zstream *lastrm,
2303c09f92d2SPeter Avalos enum la_zaction action)
2304c09f92d2SPeter Avalos {
2305c09f92d2SPeter Avalos if (lastrm->valid)
2306c09f92d2SPeter Avalos return (lastrm->code(a, lastrm, action));
2307c09f92d2SPeter Avalos return (ARCHIVE_OK);
2308c09f92d2SPeter Avalos }
2309c09f92d2SPeter Avalos
2310c09f92d2SPeter Avalos static int
compression_end(struct archive * a,struct la_zstream * lastrm)2311c09f92d2SPeter Avalos compression_end(struct archive *a, struct la_zstream *lastrm)
2312c09f92d2SPeter Avalos {
2313c09f92d2SPeter Avalos if (lastrm->valid) {
2314c09f92d2SPeter Avalos lastrm->prop_size = 0;
2315c09f92d2SPeter Avalos free(lastrm->props);
2316c09f92d2SPeter Avalos lastrm->props = NULL;
2317c09f92d2SPeter Avalos return (lastrm->end(a, lastrm));
2318c09f92d2SPeter Avalos }
2319c09f92d2SPeter Avalos return (ARCHIVE_OK);
2320c09f92d2SPeter Avalos }
2321c09f92d2SPeter Avalos
2322c09f92d2SPeter Avalos
2323