2 * Copyright (c) 2010-2012 Michihiro NAKAJIMA
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include "archive_platform.h"
27 __FBSDID("$FreeBSD$");
36 #if HAVE_LIBXML_XMLWRITER_H
37 #include <libxml/xmlwriter.h>
50 #include "archive_digest_private.h"
51 #include "archive_endian.h"
52 #include "archive_entry.h"
53 #include "archive_entry_locale.h"
54 #include "archive_private.h"
55 #include "archive_rb.h"
56 #include "archive_string.h"
57 #include "archive_write_private.h"
60 * Differences to xar utility.
61 * - Subdocument is not supported yet.
62 * - ACL is not supported yet.
63 * - When writing an XML element <link type="<file-type>">, <file-type>
64 * which is a file type a symbolic link is referencing is always marked
65 * as "broken". Xar utility uses stat(2) to get the file type, but, in
66 * libarchive format writer, we should not use it; if it is needed, we
67 * should get about it at archive_read_disk.c.
68 * - It is possible to appear both <flags> and <ext2> elements.
69 * Xar utility generates <flags> on BSD platform and <ext2> on Linux
74 #if !(defined(HAVE_LIBXML_XMLWRITER_H) && defined(LIBXML_VERSION) &&\
75 LIBXML_VERSION >= 20703) ||\
76 !defined(HAVE_ZLIB_H) || \
77 !defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1)
79 * xar needs several external libraries.
81 * o openssl or MD5/SHA1 hash function
87 archive_write_set_format_xar(struct archive *_a)
89 struct archive_write *a = (struct archive_write *)_a;
91 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
92 "Xar not supported on this platform");
93 return (ARCHIVE_WARN);
96 #else /* Support xar format */
98 /*#define DEBUG_PRINT_TOC 1 */
100 #define BAD_CAST_CONST (const xmlChar *)
102 #define HEADER_MAGIC 0x78617221
103 #define HEADER_SIZE 28
104 #define HEADER_VERSION 1
114 #define MAX_SUM_SIZE 20
115 #define MD5_NAME "md5"
116 #define SHA1_NAME "sha1"
128 #ifdef ARCHIVE_HAS_MD5
129 archive_md5_ctx md5ctx;
131 #ifdef ARCHIVE_HAS_SHA1
132 archive_sha1_ctx sha1ctx;
145 const unsigned char *next_in;
149 unsigned char *next_out;
155 int (*code) (struct archive *a,
156 struct la_zstream *lastrm,
157 enum la_zaction action);
158 int (*end)(struct archive *a,
159 struct la_zstream *lastrm);
165 unsigned char val[MAX_SUM_SIZE];
170 struct heap_data *next;
171 uint64_t temp_offset;
172 uint64_t length; /* archived size. */
173 uint64_t size; /* extracted size. */
174 enum enctype compression;
175 struct chksumval a_sum; /* archived checksum. */
176 struct chksumval e_sum; /* extracted checksum. */
180 struct archive_rb_node rbnode;
183 struct archive_entry *entry;
185 struct archive_rb_tree rbtree;
189 /* For hardlinked files.
190 * Use only when archive_entry_nlink() > 1 */
191 struct file *hardlink_target;
192 struct file *parent; /* parent directory entry */
194 * To manage sub directory files.
195 * We use 'chnext' (a member of struct file) to chain.
202 /* For making a directory tree. */
203 struct archive_string parentdir;
204 struct archive_string basename;
205 struct archive_string symlink;
209 struct heap_data *first;
210 struct heap_data **last;
212 struct heap_data data;
213 struct archive_string script;
215 signed int virtual:1;
220 struct archive_rb_node rbnode;
230 uint64_t temp_offset;
234 struct file *cur_dirent;
235 struct archive_string cur_dirstr;
236 struct file *cur_file;
237 uint64_t bytes_remaining;
238 struct archive_string tstr;
239 struct archive_string vstr;
241 enum sumalg opt_toc_sumalg;
242 enum sumalg opt_sumalg;
243 enum enctype opt_compression;
244 int opt_compression_level;
245 uint32_t opt_threads;
247 struct chksumwork a_sumwrk; /* archived checksum. */
248 struct chksumwork e_sumwrk; /* extracted checksum. */
249 struct la_zstream stream;
250 struct archive_string_conv *sconv;
252 * Compressed data buffer.
254 unsigned char wbuff[1024 * 64];
255 size_t wbuff_remaining;
257 struct heap_data toc;
259 * The list of all file entries is used to manage struct file
261 * We use 'next' (a member of struct file) to chain.
268 * The list of hard-linked file entries.
269 * We use 'hlnext' (a member of struct file) to chain.
271 struct archive_rb_tree hardlink_rbtree;
274 static int xar_options(struct archive_write *,
275 const char *, const char *);
276 static int xar_write_header(struct archive_write *,
277 struct archive_entry *);
278 static ssize_t xar_write_data(struct archive_write *,
279 const void *, size_t);
280 static int xar_finish_entry(struct archive_write *);
281 static int xar_close(struct archive_write *);
282 static int xar_free(struct archive_write *);
284 static struct file *file_new(struct archive_write *a, struct archive_entry *);
285 static void file_free(struct file *);
286 static struct file *file_create_virtual_dir(struct archive_write *a, struct xar *,
288 static int file_add_child_tail(struct file *, struct file *);
289 static struct file *file_find_child(struct file *, const char *);
290 static int file_gen_utility_names(struct archive_write *,
292 static int get_path_component(char *, int, const char *);
293 static int file_tree(struct archive_write *, struct file **);
294 static void file_register(struct xar *, struct file *);
295 static void file_init_register(struct xar *);
296 static void file_free_register(struct xar *);
297 static int file_register_hardlink(struct archive_write *,
299 static void file_connect_hardlink_files(struct xar *);
300 static void file_init_hardlinks(struct xar *);
301 static void file_free_hardlinks(struct xar *);
303 static void checksum_init(struct chksumwork *, enum sumalg);
304 static void checksum_update(struct chksumwork *, const void *, size_t);
305 static void checksum_final(struct chksumwork *, struct chksumval *);
306 static int compression_init_encoder_gzip(struct archive *,
307 struct la_zstream *, int, int);
308 static int compression_code_gzip(struct archive *,
309 struct la_zstream *, enum la_zaction);
310 static int compression_end_gzip(struct archive *, struct la_zstream *);
311 static int compression_init_encoder_bzip2(struct archive *,
312 struct la_zstream *, int);
313 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
314 static int compression_code_bzip2(struct archive *,
315 struct la_zstream *, enum la_zaction);
316 static int compression_end_bzip2(struct archive *, struct la_zstream *);
318 static int compression_init_encoder_lzma(struct archive *,
319 struct la_zstream *, int);
320 static int compression_init_encoder_xz(struct archive *,
321 struct la_zstream *, int, int);
322 #if defined(HAVE_LZMA_H)
323 static int compression_code_lzma(struct archive *,
324 struct la_zstream *, enum la_zaction);
325 static int compression_end_lzma(struct archive *, struct la_zstream *);
327 static int xar_compression_init_encoder(struct archive_write *);
328 static int compression_code(struct archive *,
329 struct la_zstream *, enum la_zaction);
330 static int compression_end(struct archive *,
331 struct la_zstream *);
332 static int save_xattrs(struct archive_write *, struct file *);
333 static int getalgsize(enum sumalg);
334 static const char *getalgname(enum sumalg);
337 archive_write_set_format_xar(struct archive *_a)
339 struct archive_write *a = (struct archive_write *)_a;
342 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
343 ARCHIVE_STATE_NEW, "archive_write_set_format_xar");
345 /* If another format was already registered, unregister it. */
346 if (a->format_free != NULL)
349 xar = calloc(1, sizeof(*xar));
351 archive_set_error(&a->archive, ENOMEM,
352 "Can't allocate xar data");
353 return (ARCHIVE_FATAL);
356 file_init_register(xar);
357 file_init_hardlinks(xar);
358 archive_string_init(&(xar->tstr));
359 archive_string_init(&(xar->vstr));
362 * Create the root directory.
364 xar->root = file_create_virtual_dir(a, xar, "");
365 if (xar->root == NULL) {
367 archive_set_error(&a->archive, ENOMEM,
368 "Can't allocate xar data");
369 return (ARCHIVE_FATAL);
371 xar->root->parent = xar->root;
372 file_register(xar, xar->root);
373 xar->cur_dirent = xar->root;
374 archive_string_init(&(xar->cur_dirstr));
375 archive_string_ensure(&(xar->cur_dirstr), 1);
376 xar->cur_dirstr.s[0] = 0;
381 /* Set default checksum type. */
382 xar->opt_toc_sumalg = CKSUM_SHA1;
383 xar->opt_sumalg = CKSUM_SHA1;
384 /* Set default compression type, level, and number of threads. */
385 xar->opt_compression = GZIP;
386 xar->opt_compression_level = 6;
387 xar->opt_threads = 1;
389 a->format_data = xar;
391 a->format_name = "xar";
392 a->format_options = xar_options;
393 a->format_write_header = xar_write_header;
394 a->format_write_data = xar_write_data;
395 a->format_finish_entry = xar_finish_entry;
396 a->format_close = xar_close;
397 a->format_free = xar_free;
398 a->archive.archive_format = ARCHIVE_FORMAT_XAR;
399 a->archive.archive_format_name = "xar";
405 xar_options(struct archive_write *a, const char *key, const char *value)
409 xar = (struct xar *)a->format_data;
411 if (strcmp(key, "checksum") == 0) {
413 xar->opt_sumalg = CKSUM_NONE;
414 else if (strcmp(value, "none") == 0)
415 xar->opt_sumalg = CKSUM_NONE;
416 else if (strcmp(value, "sha1") == 0)
417 xar->opt_sumalg = CKSUM_SHA1;
418 else if (strcmp(value, "md5") == 0)
419 xar->opt_sumalg = CKSUM_MD5;
421 archive_set_error(&(a->archive),
423 "Unknown checksum name: `%s'",
425 return (ARCHIVE_FAILED);
429 if (strcmp(key, "compression") == 0) {
430 const char *name = NULL;
433 xar->opt_compression = NONE;
434 else if (strcmp(value, "none") == 0)
435 xar->opt_compression = NONE;
436 else if (strcmp(value, "gzip") == 0)
437 xar->opt_compression = GZIP;
438 else if (strcmp(value, "bzip2") == 0)
439 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
440 xar->opt_compression = BZIP2;
444 else if (strcmp(value, "lzma") == 0)
446 xar->opt_compression = LZMA;
450 else if (strcmp(value, "xz") == 0)
452 xar->opt_compression = XZ;
457 archive_set_error(&(a->archive),
459 "Unknown compression name: `%s'",
461 return (ARCHIVE_FAILED);
464 archive_set_error(&(a->archive),
466 "`%s' compression not supported "
469 return (ARCHIVE_FAILED);
473 if (strcmp(key, "compression-level") == 0) {
475 !(value[0] >= '0' && value[0] <= '9') ||
477 archive_set_error(&(a->archive),
479 "Illegal value `%s'",
481 return (ARCHIVE_FAILED);
483 xar->opt_compression_level = value[0] - '0';
486 if (strcmp(key, "toc-checksum") == 0) {
488 xar->opt_toc_sumalg = CKSUM_NONE;
489 else if (strcmp(value, "none") == 0)
490 xar->opt_toc_sumalg = CKSUM_NONE;
491 else if (strcmp(value, "sha1") == 0)
492 xar->opt_toc_sumalg = CKSUM_SHA1;
493 else if (strcmp(value, "md5") == 0)
494 xar->opt_toc_sumalg = CKSUM_MD5;
496 archive_set_error(&(a->archive),
498 "Unknown checksum name: `%s'",
500 return (ARCHIVE_FAILED);
504 if (strcmp(key, "threads") == 0) {
508 return (ARCHIVE_FAILED);
510 xar->opt_threads = (int)strtoul(value, &endptr, 10);
511 if (errno != 0 || *endptr != '\0') {
512 xar->opt_threads = 1;
513 archive_set_error(&(a->archive),
515 "Illegal value `%s'",
517 return (ARCHIVE_FAILED);
519 if (xar->opt_threads == 0) {
520 #ifdef HAVE_LZMA_STREAM_ENCODER_MT
521 xar->opt_threads = lzma_cputhreads();
523 xar->opt_threads = 1;
528 /* Note: The "warn" return is just to inform the options
529 * supervisor that we didn't handle it. It will generate
530 * a suitable error if no one used this option. */
531 return (ARCHIVE_WARN);
535 xar_write_header(struct archive_write *a, struct archive_entry *entry)
539 struct archive_entry *file_entry;
542 xar = (struct xar *)a->format_data;
543 xar->cur_file = NULL;
544 xar->bytes_remaining = 0;
546 if (xar->sconv == NULL) {
547 xar->sconv = archive_string_conversion_to_charset(
548 &a->archive, "UTF-8", 1);
549 if (xar->sconv == NULL)
550 return (ARCHIVE_FATAL);
553 file = file_new(a, entry);
555 archive_set_error(&a->archive, ENOMEM,
556 "Can't allocate data");
557 return (ARCHIVE_FATAL);
559 r2 = file_gen_utility_names(a, file);
560 if (r2 < ARCHIVE_WARN)
564 * Ignore a path which looks like the top of directory name
565 * since we have already made the root directory of an Xar archive.
567 if (archive_strlen(&(file->parentdir)) == 0 &&
568 archive_strlen(&(file->basename)) == 0) {
573 /* Add entry into tree */
574 file_entry = file->entry;
575 r = file_tree(a, &file);
578 /* There is the same file in tree and
579 * the current file is older than the file in tree.
580 * So we don't need the current file data anymore. */
581 if (file->entry != file_entry)
584 file_register(xar, file);
586 /* A virtual file, which is a directory, does not have
587 * any contents and we won't store it into a archive
588 * file other than its name. */
593 * Prepare to save the contents of the file.
595 if (xar->temp_fd == -1) {
597 xar->temp_offset = 0;
598 xar->temp_fd = __archive_mktemp(NULL);
599 if (xar->temp_fd < 0) {
600 archive_set_error(&a->archive, errno,
601 "Couldn't create temporary file");
602 return (ARCHIVE_FATAL);
604 algsize = getalgsize(xar->opt_toc_sumalg);
606 if (lseek(xar->temp_fd, algsize, SEEK_SET) < 0) {
607 archive_set_error(&(a->archive), errno,
609 return (ARCHIVE_FATAL);
611 xar->temp_offset = algsize;
615 if (archive_entry_hardlink(file->entry) == NULL) {
616 r = save_xattrs(a, file);
618 return (ARCHIVE_FATAL);
621 /* Non regular files contents are unneeded to be saved to
622 * a temporary file. */
623 if (archive_entry_filetype(file->entry) != AE_IFREG)
627 * Set the current file to cur_file to read its contents.
629 xar->cur_file = file;
631 if (archive_entry_nlink(file->entry) > 1) {
632 r = file_register_hardlink(a, file);
635 if (archive_entry_hardlink(file->entry) != NULL) {
636 archive_entry_unset_size(file->entry);
641 /* Save a offset of current file in temporary file. */
642 file->data.temp_offset = xar->temp_offset;
643 file->data.size = archive_entry_size(file->entry);
644 file->data.compression = xar->opt_compression;
645 xar->bytes_remaining = archive_entry_size(file->entry);
646 checksum_init(&(xar->a_sumwrk), xar->opt_sumalg);
647 checksum_init(&(xar->e_sumwrk), xar->opt_sumalg);
648 r = xar_compression_init_encoder(a);
657 write_to_temp(struct archive_write *a, const void *buff, size_t s)
660 const unsigned char *p;
663 xar = (struct xar *)a->format_data;
664 p = (const unsigned char *)buff;
666 ws = write(xar->temp_fd, p, s);
668 archive_set_error(&(a->archive), errno,
669 "fwrite function failed");
670 return (ARCHIVE_FATAL);
674 xar->temp_offset += ws;
680 xar_write_data(struct archive_write *a, const void *buff, size_t s)
687 xar = (struct xar *)a->format_data;
689 if (s > xar->bytes_remaining)
690 s = (size_t)xar->bytes_remaining;
691 if (s == 0 || xar->cur_file == NULL)
693 if (xar->cur_file->data.compression == NONE) {
694 checksum_update(&(xar->e_sumwrk), buff, s);
695 checksum_update(&(xar->a_sumwrk), buff, s);
698 xar->stream.next_in = (const unsigned char *)buff;
699 xar->stream.avail_in = s;
700 if (xar->bytes_remaining > s)
703 run = ARCHIVE_Z_FINISH;
704 /* Compress file data. */
706 r = compression_code(&(a->archive), &(xar->stream),
708 if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
709 return (ARCHIVE_FATAL);
710 if (xar->stream.avail_out == 0 ||
711 run == ARCHIVE_Z_FINISH) {
712 size = sizeof(xar->wbuff) -
713 xar->stream.avail_out;
714 checksum_update(&(xar->a_sumwrk), xar->wbuff,
716 xar->cur_file->data.length += size;
717 if (write_to_temp(a, xar->wbuff,
719 return (ARCHIVE_FATAL);
720 if (r == ARCHIVE_OK) {
721 /* Output buffer was full */
722 xar->stream.next_out = xar->wbuff;
723 xar->stream.avail_out =
726 /* ARCHIVE_EOF - We are done */
730 /* Compressor wants more input */
734 rsize = s - xar->stream.avail_in;
735 checksum_update(&(xar->e_sumwrk), buff, rsize);
737 #if !defined(_WIN32) || defined(__CYGWIN__)
738 if (xar->bytes_remaining ==
739 (uint64_t)archive_entry_size(xar->cur_file->entry)) {
741 * Get the path of a shell script if so.
743 const unsigned char *b = (const unsigned char *)buff;
745 archive_string_empty(&(xar->cur_file->script));
746 if (rsize > 2 && b[0] == '#' && b[1] == '!') {
753 if ((rsize - off) > PATH_MAX)
754 end = off + PATH_MAX;
758 /* Find the end of a script path. */
759 for (i = off; i < end && b[i] != '\0' &&
760 b[i] != '\n' && b[i] != '\r' &&
761 b[i] != ' ' && b[i] != '\t'; i++)
763 archive_strncpy(&(xar->cur_file->script), b + off,
769 if (xar->cur_file->data.compression == NONE) {
770 if (write_to_temp(a, buff, size) != ARCHIVE_OK)
771 return (ARCHIVE_FATAL);
772 xar->cur_file->data.length += size;
774 xar->bytes_remaining -= rsize;
780 xar_finish_entry(struct archive_write *a)
787 xar = (struct xar *)a->format_data;
788 if (xar->cur_file == NULL)
791 while (xar->bytes_remaining > 0) {
792 s = (size_t)xar->bytes_remaining;
793 if (s > a->null_length)
795 w = xar_write_data(a, a->nulls, s);
797 xar->bytes_remaining -= w;
801 file = xar->cur_file;
802 checksum_final(&(xar->e_sumwrk), &(file->data.e_sum));
803 checksum_final(&(xar->a_sumwrk), &(file->data.a_sum));
804 xar->cur_file = NULL;
810 xmlwrite_string_attr(struct archive_write *a, xmlTextWriterPtr writer,
811 const char *key, const char *value,
812 const char *attrkey, const char *attrvalue)
816 r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key));
818 archive_set_error(&a->archive,
820 "xmlTextWriterStartElement() failed: %d", r);
821 return (ARCHIVE_FATAL);
823 if (attrkey != NULL && attrvalue != NULL) {
824 r = xmlTextWriterWriteAttribute(writer,
825 BAD_CAST_CONST(attrkey), BAD_CAST_CONST(attrvalue));
827 archive_set_error(&a->archive,
829 "xmlTextWriterWriteAttribute() failed: %d", r);
830 return (ARCHIVE_FATAL);
834 r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value));
836 archive_set_error(&a->archive,
838 "xmlTextWriterWriteString() failed: %d", r);
839 return (ARCHIVE_FATAL);
842 r = xmlTextWriterEndElement(writer);
844 archive_set_error(&a->archive,
846 "xmlTextWriterEndElement() failed: %d", r);
847 return (ARCHIVE_FATAL);
853 xmlwrite_string(struct archive_write *a, xmlTextWriterPtr writer,
854 const char *key, const char *value)
861 r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key));
863 archive_set_error(&a->archive,
865 "xmlTextWriterStartElement() failed: %d", r);
866 return (ARCHIVE_FATAL);
869 r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value));
871 archive_set_error(&a->archive,
873 "xmlTextWriterWriteString() failed: %d", r);
874 return (ARCHIVE_FATAL);
877 r = xmlTextWriterEndElement(writer);
879 archive_set_error(&a->archive,
881 "xmlTextWriterEndElement() failed: %d", r);
882 return (ARCHIVE_FATAL);
888 xmlwrite_fstring(struct archive_write *a, xmlTextWriterPtr writer,
889 const char *key, const char *fmt, ...)
894 xar = (struct xar *)a->format_data;
896 archive_string_empty(&xar->vstr);
897 archive_string_vsprintf(&xar->vstr, fmt, ap);
899 return (xmlwrite_string(a, writer, key, xar->vstr.s));
903 xmlwrite_time(struct archive_write *a, xmlTextWriterPtr writer,
904 const char *key, time_t t, int z)
908 #if defined(HAVE__GMTIME64_S)
912 #if defined(HAVE_GMTIME_R)
914 #elif defined(HAVE__GMTIME64_S)
916 _gmtime64_s(&tm, &tmptime);
918 memcpy(&tm, gmtime(&t), sizeof(tm));
920 memset(×tr, 0, sizeof(timestr));
921 /* Do not use %F and %T for portability. */
922 strftime(timestr, sizeof(timestr), "%Y-%m-%dT%H:%M:%S", &tm);
924 strcat(timestr, "Z");
925 return (xmlwrite_string(a, writer, key, timestr));
929 xmlwrite_mode(struct archive_write *a, xmlTextWriterPtr writer,
930 const char *key, mode_t mode)
935 ms[1] = '0' + ((mode >> 6) & 07);
936 ms[2] = '0' + ((mode >> 3) & 07);
937 ms[3] = '0' + (mode & 07);
940 return (xmlwrite_string(a, writer, key, ms));
944 xmlwrite_sum(struct archive_write *a, xmlTextWriterPtr writer,
945 const char *key, struct chksumval *sum)
949 char buff[MAX_SUM_SIZE*2 + 1];
955 algname = getalgname(sum->alg);
956 algsize = getalgsize(sum->alg);
957 if (algname != NULL) {
958 const char *hex = "0123456789abcdef";
961 for (i = 0; i < algsize; i++) {
962 *p++ = hex[(*s >> 4)];
963 *p++ = hex[(*s & 0x0f)];
967 r = xmlwrite_string_attr(a, writer,
971 return (ARCHIVE_FATAL);
978 xmlwrite_heap(struct archive_write *a, xmlTextWriterPtr writer,
979 struct heap_data *heap)
984 r = xmlwrite_fstring(a, writer, "length", "%ju", heap->length);
986 return (ARCHIVE_FATAL);
987 r = xmlwrite_fstring(a, writer, "offset", "%ju", heap->temp_offset);
989 return (ARCHIVE_FATAL);
990 r = xmlwrite_fstring(a, writer, "size", "%ju", heap->size);
992 return (ARCHIVE_FATAL);
993 switch (heap->compression) {
995 encname = "application/x-gzip"; break;
997 encname = "application/x-bzip2"; break;
999 encname = "application/x-lzma"; break;
1001 encname = "application/x-xz"; break;
1003 encname = "application/octet-stream"; break;
1005 r = xmlwrite_string_attr(a, writer, "encoding", NULL,
1008 return (ARCHIVE_FATAL);
1009 r = xmlwrite_sum(a, writer, "archived-checksum", &(heap->a_sum));
1011 return (ARCHIVE_FATAL);
1012 r = xmlwrite_sum(a, writer, "extracted-checksum", &(heap->e_sum));
1014 return (ARCHIVE_FATAL);
1015 return (ARCHIVE_OK);
1019 * xar utility records fflags as following xml elements:
1029 * If xar is running on BSD platform, records <flags>..</flags>;
1030 * if xar is running on linux platform, records <ext2>..</ext2>;
1031 * otherwise does not record.
1033 * Our implements records both <flags> and <ext2> if it's necessary.
1036 make_fflags_entry(struct archive_write *a, xmlTextWriterPtr writer,
1037 const char *element, const char *fflags_text)
1039 static const struct flagentry {
1041 const char *xarname;
1044 { "sappnd", "SystemAppend"},
1045 { "sappend", "SystemAppend"},
1046 { "arch", "SystemArchived"},
1047 { "archived", "SystemArchived"},
1048 { "schg", "SystemImmutable"},
1049 { "schange", "SystemImmutable"},
1050 { "simmutable", "SystemImmutable"},
1051 { "nosunlnk", "SystemNoUnlink"},
1052 { "nosunlink", "SystemNoUnlink"},
1053 { "snapshot", "SystemSnapshot"},
1054 { "uappnd", "UserAppend"},
1055 { "uappend", "UserAppend"},
1056 { "uchg", "UserImmutable"},
1057 { "uchange", "UserImmutable"},
1058 { "uimmutable", "UserImmutable"},
1059 { "nodump", "UserNoDump"},
1060 { "noopaque", "UserOpaque"},
1061 { "nouunlnk", "UserNoUnlink"},
1062 { "nouunlink", "UserNoUnlink"},
1066 { "sappnd", "AppendOnly"},
1067 { "sappend", "AppendOnly"},
1068 { "schg", "Immutable"},
1069 { "schange", "Immutable"},
1070 { "simmutable", "Immutable"},
1071 { "nodump", "NoDump"},
1072 { "nouunlnk", "Undelete"},
1073 { "nouunlink", "Undelete"},
1074 { "btree", "BTree"},
1075 { "comperr", "CompError"},
1076 { "compress", "Compress"},
1077 { "noatime", "NoAtime"},
1078 { "compdirty", "CompDirty"},
1079 { "comprblk", "CompBlock"},
1080 { "dirsync", "DirSync"},
1081 { "hashidx", "HashIndexed"},
1082 { "imagic", "iMagic"},
1083 { "journal", "Journaled"},
1084 { "securedeletion", "SecureDeletion"},
1085 { "sync", "Synchronous"},
1086 { "notail", "NoTail"},
1087 { "topdir", "TopDir"},
1088 { "reserved", "Reserved"},
1091 const struct flagentry *fe, *flagentry;
1092 #define FLAGENTRY_MAXSIZE ((sizeof(flagbsd)+sizeof(flagext2))/sizeof(flagbsd))
1093 const struct flagentry *avail[FLAGENTRY_MAXSIZE];
1097 if (strcmp(element, "ext2") == 0)
1098 flagentry = flagext2;
1100 flagentry = flagbsd;
1106 cp = strchr(p, ',');
1110 for (fe = flagentry; fe->name != NULL; fe++) {
1111 if (fe->name[cp - p] != '\0'
1112 || p[0] != fe->name[0])
1114 if (strncmp(p, fe->name, cp - p) == 0) {
1123 } while (p != NULL);
1126 r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(element));
1128 archive_set_error(&a->archive,
1130 "xmlTextWriterStartElement() failed: %d", r);
1131 return (ARCHIVE_FATAL);
1133 for (i = 0; i < n; i++) {
1134 r = xmlwrite_string(a, writer,
1135 avail[i]->xarname, NULL);
1136 if (r != ARCHIVE_OK)
1140 r = xmlTextWriterEndElement(writer);
1142 archive_set_error(&a->archive,
1144 "xmlTextWriterEndElement() failed: %d", r);
1145 return (ARCHIVE_FATAL);
1148 return (ARCHIVE_OK);
1152 make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
1156 const char *filetype, *filelink, *fflags;
1157 struct archive_string linkto;
1158 struct heap_data *heap;
1164 xar = (struct xar *)a->format_data;
1168 * Make a file name entry, "<name>".
1170 l = ll = archive_strlen(&(file->basename));
1173 archive_set_error(&a->archive, ENOMEM,
1174 "Can't allocate memory");
1175 return (ARCHIVE_FATAL);
1177 r = UTF8Toisolat1(tmp, &l, BAD_CAST(file->basename.s), &ll);
1180 r = xmlTextWriterStartElement(writer, BAD_CAST("name"));
1182 archive_set_error(&a->archive,
1184 "xmlTextWriterStartElement() failed: %d", r);
1185 return (ARCHIVE_FATAL);
1187 r = xmlTextWriterWriteAttribute(writer,
1188 BAD_CAST("enctype"), BAD_CAST("base64"));
1190 archive_set_error(&a->archive,
1192 "xmlTextWriterWriteAttribute() failed: %d", r);
1193 return (ARCHIVE_FATAL);
1195 r = xmlTextWriterWriteBase64(writer, file->basename.s,
1196 0, archive_strlen(&(file->basename)));
1198 archive_set_error(&a->archive,
1200 "xmlTextWriterWriteBase64() failed: %d", r);
1201 return (ARCHIVE_FATAL);
1203 r = xmlTextWriterEndElement(writer);
1205 archive_set_error(&a->archive,
1207 "xmlTextWriterEndElement() failed: %d", r);
1208 return (ARCHIVE_FATAL);
1211 r = xmlwrite_string(a, writer, "name", file->basename.s);
1213 return (ARCHIVE_FATAL);
1217 * Make a file type entry, "<type>".
1220 archive_string_init(&linkto);
1221 switch (archive_entry_filetype(file->entry)) {
1223 filetype = "directory"; break;
1225 filetype = "symlink"; break;
1227 filetype = "character special"; break;
1229 filetype = "block special"; break;
1231 filetype = "socket"; break;
1233 filetype = "fifo"; break;
1236 if (file->hardlink_target != NULL) {
1237 filetype = "hardlink";
1239 if (file->hardlink_target == file)
1240 archive_strcpy(&linkto, "original");
1242 archive_string_sprintf(&linkto, "%d",
1243 file->hardlink_target->id);
1248 r = xmlwrite_string_attr(a, writer, "type", filetype,
1249 filelink, linkto.s);
1250 archive_string_free(&linkto);
1252 return (ARCHIVE_FATAL);
1255 * On a virtual directory, we record "name" and "type" only.
1258 return (ARCHIVE_OK);
1260 switch (archive_entry_filetype(file->entry)) {
1263 * xar utility has checked a file type, which
1264 * a symbolic-link file has referenced.
1266 * <link type="directory">../ref/</link>
1267 * The symlink target file is "../ref/" and its
1268 * file type is a directory.
1270 * <link type="file">../f</link>
1271 * The symlink target file is "../f" and its
1272 * file type is a regular file.
1274 * But our implementation cannot do it, and then we
1275 * always record that a attribute "type" is "broken",
1277 * <link type="broken">foo/bar</link>
1278 * It means "foo/bar" is not reachable.
1280 r = xmlwrite_string_attr(a, writer, "link",
1284 return (ARCHIVE_FATAL);
1288 r = xmlTextWriterStartElement(writer, BAD_CAST("device"));
1290 archive_set_error(&a->archive,
1292 "xmlTextWriterStartElement() failed: %d", r);
1293 return (ARCHIVE_FATAL);
1295 r = xmlwrite_fstring(a, writer, "major",
1296 "%d", archive_entry_rdevmajor(file->entry));
1298 return (ARCHIVE_FATAL);
1299 r = xmlwrite_fstring(a, writer, "minor",
1300 "%d", archive_entry_rdevminor(file->entry));
1302 return (ARCHIVE_FATAL);
1303 r = xmlTextWriterEndElement(writer);
1305 archive_set_error(&a->archive,
1307 "xmlTextWriterEndElement() failed: %d", r);
1308 return (ARCHIVE_FATAL);
1316 * Make a inode entry, "<inode>".
1318 r = xmlwrite_fstring(a, writer, "inode",
1319 "%jd", archive_entry_ino64(file->entry));
1321 return (ARCHIVE_FATAL);
1322 if (archive_entry_dev(file->entry) != 0) {
1323 r = xmlwrite_fstring(a, writer, "deviceno",
1324 "%d", archive_entry_dev(file->entry));
1326 return (ARCHIVE_FATAL);
1330 * Make a file mode entry, "<mode>".
1332 r = xmlwrite_mode(a, writer, "mode",
1333 archive_entry_mode(file->entry));
1335 return (ARCHIVE_FATAL);
1338 * Make a user entry, "<uid>" and "<user>.
1340 r = xmlwrite_fstring(a, writer, "uid",
1341 "%d", archive_entry_uid(file->entry));
1343 return (ARCHIVE_FATAL);
1344 r = archive_entry_uname_l(file->entry, &p, &len, xar->sconv);
1346 if (errno == ENOMEM) {
1347 archive_set_error(&a->archive, ENOMEM,
1348 "Can't allocate memory for Uname");
1349 return (ARCHIVE_FATAL);
1351 archive_set_error(&a->archive,
1352 ARCHIVE_ERRNO_FILE_FORMAT,
1353 "Can't translate uname '%s' to UTF-8",
1354 archive_entry_uname(file->entry));
1358 r = xmlwrite_string(a, writer, "user", p);
1360 return (ARCHIVE_FATAL);
1364 * Make a group entry, "<gid>" and "<group>.
1366 r = xmlwrite_fstring(a, writer, "gid",
1367 "%d", archive_entry_gid(file->entry));
1369 return (ARCHIVE_FATAL);
1370 r = archive_entry_gname_l(file->entry, &p, &len, xar->sconv);
1372 if (errno == ENOMEM) {
1373 archive_set_error(&a->archive, ENOMEM,
1374 "Can't allocate memory for Gname");
1375 return (ARCHIVE_FATAL);
1377 archive_set_error(&a->archive,
1378 ARCHIVE_ERRNO_FILE_FORMAT,
1379 "Can't translate gname '%s' to UTF-8",
1380 archive_entry_gname(file->entry));
1384 r = xmlwrite_string(a, writer, "group", p);
1386 return (ARCHIVE_FATAL);
1390 * Make a ctime entry, "<ctime>".
1392 if (archive_entry_ctime_is_set(file->entry)) {
1393 r = xmlwrite_time(a, writer, "ctime",
1394 archive_entry_ctime(file->entry), 1);
1396 return (ARCHIVE_FATAL);
1400 * Make a mtime entry, "<mtime>".
1402 if (archive_entry_mtime_is_set(file->entry)) {
1403 r = xmlwrite_time(a, writer, "mtime",
1404 archive_entry_mtime(file->entry), 1);
1406 return (ARCHIVE_FATAL);
1410 * Make a atime entry, "<atime>".
1412 if (archive_entry_atime_is_set(file->entry)) {
1413 r = xmlwrite_time(a, writer, "atime",
1414 archive_entry_atime(file->entry), 1);
1416 return (ARCHIVE_FATAL);
1420 * Make fflags entries, "<flags>" and "<ext2>".
1422 fflags = archive_entry_fflags_text(file->entry);
1423 if (fflags != NULL) {
1424 r = make_fflags_entry(a, writer, "flags", fflags);
1427 r = make_fflags_entry(a, writer, "ext2", fflags);
1433 * Make extended attribute entries, "<ea>".
1435 archive_entry_xattr_reset(file->entry);
1436 for (heap = file->xattr.first; heap != NULL; heap = heap->next) {
1441 archive_entry_xattr_next(file->entry,
1442 &name, &value, &size);
1443 r = xmlTextWriterStartElement(writer, BAD_CAST("ea"));
1445 archive_set_error(&a->archive,
1447 "xmlTextWriterStartElement() failed: %d", r);
1448 return (ARCHIVE_FATAL);
1450 r = xmlTextWriterWriteFormatAttribute(writer,
1451 BAD_CAST("id"), "%d", heap->id);
1453 archive_set_error(&a->archive,
1455 "xmlTextWriterWriteAttribute() failed: %d", r);
1456 return (ARCHIVE_FATAL);
1458 r = xmlwrite_heap(a, writer, heap);
1460 return (ARCHIVE_FATAL);
1461 r = xmlwrite_string(a, writer, "name", name);
1463 return (ARCHIVE_FATAL);
1465 r = xmlTextWriterEndElement(writer);
1467 archive_set_error(&a->archive,
1469 "xmlTextWriterEndElement() failed: %d", r);
1470 return (ARCHIVE_FATAL);
1475 * Make a file data entry, "<data>".
1477 if (file->data.length > 0) {
1478 r = xmlTextWriterStartElement(writer, BAD_CAST("data"));
1480 archive_set_error(&a->archive,
1482 "xmlTextWriterStartElement() failed: %d", r);
1483 return (ARCHIVE_FATAL);
1486 r = xmlwrite_heap(a, writer, &(file->data));
1488 return (ARCHIVE_FATAL);
1490 r = xmlTextWriterEndElement(writer);
1492 archive_set_error(&a->archive,
1494 "xmlTextWriterEndElement() failed: %d", r);
1495 return (ARCHIVE_FATAL);
1499 if (archive_strlen(&file->script) > 0) {
1500 r = xmlTextWriterStartElement(writer, BAD_CAST("content"));
1502 archive_set_error(&a->archive,
1504 "xmlTextWriterStartElement() failed: %d", r);
1505 return (ARCHIVE_FATAL);
1508 r = xmlwrite_string(a, writer,
1509 "interpreter", file->script.s);
1511 return (ARCHIVE_FATAL);
1513 r = xmlwrite_string(a, writer, "type", "script");
1515 return (ARCHIVE_FATAL);
1517 r = xmlTextWriterEndElement(writer);
1519 archive_set_error(&a->archive,
1521 "xmlTextWriterEndElement() failed: %d", r);
1522 return (ARCHIVE_FATAL);
1533 make_toc(struct archive_write *a)
1538 xmlTextWriterPtr writer;
1542 xar = (struct xar *)a->format_data;
1544 ret = ARCHIVE_FATAL;
1547 * Initialize xml writer.
1550 bp = xmlBufferCreate();
1552 archive_set_error(&a->archive, ENOMEM,
1553 "xmlBufferCreate() "
1554 "couldn't create xml buffer");
1557 writer = xmlNewTextWriterMemory(bp, 0);
1558 if (writer == NULL) {
1559 archive_set_error(&a->archive,
1561 "xmlNewTextWriterMemory() "
1562 "couldn't create xml writer");
1565 r = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL);
1567 archive_set_error(&a->archive,
1569 "xmlTextWriterStartDocument() failed: %d", r);
1572 r = xmlTextWriterSetIndent(writer, 4);
1574 archive_set_error(&a->archive,
1576 "xmlTextWriterSetIndent() failed: %d", r);
1581 * Start recording TOC
1583 r = xmlTextWriterStartElement(writer, BAD_CAST("xar"));
1585 archive_set_error(&a->archive,
1587 "xmlTextWriterStartElement() failed: %d", r);
1590 r = xmlTextWriterStartElement(writer, BAD_CAST("toc"));
1592 archive_set_error(&a->archive,
1594 "xmlTextWriterStartDocument() failed: %d", r);
1599 * Record the creation time of the archive file.
1601 r = xmlwrite_time(a, writer, "creation-time", time(NULL), 0);
1606 * Record the checksum value of TOC
1608 algsize = getalgsize(xar->opt_toc_sumalg);
1611 * Record TOC checksum
1613 r = xmlTextWriterStartElement(writer, BAD_CAST("checksum"));
1615 archive_set_error(&a->archive,
1617 "xmlTextWriterStartElement() failed: %d", r);
1620 r = xmlTextWriterWriteAttribute(writer, BAD_CAST("style"),
1621 BAD_CAST_CONST(getalgname(xar->opt_toc_sumalg)));
1623 archive_set_error(&a->archive,
1625 "xmlTextWriterWriteAttribute() failed: %d", r);
1630 * Record the offset of the value of checksum of TOC
1632 r = xmlwrite_string(a, writer, "offset", "0");
1637 * Record the size of the value of checksum of TOC
1639 r = xmlwrite_fstring(a, writer, "size", "%d", algsize);
1643 r = xmlTextWriterEndElement(writer);
1645 archive_set_error(&a->archive,
1647 "xmlTextWriterEndElement() failed: %d", r);
1654 if (np != np->parent) {
1655 r = make_file_entry(a, writer, np);
1656 if (r != ARCHIVE_OK)
1660 if (np->dir && np->children.first != NULL) {
1661 /* Enter to sub directories. */
1662 np = np->children.first;
1663 r = xmlTextWriterStartElement(writer,
1666 archive_set_error(&a->archive,
1668 "xmlTextWriterStartElement() "
1672 r = xmlTextWriterWriteFormatAttribute(
1673 writer, BAD_CAST("id"), "%d", np->id);
1675 archive_set_error(&a->archive,
1677 "xmlTextWriterWriteAttribute() "
1683 while (np != np->parent) {
1684 r = xmlTextWriterEndElement(writer);
1686 archive_set_error(&a->archive,
1688 "xmlTextWriterEndElement() "
1692 if (np->chnext == NULL) {
1693 /* Return to the parent directory. */
1697 r = xmlTextWriterStartElement(writer,
1700 archive_set_error(&a->archive,
1702 "xmlTextWriterStartElement() "
1706 r = xmlTextWriterWriteFormatAttribute(
1707 writer, BAD_CAST("id"), "%d", np->id);
1709 archive_set_error(&a->archive,
1711 "xmlTextWriterWriteAttribute() "
1718 } while (np != np->parent);
1720 r = xmlTextWriterEndDocument(writer);
1722 archive_set_error(&a->archive,
1724 "xmlTextWriterEndDocument() failed: %d", r);
1728 fprintf(stderr, "\n---TOC-- %d bytes --\n%s\n",
1729 strlen((const char *)bp->content), bp->content);
1733 * Compress the TOC and calculate the sum of the TOC.
1735 xar->toc.temp_offset = xar->temp_offset;
1736 xar->toc.size = bp->use;
1737 checksum_init(&(xar->a_sumwrk), xar->opt_toc_sumalg);
1739 r = compression_init_encoder_gzip(&(a->archive),
1740 &(xar->stream), 6, 1);
1741 if (r != ARCHIVE_OK)
1743 xar->stream.next_in = bp->content;
1744 xar->stream.avail_in = bp->use;
1745 xar->stream.total_in = 0;
1746 xar->stream.next_out = xar->wbuff;
1747 xar->stream.avail_out = sizeof(xar->wbuff);
1748 xar->stream.total_out = 0;
1752 r = compression_code(&(a->archive),
1753 &(xar->stream), ARCHIVE_Z_FINISH);
1754 if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
1756 size = sizeof(xar->wbuff) - xar->stream.avail_out;
1757 checksum_update(&(xar->a_sumwrk), xar->wbuff, size);
1758 if (write_to_temp(a, xar->wbuff, size) != ARCHIVE_OK)
1760 if (r == ARCHIVE_EOF)
1762 xar->stream.next_out = xar->wbuff;
1763 xar->stream.avail_out = sizeof(xar->wbuff);
1765 r = compression_end(&(a->archive), &(xar->stream));
1766 if (r != ARCHIVE_OK)
1768 xar->toc.length = xar->stream.total_out;
1769 xar->toc.compression = GZIP;
1770 checksum_final(&(xar->a_sumwrk), &(xar->toc.a_sum));
1775 xmlFreeTextWriter(writer);
1783 flush_wbuff(struct archive_write *a)
1789 xar = (struct xar *)a->format_data;
1790 s = sizeof(xar->wbuff) - xar->wbuff_remaining;
1791 r = __archive_write_output(a, xar->wbuff, s);
1792 if (r != ARCHIVE_OK)
1794 xar->wbuff_remaining = sizeof(xar->wbuff);
1799 copy_out(struct archive_write *a, uint64_t offset, uint64_t length)
1804 xar = (struct xar *)a->format_data;
1805 if (lseek(xar->temp_fd, offset, SEEK_SET) < 0) {
1806 archive_set_error(&(a->archive), errno, "lseek failed");
1807 return (ARCHIVE_FATAL);
1814 if (length > xar->wbuff_remaining)
1815 rsize = xar->wbuff_remaining;
1817 rsize = (size_t)length;
1818 wb = xar->wbuff + (sizeof(xar->wbuff) - xar->wbuff_remaining);
1819 rs = read(xar->temp_fd, wb, rsize);
1821 archive_set_error(&(a->archive), errno,
1822 "Can't read temporary file(%jd)",
1824 return (ARCHIVE_FATAL);
1827 archive_set_error(&(a->archive), 0,
1828 "Truncated xar archive");
1829 return (ARCHIVE_FATAL);
1831 xar->wbuff_remaining -= rs;
1833 if (xar->wbuff_remaining == 0) {
1835 if (r != ARCHIVE_OK)
1839 return (ARCHIVE_OK);
1843 xar_close(struct archive_write *a)
1850 xar = (struct xar *)a->format_data;
1853 if (xar->root->children.first == NULL)
1854 return (ARCHIVE_OK);
1856 /* Save the length of all file extended attributes and contents. */
1857 length = xar->temp_offset;
1859 /* Connect hardlinked files */
1860 file_connect_hardlink_files(xar);
1864 if (r != ARCHIVE_OK)
1867 * Make the xar header on wbuff(write buffer).
1870 xar->wbuff_remaining = sizeof(xar->wbuff);
1871 archive_be32enc(&wb[0], HEADER_MAGIC);
1872 archive_be16enc(&wb[4], HEADER_SIZE);
1873 archive_be16enc(&wb[6], HEADER_VERSION);
1874 archive_be64enc(&wb[8], xar->toc.length);
1875 archive_be64enc(&wb[16], xar->toc.size);
1876 archive_be32enc(&wb[24], xar->toc.a_sum.alg);
1877 xar->wbuff_remaining -= HEADER_SIZE;
1882 r = copy_out(a, xar->toc.temp_offset, xar->toc.length);
1883 if (r != ARCHIVE_OK)
1886 /* Write the checksum value of the TOC. */
1887 if (xar->toc.a_sum.len) {
1888 if (xar->wbuff_remaining < xar->toc.a_sum.len) {
1890 if (r != ARCHIVE_OK)
1893 wb = xar->wbuff + (sizeof(xar->wbuff) - xar->wbuff_remaining);
1894 memcpy(wb, xar->toc.a_sum.val, xar->toc.a_sum.len);
1895 xar->wbuff_remaining -= xar->toc.a_sum.len;
1899 * Write all file extended attributes and contents.
1901 r = copy_out(a, xar->toc.a_sum.len, length);
1902 if (r != ARCHIVE_OK)
1909 xar_free(struct archive_write *a)
1913 xar = (struct xar *)a->format_data;
1915 /* Close the temporary file. */
1916 if (xar->temp_fd >= 0)
1917 close(xar->temp_fd);
1919 archive_string_free(&(xar->cur_dirstr));
1920 archive_string_free(&(xar->tstr));
1921 archive_string_free(&(xar->vstr));
1922 file_free_hardlinks(xar);
1923 file_free_register(xar);
1924 compression_end(&(a->archive), &(xar->stream));
1927 return (ARCHIVE_OK);
1931 file_cmp_node(const struct archive_rb_node *n1,
1932 const struct archive_rb_node *n2)
1934 const struct file *f1 = (const struct file *)n1;
1935 const struct file *f2 = (const struct file *)n2;
1937 return (strcmp(f1->basename.s, f2->basename.s));
1941 file_cmp_key(const struct archive_rb_node *n, const void *key)
1943 const struct file *f = (const struct file *)n;
1945 return (strcmp(f->basename.s, (const char *)key));
1948 static struct file *
1949 file_new(struct archive_write *a, struct archive_entry *entry)
1952 static const struct archive_rb_tree_ops rb_ops = {
1953 file_cmp_node, file_cmp_key
1956 file = calloc(1, sizeof(*file));
1961 file->entry = archive_entry_clone(entry);
1963 file->entry = archive_entry_new2(&a->archive);
1964 if (file->entry == NULL) {
1968 __archive_rb_tree_init(&(file->rbtree), &rb_ops);
1969 file->children.first = NULL;
1970 file->children.last = &(file->children.first);
1971 file->xattr.first = NULL;
1972 file->xattr.last = &(file->xattr.first);
1973 archive_string_init(&(file->parentdir));
1974 archive_string_init(&(file->basename));
1975 archive_string_init(&(file->symlink));
1976 archive_string_init(&(file->script));
1977 if (entry != NULL && archive_entry_filetype(entry) == AE_IFDIR)
1984 file_free(struct file *file)
1986 struct heap_data *heap, *next_heap;
1988 heap = file->xattr.first;
1989 while (heap != NULL) {
1990 next_heap = heap->next;
1994 archive_string_free(&(file->parentdir));
1995 archive_string_free(&(file->basename));
1996 archive_string_free(&(file->symlink));
1997 archive_string_free(&(file->script));
1998 archive_entry_free(file->entry);
2002 static struct file *
2003 file_create_virtual_dir(struct archive_write *a, struct xar *xar,
2004 const char *pathname)
2008 (void)xar; /* UNUSED */
2010 file = file_new(a, NULL);
2013 archive_entry_set_pathname(file->entry, pathname);
2014 archive_entry_set_mode(file->entry, 0555 | AE_IFDIR);
2023 file_add_child_tail(struct file *parent, struct file *child)
2025 if (!__archive_rb_tree_insert_node(
2026 &(parent->rbtree), (struct archive_rb_node *)child))
2028 child->chnext = NULL;
2029 *parent->children.last = child;
2030 parent->children.last = &(child->chnext);
2031 child->parent = parent;
2036 * Find a entry from `parent'
2038 static struct file *
2039 file_find_child(struct file *parent, const char *child_name)
2043 np = (struct file *)__archive_rb_tree_find_node(
2044 &(parent->rbtree), child_name);
2048 #if defined(_WIN32) || defined(__CYGWIN__)
2050 cleanup_backslash(char *utf8, size_t len)
2053 /* Convert a path-separator from '\' to '/' */
2054 while (*utf8 != '\0' && len) {
2062 #define cleanup_backslash(p, len) /* nop */
2066 * Generate a parent directory name and a base name from a pathname.
2069 file_gen_utility_names(struct archive_write *a, struct file *file)
2073 char *p, *dirname, *slash;
2077 xar = (struct xar *)a->format_data;
2078 archive_string_empty(&(file->parentdir));
2079 archive_string_empty(&(file->basename));
2080 archive_string_empty(&(file->symlink));
2082 if (file->parent == file)/* virtual root */
2083 return (ARCHIVE_OK);
2085 if (archive_entry_pathname_l(file->entry, &pp, &len, xar->sconv)
2087 if (errno == ENOMEM) {
2088 archive_set_error(&a->archive, ENOMEM,
2089 "Can't allocate memory for Pathname");
2090 return (ARCHIVE_FATAL);
2092 archive_set_error(&a->archive,
2093 ARCHIVE_ERRNO_FILE_FORMAT,
2094 "Can't translate pathname '%s' to UTF-8",
2095 archive_entry_pathname(file->entry));
2098 archive_strncpy(&(file->parentdir), pp, len);
2099 len = file->parentdir.length;
2100 p = dirname = file->parentdir.s;
2102 * Convert a path-separator from '\' to '/'
2104 cleanup_backslash(p, len);
2107 * Remove leading '/', '../' and './' elements
2113 } else if (p[0] != '.')
2115 else if (p[1] == '.' && p[2] == '/') {
2118 } else if (p[1] == '/' || (p[1] == '.' && p[2] == '\0')) {
2121 } else if (p[1] == '\0') {
2128 memmove(dirname, p, len+1);
2132 * Remove "/","/." and "/.." elements from tail.
2137 if (p[len-1] == '/') {
2141 if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
2145 if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
2156 /* Convert '//' --> '/' */
2158 else if (p[1] == '.' && p[2] == '/')
2159 /* Convert '/./' --> '/' */
2161 else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
2162 /* Convert 'dir/dir1/../dir2/'
2166 while (rp >= dirname) {
2175 strcpy(dirname, p+4);
2186 if (archive_entry_filetype(file->entry) == AE_IFLNK) {
2188 /* Convert symlink name too. */
2189 if (archive_entry_symlink_l(file->entry, &pp, &len2,
2191 if (errno == ENOMEM) {
2192 archive_set_error(&a->archive, ENOMEM,
2193 "Can't allocate memory for Linkname");
2194 return (ARCHIVE_FATAL);
2196 archive_set_error(&a->archive,
2197 ARCHIVE_ERRNO_FILE_FORMAT,
2198 "Can't translate symlink '%s' to UTF-8",
2199 archive_entry_symlink(file->entry));
2202 archive_strncpy(&(file->symlink), pp, len2);
2203 cleanup_backslash(file->symlink.s, file->symlink.length);
2206 * - Count up directory elements.
2207 * - Find out the position which points the last position of
2208 * path separator('/').
2211 for (; *p != '\0'; p++)
2214 if (slash == NULL) {
2215 /* The pathname doesn't have a parent directory. */
2216 file->parentdir.length = len;
2217 archive_string_copy(&(file->basename), &(file->parentdir));
2218 archive_string_empty(&(file->parentdir));
2219 *file->parentdir.s = '\0';
2223 /* Make a basename from dirname and slash */
2225 file->parentdir.length = slash - dirname;
2226 archive_strcpy(&(file->basename), slash + 1);
2231 get_path_component(char *name, int n, const char *fn)
2236 p = strchr(fn, '/');
2238 if ((l = strlen(fn)) == 0)
2244 memcpy(name, fn, l);
2251 * Add a new entry into the tree.
2254 file_tree(struct archive_write *a, struct file **filepp)
2256 #if defined(_WIN32) && !defined(__CYGWIN__)
2257 char name[_MAX_FNAME];/* Included null terminator size. */
2258 #elif defined(NAME_MAX) && NAME_MAX >= 255
2259 char name[NAME_MAX+1];
2263 struct xar *xar = (struct xar *)a->format_data;
2264 struct file *dent, *file, *np;
2265 struct archive_entry *ent;
2271 if (file->parentdir.length > 0)
2272 fn = p = file->parentdir.s;
2277 * If the path of the parent directory of `file' entry is
2278 * the same as the path of `cur_dirent', add isoent to
2281 if (archive_strlen(&(xar->cur_dirstr))
2282 == archive_strlen(&(file->parentdir)) &&
2283 strcmp(xar->cur_dirstr.s, fn) == 0) {
2284 if (!file_add_child_tail(xar->cur_dirent, file)) {
2285 np = (struct file *)__archive_rb_tree_find_node(
2286 &(xar->cur_dirent->rbtree),
2290 return (ARCHIVE_OK);
2294 l = get_path_component(name, sizeof(name), fn);
2300 archive_set_error(&a->archive,
2302 "A name buffer is too small");
2305 return (ARCHIVE_FATAL);
2308 np = file_find_child(dent, name);
2309 if (np == NULL || fn[0] == '\0')
2312 /* Find next subdirectory. */
2314 /* NOT Directory! */
2315 archive_set_error(&a->archive,
2317 "`%s' is not directory, we cannot insert `%s' ",
2318 archive_entry_pathname(np->entry),
2319 archive_entry_pathname(file->entry));
2322 return (ARCHIVE_FAILED);
2331 * Create virtual parent directories.
2333 while (fn[0] != '\0') {
2335 struct archive_string as;
2337 archive_string_init(&as);
2338 archive_strncat(&as, p, fn - p + l);
2339 if (as.s[as.length-1] == '/') {
2340 as.s[as.length-1] = '\0';
2343 vp = file_create_virtual_dir(a, xar, as.s);
2345 archive_string_free(&as);
2346 archive_set_error(&a->archive, ENOMEM,
2347 "Can't allocate memory");
2350 return (ARCHIVE_FATAL);
2352 archive_string_free(&as);
2353 if (file_gen_utility_names(a, vp) <= ARCHIVE_FAILED)
2354 return (ARCHIVE_FATAL);
2355 file_add_child_tail(dent, vp);
2356 file_register(xar, vp);
2362 l = get_path_component(name, sizeof(name), fn);
2364 archive_string_free(&as);
2365 archive_set_error(&a->archive,
2367 "A name buffer is too small");
2370 return (ARCHIVE_FATAL);
2375 /* Found out the parent directory where isoent can be
2377 xar->cur_dirent = dent;
2378 archive_string_empty(&(xar->cur_dirstr));
2379 archive_string_ensure(&(xar->cur_dirstr),
2380 archive_strlen(&(dent->parentdir)) +
2381 archive_strlen(&(dent->basename)) + 2);
2382 if (archive_strlen(&(dent->parentdir)) +
2383 archive_strlen(&(dent->basename)) == 0)
2384 xar->cur_dirstr.s[0] = 0;
2386 if (archive_strlen(&(dent->parentdir)) > 0) {
2387 archive_string_copy(&(xar->cur_dirstr),
2388 &(dent->parentdir));
2389 archive_strappend_char(&(xar->cur_dirstr), '/');
2391 archive_string_concat(&(xar->cur_dirstr),
2395 if (!file_add_child_tail(dent, file)) {
2396 np = (struct file *)__archive_rb_tree_find_node(
2397 &(dent->rbtree), file->basename.s);
2400 return (ARCHIVE_OK);
2405 * We have already has the entry the filename of which is
2408 if (archive_entry_filetype(np->entry) !=
2409 archive_entry_filetype(file->entry)) {
2410 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2411 "Found duplicate entries `%s' and its file type is "
2413 archive_entry_pathname(np->entry));
2416 return (ARCHIVE_FAILED);
2421 np->entry = file->entry;
2427 return (ARCHIVE_OK);
2431 file_register(struct xar *xar, struct file *file)
2433 file->id = xar->file_idx++;
2435 *xar->file_list.last = file;
2436 xar->file_list.last = &(file->next);
2440 file_init_register(struct xar *xar)
2442 xar->file_list.first = NULL;
2443 xar->file_list.last = &(xar->file_list.first);
2447 file_free_register(struct xar *xar)
2449 struct file *file, *file_next;
2451 file = xar->file_list.first;
2452 while (file != NULL) {
2453 file_next = file->next;
2460 * Register entry to get a hardlink target.
2463 file_register_hardlink(struct archive_write *a, struct file *file)
2465 struct xar *xar = (struct xar *)a->format_data;
2466 struct hardlink *hl;
2467 const char *pathname;
2469 archive_entry_set_nlink(file->entry, 1);
2470 pathname = archive_entry_hardlink(file->entry);
2471 if (pathname == NULL) {
2472 /* This `file` is a hardlink target. */
2473 hl = malloc(sizeof(*hl));
2475 archive_set_error(&a->archive, ENOMEM,
2476 "Can't allocate memory");
2477 return (ARCHIVE_FATAL);
2480 /* A hardlink target must be the first position. */
2481 file->hlnext = NULL;
2482 hl->file_list.first = file;
2483 hl->file_list.last = &(file->hlnext);
2484 __archive_rb_tree_insert_node(&(xar->hardlink_rbtree),
2485 (struct archive_rb_node *)hl);
2487 hl = (struct hardlink *)__archive_rb_tree_find_node(
2488 &(xar->hardlink_rbtree), pathname);
2490 /* Insert `file` entry into the tail. */
2491 file->hlnext = NULL;
2492 *hl->file_list.last = file;
2493 hl->file_list.last = &(file->hlnext);
2496 archive_entry_unset_size(file->entry);
2499 return (ARCHIVE_OK);
2503 * Hardlinked files have to have the same location of extent.
2504 * We have to find out hardlink target entries for entries which
2505 * have a hardlink target name.
2508 file_connect_hardlink_files(struct xar *xar)
2510 struct archive_rb_node *n;
2511 struct hardlink *hl;
2512 struct file *target, *nf;
2514 ARCHIVE_RB_TREE_FOREACH(n, &(xar->hardlink_rbtree)) {
2515 hl = (struct hardlink *)n;
2517 /* The first entry must be a hardlink target. */
2518 target = hl->file_list.first;
2519 archive_entry_set_nlink(target->entry, hl->nlink);
2521 /* It means this file is a hardlink
2523 target->hardlink_target = target;
2524 for (nf = target->hlnext;
2525 nf != NULL; nf = nf->hlnext) {
2526 nf->hardlink_target = target;
2527 archive_entry_set_nlink(nf->entry, hl->nlink);
2533 file_hd_cmp_node(const struct archive_rb_node *n1,
2534 const struct archive_rb_node *n2)
2536 const struct hardlink *h1 = (const struct hardlink *)n1;
2537 const struct hardlink *h2 = (const struct hardlink *)n2;
2539 return (strcmp(archive_entry_pathname(h1->file_list.first->entry),
2540 archive_entry_pathname(h2->file_list.first->entry)));
2544 file_hd_cmp_key(const struct archive_rb_node *n, const void *key)
2546 const struct hardlink *h = (const struct hardlink *)n;
2548 return (strcmp(archive_entry_pathname(h->file_list.first->entry),
2549 (const char *)key));
2554 file_init_hardlinks(struct xar *xar)
2556 static const struct archive_rb_tree_ops rb_ops = {
2557 file_hd_cmp_node, file_hd_cmp_key,
2560 __archive_rb_tree_init(&(xar->hardlink_rbtree), &rb_ops);
2564 file_free_hardlinks(struct xar *xar)
2566 struct archive_rb_node *n, *tmp;
2568 ARCHIVE_RB_TREE_FOREACH_SAFE(n, &(xar->hardlink_rbtree), tmp) {
2569 __archive_rb_tree_remove_node(&(xar->hardlink_rbtree), n);
2575 checksum_init(struct chksumwork *sumwrk, enum sumalg sum_alg)
2577 sumwrk->alg = sum_alg;
2582 archive_sha1_init(&(sumwrk->sha1ctx));
2585 archive_md5_init(&(sumwrk->md5ctx));
2591 checksum_update(struct chksumwork *sumwrk, const void *buff, size_t size)
2594 switch (sumwrk->alg) {
2598 archive_sha1_update(&(sumwrk->sha1ctx), buff, size);
2601 archive_md5_update(&(sumwrk->md5ctx), buff, size);
2607 checksum_final(struct chksumwork *sumwrk, struct chksumval *sumval)
2610 switch (sumwrk->alg) {
2615 archive_sha1_final(&(sumwrk->sha1ctx), sumval->val);
2616 sumval->len = SHA1_SIZE;
2619 archive_md5_final(&(sumwrk->md5ctx), sumval->val);
2620 sumval->len = MD5_SIZE;
2623 sumval->alg = sumwrk->alg;
2626 #if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
2628 compression_unsupported_encoder(struct archive *a,
2629 struct la_zstream *lastrm, const char *name)
2632 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2633 "%s compression not supported on this platform", name);
2635 lastrm->real_stream = NULL;
2636 return (ARCHIVE_FAILED);
2641 compression_init_encoder_gzip(struct archive *a,
2642 struct la_zstream *lastrm, int level, int withheader)
2647 compression_end(a, lastrm);
2648 strm = calloc(1, sizeof(*strm));
2650 archive_set_error(a, ENOMEM,
2651 "Can't allocate memory for gzip stream");
2652 return (ARCHIVE_FATAL);
2654 /* zlib.h is not const-correct, so we need this one bit
2655 * of ugly hackery to convert a const * pointer to
2656 * a non-const pointer. */
2657 strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
2658 strm->avail_in = lastrm->avail_in;
2659 strm->total_in = (uLong)lastrm->total_in;
2660 strm->next_out = lastrm->next_out;
2661 strm->avail_out = lastrm->avail_out;
2662 strm->total_out = (uLong)lastrm->total_out;
2663 if (deflateInit2(strm, level, Z_DEFLATED,
2664 (withheader)?15:-15,
2665 8, Z_DEFAULT_STRATEGY) != Z_OK) {
2667 lastrm->real_stream = NULL;
2668 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2669 "Internal error initializing compression library");
2670 return (ARCHIVE_FATAL);
2672 lastrm->real_stream = strm;
2674 lastrm->code = compression_code_gzip;
2675 lastrm->end = compression_end_gzip;
2676 return (ARCHIVE_OK);
2680 compression_code_gzip(struct archive *a,
2681 struct la_zstream *lastrm, enum la_zaction action)
2686 strm = (z_stream *)lastrm->real_stream;
2687 /* zlib.h is not const-correct, so we need this one bit
2688 * of ugly hackery to convert a const * pointer to
2689 * a non-const pointer. */
2690 strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
2691 strm->avail_in = lastrm->avail_in;
2692 strm->total_in = (uLong)lastrm->total_in;
2693 strm->next_out = lastrm->next_out;
2694 strm->avail_out = lastrm->avail_out;
2695 strm->total_out = (uLong)lastrm->total_out;
2697 (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH);
2698 lastrm->next_in = strm->next_in;
2699 lastrm->avail_in = strm->avail_in;
2700 lastrm->total_in = strm->total_in;
2701 lastrm->next_out = strm->next_out;
2702 lastrm->avail_out = strm->avail_out;
2703 lastrm->total_out = strm->total_out;
2706 return (ARCHIVE_OK);
2708 return (ARCHIVE_EOF);
2710 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2711 "GZip compression failed:"
2712 " deflate() call returned status %d", r);
2713 return (ARCHIVE_FATAL);
2718 compression_end_gzip(struct archive *a, struct la_zstream *lastrm)
2723 strm = (z_stream *)lastrm->real_stream;
2724 r = deflateEnd(strm);
2726 lastrm->real_stream = NULL;
2729 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2730 "Failed to clean up compressor");
2731 return (ARCHIVE_FATAL);
2733 return (ARCHIVE_OK);
2736 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
2738 compression_init_encoder_bzip2(struct archive *a,
2739 struct la_zstream *lastrm, int level)
2744 compression_end(a, lastrm);
2745 strm = calloc(1, sizeof(*strm));
2747 archive_set_error(a, ENOMEM,
2748 "Can't allocate memory for bzip2 stream");
2749 return (ARCHIVE_FATAL);
2751 /* bzlib.h is not const-correct, so we need this one bit
2752 * of ugly hackery to convert a const * pointer to
2753 * a non-const pointer. */
2754 strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
2755 strm->avail_in = lastrm->avail_in;
2756 strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
2757 strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
2758 strm->next_out = (char *)lastrm->next_out;
2759 strm->avail_out = lastrm->avail_out;
2760 strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
2761 strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
2762 if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) {
2764 lastrm->real_stream = NULL;
2765 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2766 "Internal error initializing compression library");
2767 return (ARCHIVE_FATAL);
2769 lastrm->real_stream = strm;
2771 lastrm->code = compression_code_bzip2;
2772 lastrm->end = compression_end_bzip2;
2773 return (ARCHIVE_OK);
2777 compression_code_bzip2(struct archive *a,
2778 struct la_zstream *lastrm, enum la_zaction action)
2783 strm = (bz_stream *)lastrm->real_stream;
2784 /* bzlib.h is not const-correct, so we need this one bit
2785 * of ugly hackery to convert a const * pointer to
2786 * a non-const pointer. */
2787 strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
2788 strm->avail_in = lastrm->avail_in;
2789 strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
2790 strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
2791 strm->next_out = (char *)lastrm->next_out;
2792 strm->avail_out = lastrm->avail_out;
2793 strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
2794 strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
2795 r = BZ2_bzCompress(strm,
2796 (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN);
2797 lastrm->next_in = (const unsigned char *)strm->next_in;
2798 lastrm->avail_in = strm->avail_in;
2800 (((uint64_t)(uint32_t)strm->total_in_hi32) << 32)
2801 + (uint64_t)(uint32_t)strm->total_in_lo32;
2802 lastrm->next_out = (unsigned char *)strm->next_out;
2803 lastrm->avail_out = strm->avail_out;
2805 (((uint64_t)(uint32_t)strm->total_out_hi32) << 32)
2806 + (uint64_t)(uint32_t)strm->total_out_lo32;
2808 case BZ_RUN_OK: /* Non-finishing */
2809 case BZ_FINISH_OK: /* Finishing: There's more work to do */
2810 return (ARCHIVE_OK);
2811 case BZ_STREAM_END: /* Finishing: all done */
2812 /* Only occurs in finishing case */
2813 return (ARCHIVE_EOF);
2815 /* Any other return value indicates an error */
2816 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2817 "Bzip2 compression failed:"
2818 " BZ2_bzCompress() call returned status %d", r);
2819 return (ARCHIVE_FATAL);
2824 compression_end_bzip2(struct archive *a, struct la_zstream *lastrm)
2829 strm = (bz_stream *)lastrm->real_stream;
2830 r = BZ2_bzCompressEnd(strm);
2832 lastrm->real_stream = NULL;
2835 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2836 "Failed to clean up compressor");
2837 return (ARCHIVE_FATAL);
2839 return (ARCHIVE_OK);
2844 compression_init_encoder_bzip2(struct archive *a,
2845 struct la_zstream *lastrm, int level)
2848 (void) level; /* UNUSED */
2850 compression_end(a, lastrm);
2851 return (compression_unsupported_encoder(a, lastrm, "bzip2"));
2855 #if defined(HAVE_LZMA_H)
2857 compression_init_encoder_lzma(struct archive *a,
2858 struct la_zstream *lastrm, int level)
2860 static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
2862 lzma_options_lzma lzma_opt;
2866 compression_end(a, lastrm);
2867 if (lzma_lzma_preset(&lzma_opt, level)) {
2868 lastrm->real_stream = NULL;
2869 archive_set_error(a, ENOMEM,
2870 "Internal error initializing compression library");
2871 return (ARCHIVE_FATAL);
2873 strm = calloc(1, sizeof(*strm));
2875 archive_set_error(a, ENOMEM,
2876 "Can't allocate memory for lzma stream");
2877 return (ARCHIVE_FATAL);
2879 *strm = lzma_init_data;
2880 r = lzma_alone_encoder(strm, &lzma_opt);
2883 lastrm->real_stream = strm;
2885 lastrm->code = compression_code_lzma;
2886 lastrm->end = compression_end_lzma;
2889 case LZMA_MEM_ERROR:
2891 lastrm->real_stream = NULL;
2892 archive_set_error(a, ENOMEM,
2893 "Internal error initializing compression library: "
2894 "Cannot allocate memory");
2899 lastrm->real_stream = NULL;
2900 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2901 "Internal error initializing compression library: "
2902 "It's a bug in liblzma");
2910 compression_init_encoder_xz(struct archive *a,
2911 struct la_zstream *lastrm, int level, int threads)
2913 static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
2915 lzma_filter *lzmafilters;
2916 lzma_options_lzma lzma_opt;
2918 #ifdef HAVE_LZMA_STREAM_ENCODER_MT
2922 (void)threads; /* UNUSED (if multi-threaded LZMA library not avail) */
2925 compression_end(a, lastrm);
2926 strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2);
2928 archive_set_error(a, ENOMEM,
2929 "Can't allocate memory for xz stream");
2930 return (ARCHIVE_FATAL);
2932 lzmafilters = (lzma_filter *)(strm+1);
2935 if (lzma_lzma_preset(&lzma_opt, level)) {
2937 lastrm->real_stream = NULL;
2938 archive_set_error(a, ENOMEM,
2939 "Internal error initializing compression library");
2940 return (ARCHIVE_FATAL);
2942 lzmafilters[0].id = LZMA_FILTER_LZMA2;
2943 lzmafilters[0].options = &lzma_opt;
2944 lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
2946 *strm = lzma_init_data;
2947 #ifdef HAVE_LZMA_STREAM_ENCODER_MT
2949 memset(&mt_options, 0, sizeof(mt_options));
2950 mt_options.threads = threads;
2951 mt_options.timeout = 300;
2952 mt_options.filters = lzmafilters;
2953 mt_options.check = LZMA_CHECK_CRC64;
2954 r = lzma_stream_encoder_mt(strm, &mt_options);
2957 r = lzma_stream_encoder(strm, lzmafilters, LZMA_CHECK_CRC64);
2960 lastrm->real_stream = strm;
2962 lastrm->code = compression_code_lzma;
2963 lastrm->end = compression_end_lzma;
2966 case LZMA_MEM_ERROR:
2968 lastrm->real_stream = NULL;
2969 archive_set_error(a, ENOMEM,
2970 "Internal error initializing compression library: "
2971 "Cannot allocate memory");
2976 lastrm->real_stream = NULL;
2977 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2978 "Internal error initializing compression library: "
2979 "It's a bug in liblzma");
2987 compression_code_lzma(struct archive *a,
2988 struct la_zstream *lastrm, enum la_zaction action)
2993 strm = (lzma_stream *)lastrm->real_stream;
2994 strm->next_in = lastrm->next_in;
2995 strm->avail_in = lastrm->avail_in;
2996 strm->total_in = lastrm->total_in;
2997 strm->next_out = lastrm->next_out;
2998 strm->avail_out = lastrm->avail_out;
2999 strm->total_out = lastrm->total_out;
3001 (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN);
3002 lastrm->next_in = strm->next_in;
3003 lastrm->avail_in = strm->avail_in;
3004 lastrm->total_in = strm->total_in;
3005 lastrm->next_out = strm->next_out;
3006 lastrm->avail_out = strm->avail_out;
3007 lastrm->total_out = strm->total_out;
3010 /* Non-finishing case */
3011 return (ARCHIVE_OK);
3012 case LZMA_STREAM_END:
3013 /* This return can only occur in finishing case. */
3014 return (ARCHIVE_EOF);
3015 case LZMA_MEMLIMIT_ERROR:
3016 archive_set_error(a, ENOMEM,
3017 "lzma compression error:"
3018 " %ju MiB would have been needed",
3019 (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1)
3021 return (ARCHIVE_FATAL);
3023 /* Any other return value indicates an error */
3024 archive_set_error(a, ARCHIVE_ERRNO_MISC,
3025 "lzma compression failed:"
3026 " lzma_code() call returned status %d", r);
3027 return (ARCHIVE_FATAL);
3032 compression_end_lzma(struct archive *a, struct la_zstream *lastrm)
3036 (void)a; /* UNUSED */
3037 strm = (lzma_stream *)lastrm->real_stream;
3041 lastrm->real_stream = NULL;
3042 return (ARCHIVE_OK);
3046 compression_init_encoder_lzma(struct archive *a,
3047 struct la_zstream *lastrm, int level)
3050 (void) level; /* UNUSED */
3052 compression_end(a, lastrm);
3053 return (compression_unsupported_encoder(a, lastrm, "lzma"));
3056 compression_init_encoder_xz(struct archive *a,
3057 struct la_zstream *lastrm, int level, int threads)
3060 (void) level; /* UNUSED */
3061 (void) threads; /* UNUSED */
3063 compression_end(a, lastrm);
3064 return (compression_unsupported_encoder(a, lastrm, "xz"));
3069 xar_compression_init_encoder(struct archive_write *a)
3074 xar = (struct xar *)a->format_data;
3075 switch (xar->opt_compression) {
3077 r = compression_init_encoder_gzip(
3078 &(a->archive), &(xar->stream),
3079 xar->opt_compression_level, 1);
3082 r = compression_init_encoder_bzip2(
3083 &(a->archive), &(xar->stream),
3084 xar->opt_compression_level);
3087 r = compression_init_encoder_lzma(
3088 &(a->archive), &(xar->stream),
3089 xar->opt_compression_level);
3092 r = compression_init_encoder_xz(
3093 &(a->archive), &(xar->stream),
3094 xar->opt_compression_level, xar->opt_threads);
3100 if (r == ARCHIVE_OK) {
3101 xar->stream.total_in = 0;
3102 xar->stream.next_out = xar->wbuff;
3103 xar->stream.avail_out = sizeof(xar->wbuff);
3104 xar->stream.total_out = 0;
3111 compression_code(struct archive *a, struct la_zstream *lastrm,
3112 enum la_zaction action)
3115 return (lastrm->code(a, lastrm, action));
3116 return (ARCHIVE_OK);
3120 compression_end(struct archive *a, struct la_zstream *lastrm)
3123 return (lastrm->end(a, lastrm));
3124 return (ARCHIVE_OK);
3129 save_xattrs(struct archive_write *a, struct file *file)
3134 struct heap_data *heap;
3138 xar = (struct xar *)a->format_data;
3139 count = archive_entry_xattr_reset(file->entry);
3141 return (ARCHIVE_OK);
3143 archive_entry_xattr_next(file->entry,
3144 &name, &value, &size);
3145 checksum_init(&(xar->a_sumwrk), xar->opt_sumalg);
3146 checksum_init(&(xar->e_sumwrk), xar->opt_sumalg);
3148 heap = calloc(1, sizeof(*heap));
3150 archive_set_error(&a->archive, ENOMEM,
3151 "Can't allocate memory for xattr");
3152 return (ARCHIVE_FATAL);
3154 heap->id = file->ea_idx++;
3155 heap->temp_offset = xar->temp_offset;
3156 heap->size = size;/* save a extracted size */
3157 heap->compression = xar->opt_compression;
3158 /* Get a extracted sumcheck value. */
3159 checksum_update(&(xar->e_sumwrk), value, size);
3160 checksum_final(&(xar->e_sumwrk), &(heap->e_sum));
3163 * Not compression to xattr is simple way.
3165 if (heap->compression == NONE) {
3166 checksum_update(&(xar->a_sumwrk), value, size);
3167 checksum_final(&(xar->a_sumwrk), &(heap->a_sum));
3168 if (write_to_temp(a, value, size)
3171 return (ARCHIVE_FATAL);
3173 heap->length = size;
3174 /* Add heap to the tail of file->xattr. */
3176 *file->xattr.last = heap;
3177 file->xattr.last = &(heap->next);
3183 * Init compression library.
3185 r = xar_compression_init_encoder(a);
3186 if (r != ARCHIVE_OK) {
3188 return (ARCHIVE_FATAL);
3191 xar->stream.next_in = (const unsigned char *)value;
3192 xar->stream.avail_in = size;
3194 r = compression_code(&(a->archive),
3195 &(xar->stream), ARCHIVE_Z_FINISH);
3196 if (r != ARCHIVE_OK && r != ARCHIVE_EOF) {
3198 return (ARCHIVE_FATAL);
3200 size = sizeof(xar->wbuff) - xar->stream.avail_out;
3201 checksum_update(&(xar->a_sumwrk),
3203 if (write_to_temp(a, xar->wbuff, size)
3205 return (ARCHIVE_FATAL);
3206 if (r == ARCHIVE_OK) {
3207 xar->stream.next_out = xar->wbuff;
3208 xar->stream.avail_out = sizeof(xar->wbuff);
3210 checksum_final(&(xar->a_sumwrk),
3212 heap->length = xar->stream.total_out;
3213 /* Add heap to the tail of file->xattr. */
3215 *file->xattr.last = heap;
3216 file->xattr.last = &(heap->next);
3220 /* Clean up compression library. */
3221 r = compression_end(&(a->archive), &(xar->stream));
3222 if (r != ARCHIVE_OK)
3223 return (ARCHIVE_FATAL);
3225 return (ARCHIVE_OK);
3229 getalgsize(enum sumalg sumalg)
3243 getalgname(enum sumalg sumalg)
3256 #endif /* Support xar format */