2 * Copyright (c) 2010-2011 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>
54 #include "archive_crypto_private.h"
55 #include "archive_endian.h"
56 #include "archive_entry.h"
57 #include "archive_entry_locale.h"
58 #include "archive_private.h"
59 #include "archive_rb.h"
60 #include "archive_string.h"
61 #include "archive_write_private.h"
64 * Differences to xar utility.
65 * - Subdocument is not supported yet.
66 * - ACL is not supported yet.
67 * - When writing an XML element <link type="<file-type>">, <file-type>
68 * which is a file type a symbolic link is referencing is always marked
69 * as "broken". Xar utility uses stat(2) to get the file type, but, in
70 * libarcive format writer, we should not use it; if it is needed, we
71 * should get about it at archive_read_disk.c.
72 * - It is possible to appear both <flags> and <ext2> elements.
73 * Xar utility generates <flags> on BSD platform and <ext2> on Linux
78 #if !(defined(HAVE_LIBXML_XMLWRITER_H) && defined(LIBXML_VERSION) &&\
79 LIBXML_VERSION >= 20703) ||\
80 !defined(HAVE_ZLIB_H) || \
81 !defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1)
83 * xar needs several external libraries.
85 * o openssl or MD5/SHA1 hash function
91 archive_write_set_format_xar(struct archive *_a)
93 struct archive_write *a = (struct archive_write *)_a;
95 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
96 "Xar not supported on this platform");
97 return (ARCHIVE_WARN);
100 #else /* Support xar format */
102 /*#define DEBUG_PRINT_TOC 1 */
104 #define HEADER_MAGIC 0x78617221
105 #define HEADER_SIZE 28
106 #define HEADER_VERSION 1
116 #define MAX_SUM_SIZE 20
117 #define MD5_NAME "md5"
118 #define SHA1_NAME "sha1"
130 #ifdef ARCHIVE_HAS_MD5
131 archive_md5_ctx md5ctx;
133 #ifdef ARCHIVE_HAS_SHA1
134 archive_sha1_ctx sha1ctx;
147 const unsigned char *next_in;
151 unsigned char *next_out;
157 int (*code) (struct archive *a,
158 struct la_zstream *lastrm,
159 enum la_zaction action);
160 int (*end)(struct archive *a,
161 struct la_zstream *lastrm);
167 unsigned char val[MAX_SUM_SIZE];
172 struct heap_data *next;
173 uint64_t temp_offset;
174 uint64_t length; /* archived size. */
175 uint64_t size; /* extracted size. */
176 enum enctype compression;
177 struct chksumval a_sum; /* archived checksum. */
178 struct chksumval e_sum; /* extracted checksum. */
182 struct archive_rb_node rbnode;
185 struct archive_entry *entry;
187 struct archive_rb_tree rbtree;
191 /* For hardlinked files.
192 * Use only when archive_entry_nlink() > 1 */
193 struct file *hardlink_target;
194 struct file *parent; /* parent directory entry */
196 * To manage sub directory files.
197 * We use 'chnext' a menber of struct file to chain.
204 /* For making a directory tree. */
205 struct archive_string parentdir;
206 struct archive_string basename;
207 struct archive_string symlink;
211 struct heap_data *first;
212 struct heap_data **last;
214 struct heap_data data;
215 struct archive_string script;
222 struct archive_rb_node rbnode;
232 uint64_t temp_offset;
236 struct file *cur_dirent;
237 struct archive_string cur_dirstr;
238 struct file *cur_file;
239 uint64_t bytes_remaining;
240 struct archive_string tstr;
241 struct archive_string vstr;
243 enum sumalg opt_toc_sumalg;
244 enum sumalg opt_sumalg;
245 enum enctype opt_compression;
246 int opt_compression_level;
248 struct chksumwork a_sumwrk; /* archived checksum. */
249 struct chksumwork e_sumwrk; /* extracted checksum. */
250 struct la_zstream stream;
251 struct archive_string_conv *sconv;
253 * Compressed data buffer.
255 unsigned char wbuff[1024 * 64];
256 size_t wbuff_remaining;
258 struct heap_data toc;
260 * The list of all file entries is used to manage struct file
262 * We use 'next' a menber of struct file to chain.
269 * The list of hard-linked file entries.
270 * We use 'hlnext' a menber of struct file to chain.
272 struct archive_rb_tree hardlink_rbtree;
275 static int xar_options(struct archive_write *,
276 const char *, const char *);
277 static int xar_write_header(struct archive_write *,
278 struct archive_entry *);
279 static ssize_t xar_write_data(struct archive_write *,
280 const void *, size_t);
281 static int xar_finish_entry(struct archive_write *);
282 static int xar_close(struct archive_write *);
283 static int xar_free(struct archive_write *);
285 static struct file *file_new(struct archive_write *a, struct archive_entry *);
286 static void file_free(struct file *);
287 static struct file *file_create_virtual_dir(struct archive_write *a, struct xar *,
289 static int file_add_child_tail(struct file *, struct file *);
290 static struct file *file_find_child(struct file *, const char *);
291 static int file_gen_utility_names(struct archive_write *,
293 static int get_path_component(char *, int, const char *);
294 static int file_tree(struct archive_write *, struct file **);
295 static void file_register(struct xar *, struct file *);
296 static void file_init_register(struct xar *);
297 static void file_free_register(struct xar *);
298 static int file_register_hardlink(struct archive_write *,
300 static void file_connect_hardlink_files(struct xar *);
301 static void file_init_hardlinks(struct xar *);
302 static void file_free_hardlinks(struct xar *);
304 static void checksum_init(struct chksumwork *, enum sumalg);
305 static void checksum_update(struct chksumwork *, const void *, size_t);
306 static void checksum_final(struct chksumwork *, struct chksumval *);
307 static int compression_init_encoder_gzip(struct archive *,
308 struct la_zstream *, int, int);
309 static int compression_code_gzip(struct archive *,
310 struct la_zstream *, enum la_zaction);
311 static int compression_end_gzip(struct archive *, struct la_zstream *);
312 static int compression_init_encoder_bzip2(struct archive *,
313 struct la_zstream *, int);
314 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
315 static int compression_code_bzip2(struct archive *,
316 struct la_zstream *, enum la_zaction);
317 static int compression_end_bzip2(struct archive *, struct la_zstream *);
319 static int compression_init_encoder_lzma(struct archive *,
320 struct la_zstream *, int);
321 static int compression_init_encoder_xz(struct archive *,
322 struct la_zstream *, int);
323 #if defined(HAVE_LZMA_H)
324 static int compression_code_lzma(struct archive *,
325 struct la_zstream *, enum la_zaction);
326 static int compression_end_lzma(struct archive *, struct la_zstream *);
328 static int xar_compression_init_encoder(struct archive_write *);
329 static int compression_code(struct archive *,
330 struct la_zstream *, enum la_zaction);
331 static int compression_end(struct archive *,
332 struct la_zstream *);
333 static int save_xattrs(struct archive_write *, struct file *);
334 static int getalgsize(enum sumalg);
335 static const char *getalgname(enum sumalg);
338 archive_write_set_format_xar(struct archive *_a)
340 struct archive_write *a = (struct archive_write *)_a;
343 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
344 ARCHIVE_STATE_NEW, "archive_write_set_format_xar");
346 /* If another format was already registered, unregister it. */
347 if (a->format_free != NULL)
350 xar = calloc(1, sizeof(*xar));
352 archive_set_error(&a->archive, ENOMEM,
353 "Can't allocate xar data");
354 return (ARCHIVE_FATAL);
357 file_init_register(xar);
358 file_init_hardlinks(xar);
359 archive_string_init(&(xar->tstr));
360 archive_string_init(&(xar->vstr));
363 * Create the root directory.
365 xar->root = file_create_virtual_dir(a, xar, "");
366 if (xar->root == NULL) {
368 archive_set_error(&a->archive, ENOMEM,
369 "Can't allocate xar data");
370 return (ARCHIVE_FATAL);
372 xar->root->parent = xar->root;
373 file_register(xar, xar->root);
374 xar->cur_dirent = xar->root;
375 archive_string_init(&(xar->cur_dirstr));
376 archive_string_ensure(&(xar->cur_dirstr), 1);
377 xar->cur_dirstr.s[0] = 0;
382 /* Set default checksum type. */
383 xar->opt_toc_sumalg = CKSUM_SHA1;
384 xar->opt_sumalg = CKSUM_SHA1;
385 /* Set default compression type and level. */
386 xar->opt_compression = GZIP;
387 xar->opt_compression_level = 6;
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, "sha1") == 0)
415 xar->opt_sumalg = CKSUM_SHA1;
416 else if (strcmp(value, "md5") == 0)
417 xar->opt_sumalg = CKSUM_MD5;
419 archive_set_error(&(a->archive),
421 "Unkonwn checksum name: `%s'",
423 return (ARCHIVE_FAILED);
427 if (strcmp(key, "compression") == 0) {
428 const char *name = NULL;
431 xar->opt_compression = NONE;
432 else if (strcmp(value, "gzip") == 0)
433 xar->opt_compression = GZIP;
434 else if (strcmp(value, "bzip2") == 0)
435 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
436 xar->opt_compression = BZIP2;
440 else if (strcmp(value, "lzma") == 0)
442 xar->opt_compression = LZMA;
446 else if (strcmp(value, "xz") == 0)
448 xar->opt_compression = XZ;
453 archive_set_error(&(a->archive),
455 "Unkonwn compression name: `%s'",
457 return (ARCHIVE_FAILED);
460 archive_set_error(&(a->archive),
462 "`%s' compression not supported "
465 return (ARCHIVE_FAILED);
469 if (strcmp(key, "compression-level") == 0) {
471 !(value[0] >= '0' && value[0] <= '9') ||
473 archive_set_error(&(a->archive),
475 "Illeagal value `%s'",
477 return (ARCHIVE_FAILED);
479 xar->opt_compression_level = value[0] - '0';
482 if (strcmp(key, "toc-checksum") == 0) {
484 xar->opt_toc_sumalg = CKSUM_NONE;
485 else if (strcmp(value, "sha1") == 0)
486 xar->opt_toc_sumalg = CKSUM_SHA1;
487 else if (strcmp(value, "md5") == 0)
488 xar->opt_toc_sumalg = CKSUM_MD5;
490 archive_set_error(&(a->archive),
492 "Unkonwn checksum name: `%s'",
494 return (ARCHIVE_FAILED);
499 return (ARCHIVE_FAILED);
503 xar_write_header(struct archive_write *a, struct archive_entry *entry)
507 struct archive_entry *file_entry;
510 xar = (struct xar *)a->format_data;
511 xar->cur_file = NULL;
512 xar->bytes_remaining = 0;
514 if (xar->sconv == NULL) {
515 xar->sconv = archive_string_conversion_to_charset(
516 &a->archive, "UTF-8", 1);
517 if (xar->sconv == NULL)
518 return (ARCHIVE_FATAL);
521 file = file_new(a, entry);
523 archive_set_error(&a->archive, ENOMEM,
524 "Can't allocate data");
525 return (ARCHIVE_FATAL);
527 r2 = file_gen_utility_names(a, file);
528 if (r2 < ARCHIVE_WARN)
532 * Ignore a path which looks like the top of directory name
533 * since we have already made the root directory of an Xar archive.
535 if (archive_strlen(&(file->parentdir)) == 0 &&
536 archive_strlen(&(file->basename)) == 0) {
541 /* Add entry into tree */
542 file_entry = file->entry;
543 r = file_tree(a, &file);
546 /* There is the same file in tree and
547 * the current file is older than the file in tree.
548 * So we don't need the current file data anymore. */
549 if (file->entry != file_entry)
552 file_register(xar, file);
554 /* A virtual file, which is a directory, does not have
555 * any contents and we won't store it into a archive
556 * file other than its name. */
561 * Prepare to save the contents of the file.
563 if (xar->temp_fd == -1) {
565 xar->temp_offset = 0;
566 xar->temp_fd = __archive_mktemp(NULL);
567 if (xar->temp_fd < 0) {
568 archive_set_error(&a->archive, errno,
569 "Couldn't create temporary file");
570 return (ARCHIVE_FATAL);
572 algsize = getalgsize(xar->opt_toc_sumalg);
574 if (lseek(xar->temp_fd, algsize, SEEK_SET) < 0) {
575 archive_set_error(&(a->archive), errno,
577 return (ARCHIVE_FATAL);
579 xar->temp_offset = algsize;
583 if (archive_entry_hardlink(file->entry) == NULL) {
584 r = save_xattrs(a, file);
586 return (ARCHIVE_FATAL);
589 /* Non regular files contents are unneeded to be saved to
590 * a temporary file. */
591 if (archive_entry_filetype(file->entry) != AE_IFREG)
595 * Set the current file to cur_file to read its contents.
597 xar->cur_file = file;
599 if (archive_entry_nlink(file->entry) > 1) {
600 r = file_register_hardlink(a, file);
603 if (archive_entry_hardlink(file->entry) != NULL) {
604 archive_entry_unset_size(file->entry);
609 /* Save a offset of current file in temporary file. */
610 file->data.temp_offset = xar->temp_offset;
611 file->data.size = archive_entry_size(file->entry);
612 file->data.compression = xar->opt_compression;
613 xar->bytes_remaining = archive_entry_size(file->entry);
614 checksum_init(&(xar->a_sumwrk), xar->opt_sumalg);
615 checksum_init(&(xar->e_sumwrk), xar->opt_sumalg);
616 r = xar_compression_init_encoder(a);
625 write_to_temp(struct archive_write *a, const void *buff, size_t s)
631 xar = (struct xar *)a->format_data;
632 p = (unsigned char *)buff;
634 ws = write(xar->temp_fd, p, s);
636 archive_set_error(&(a->archive), errno,
637 "fwrite function failed");
638 return (ARCHIVE_FATAL);
642 xar->temp_offset += ws;
648 xar_write_data(struct archive_write *a, const void *buff, size_t s)
655 xar = (struct xar *)a->format_data;
657 if (s > xar->bytes_remaining)
658 s = xar->bytes_remaining;
659 if (s == 0 || xar->cur_file == NULL)
661 if (xar->cur_file->data.compression == NONE) {
662 checksum_update(&(xar->e_sumwrk), buff, s);
663 checksum_update(&(xar->a_sumwrk), buff, s);
666 xar->stream.next_in = (const unsigned char *)buff;
667 xar->stream.avail_in = s;
668 if (xar->bytes_remaining > s)
671 run = ARCHIVE_Z_FINISH;
672 /* Compress file data. */
673 r = compression_code(&(a->archive), &(xar->stream), run);
674 if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
675 return (ARCHIVE_FATAL);
676 rsize = s - xar->stream.avail_in;
677 checksum_update(&(xar->e_sumwrk), buff, rsize);
678 size = sizeof(xar->wbuff) - xar->stream.avail_out;
679 checksum_update(&(xar->a_sumwrk), xar->wbuff, size);
681 #if !defined(_WIN32) || defined(__CYGWIN__)
682 if (xar->bytes_remaining ==
683 archive_entry_size(xar->cur_file->entry)) {
685 * Get the path of a shell script if so.
687 const unsigned char *b = (const unsigned char *)buff;
689 archive_string_empty(&(xar->cur_file->script));
690 if (rsize > 2 && b[0] == '#' && b[1] == '!') {
697 if ((rsize - off) > PATH_MAX)
698 end = off + PATH_MAX;
702 /* Find the end of a script path. */
703 for (i = off; i < end && b[i] != '\0' &&
704 b[i] != '\n' && b[i] != '\r' &&
705 b[i] != ' ' && b[i] != '\t'; i++)
707 archive_strncpy(&(xar->cur_file->script), b + off,
713 if (xar->cur_file->data.compression == NONE) {
714 if (write_to_temp(a, buff, size) != ARCHIVE_OK)
715 return (ARCHIVE_FATAL);
717 if (write_to_temp(a, xar->wbuff, size) != ARCHIVE_OK)
718 return (ARCHIVE_FATAL);
720 xar->bytes_remaining -= rsize;
721 xar->cur_file->data.length += size;
727 xar_finish_entry(struct archive_write *a)
734 xar = (struct xar *)a->format_data;
735 if (xar->cur_file == NULL)
738 while (xar->bytes_remaining > 0) {
739 s = xar->bytes_remaining;
740 if (s > a->null_length)
742 w = xar_write_data(a, a->nulls, s);
744 xar->bytes_remaining -= w;
748 file = xar->cur_file;
749 checksum_final(&(xar->e_sumwrk), &(file->data.e_sum));
750 checksum_final(&(xar->a_sumwrk), &(file->data.a_sum));
751 xar->cur_file = NULL;
757 xmlwrite_string_attr(struct archive_write *a, xmlTextWriterPtr writer,
758 const char *key, const char *value,
759 const char *attrkey, const char *attrvalue)
763 r = xmlTextWriterStartElement(writer, BAD_CAST(key));
765 archive_set_error(&a->archive,
767 "xmlTextWriterStartElement() failed: %d", r);
768 return (ARCHIVE_FATAL);
770 if (attrkey != NULL && attrvalue != NULL) {
771 r = xmlTextWriterWriteAttribute(writer,
772 BAD_CAST(attrkey), BAD_CAST(attrvalue));
774 archive_set_error(&a->archive,
776 "xmlTextWriterWriteAttribute() failed: %d", r);
777 return (ARCHIVE_FATAL);
781 r = xmlTextWriterWriteString(writer, BAD_CAST(value));
783 archive_set_error(&a->archive,
785 "xmlTextWriterWriteString() failed: %d", r);
786 return (ARCHIVE_FATAL);
789 r = xmlTextWriterEndElement(writer);
791 archive_set_error(&a->archive,
793 "xmlTextWriterEndElement() failed: %d", r);
794 return (ARCHIVE_FATAL);
800 xmlwrite_string(struct archive_write *a, xmlTextWriterPtr writer,
801 const char *key, const char *value)
808 r = xmlTextWriterStartElement(writer, BAD_CAST(key));
810 archive_set_error(&a->archive,
812 "xmlTextWriterStartElement() failed: %d", r);
813 return (ARCHIVE_FATAL);
816 r = xmlTextWriterWriteString(writer, BAD_CAST(value));
818 archive_set_error(&a->archive,
820 "xmlTextWriterWriteString() failed: %d", r);
821 return (ARCHIVE_FATAL);
824 r = xmlTextWriterEndElement(writer);
826 archive_set_error(&a->archive,
828 "xmlTextWriterEndElement() failed: %d", r);
829 return (ARCHIVE_FATAL);
835 xmlwrite_fstring(struct archive_write *a, xmlTextWriterPtr writer,
836 const char *key, const char *fmt, ...)
841 xar = (struct xar *)a->format_data;
843 archive_string_empty(&xar->vstr);
844 archive_string_vsprintf(&xar->vstr, fmt, ap);
846 return (xmlwrite_string(a, writer, key, xar->vstr.s));
850 xmlwrite_time(struct archive_write *a, xmlTextWriterPtr writer,
851 const char *key, time_t t, int z)
856 #if defined(HAVE_GMTIME_R)
858 #elif defined(HAVE__GMTIME64_S)
859 _gmtime64_s(&tm, &t);
861 memcpy(&tm, gmtime(&t), sizeof(tm));
863 memset(×tr, 0, sizeof(timestr));
864 /* Do not use %F and %T for portability. */
865 strftime(timestr, sizeof(timestr), "%Y-%m-%dT%H:%M:%S", &tm);
867 strcat(timestr, "Z");
868 return (xmlwrite_string(a, writer, key, timestr));
872 xmlwrite_mode(struct archive_write *a, xmlTextWriterPtr writer,
873 const char *key, mode_t mode)
878 ms[1] = '0' + ((mode >> 6) & 07);
879 ms[2] = '0' + ((mode >> 3) & 07);
880 ms[3] = '0' + (mode & 07);
883 return (xmlwrite_string(a, writer, key, ms));
887 xmlwrite_sum(struct archive_write *a, xmlTextWriterPtr writer,
888 const char *key, struct chksumval *sum)
892 char buff[MAX_SUM_SIZE*2 + 1];
898 algname = getalgname(sum->alg);
899 algsize = getalgsize(sum->alg);
900 if (algname != NULL) {
901 const char *hex = "0123456789abcdef";
904 for (i = 0; i < algsize; i++) {
905 *p++ = hex[(*s >> 4)];
906 *p++ = hex[(*s & 0x0f)];
910 r = xmlwrite_string_attr(a, writer,
914 return (ARCHIVE_FATAL);
921 xmlwrite_heap(struct archive_write *a, xmlTextWriterPtr writer,
922 struct heap_data *heap)
927 r = xmlwrite_fstring(a, writer, "length", "%ju", heap->length);
929 return (ARCHIVE_FATAL);
930 r = xmlwrite_fstring(a, writer, "offset", "%ju", heap->temp_offset);
932 return (ARCHIVE_FATAL);
933 r = xmlwrite_fstring(a, writer, "size", "%ju", heap->size);
935 return (ARCHIVE_FATAL);
936 switch (heap->compression) {
938 encname = "application/x-gzip"; break;
940 encname = "application/x-bzip2"; break;
942 encname = "application/x-lzma"; break;
944 encname = "application/x-xz"; break;
946 encname = "application/octet-stream"; break;
948 r = xmlwrite_string_attr(a, writer, "encoding", NULL,
951 return (ARCHIVE_FATAL);
952 r = xmlwrite_sum(a, writer, "archived-checksum", &(heap->a_sum));
954 return (ARCHIVE_FATAL);
955 r = xmlwrite_sum(a, writer, "extracted-checksum", &(heap->e_sum));
957 return (ARCHIVE_FATAL);
962 * xar utility records fflags as following xml elements:
972 * If xar is running on BSD platform, records <flags>..</flags>;
973 * if xar is running on linux platform, records <ext2>..</ext2>;
974 * otherwise does not record.
976 * Our implements records both <flags> and <ext2> if it's necessary.
979 make_fflags_entry(struct archive_write *a, xmlTextWriterPtr writer,
980 const char *element, const char *fflags_text)
982 static const struct flagentry {
987 { "sappnd", "SystemAppend"},
988 { "sappend", "SystemAppend"},
989 { "arch", "SystemArchived"},
990 { "archived", "SystemArchived"},
991 { "schg", "SystemImmutable"},
992 { "schange", "SystemImmutable"},
993 { "simmutable", "SystemImmutable"},
994 { "nosunlnk", "SystemNoUnlink"},
995 { "nosunlink", "SystemNoUnlink"},
996 { "snapshot", "SystemSnapshot"},
997 { "uappnd", "UserAppend"},
998 { "uappend", "UserAppend"},
999 { "uchg", "UserImmutable"},
1000 { "uchange", "UserImmutable"},
1001 { "uimmutable", "UserImmutable"},
1002 { "nodump", "UserNoDump"},
1003 { "noopaque", "UserOpaque"},
1004 { "nouunlnk", "UserNoUnlink"},
1005 { "nouunlink", "UserNoUnlink"},
1009 { "sappnd", "AppendOnly"},
1010 { "sappend", "AppendOnly"},
1011 { "schg", "Immutable"},
1012 { "schange", "Immutable"},
1013 { "simmutable", "Immutable"},
1014 { "nodump", "NoDump"},
1015 { "nouunlnk", "Undelete"},
1016 { "nouunlink", "Undelete"},
1017 { "btree", "BTree"},
1018 { "comperr", "CompError"},
1019 { "compress", "Compress"},
1020 { "noatime", "NoAtime"},
1021 { "compdirty", "CompDirty"},
1022 { "comprblk", "CompBlock"},
1023 { "dirsync", "DirSync"},
1024 { "hashidx", "HashIndexed"},
1025 { "imagic", "iMagic"},
1026 { "journal", "Journaled"},
1027 { "securedeletion", "SecureDeletion"},
1028 { "sync", "Synchronous"},
1029 { "notail", "NoTail"},
1030 { "topdir", "TopDir"},
1031 { "reserved", "Reserved"},
1034 const struct flagentry *fe, *flagentry;
1035 #define FLAGENTRY_MAXSIZE ((sizeof(flagbsd)+sizeof(flagext2))/sizeof(flagbsd))
1036 const struct flagentry *avail[FLAGENTRY_MAXSIZE];
1040 if (strcmp(element, "ext2") == 0)
1041 flagentry = flagext2;
1043 flagentry = flagbsd;
1049 cp = strchr(p, ',');
1053 for (fe = flagentry; fe->name != NULL; fe++) {
1054 if (fe->name[cp - p] != '\0'
1055 || p[0] != fe->name[0])
1057 if (strncmp(p, fe->name, cp - p) == 0) {
1066 } while (p != NULL);
1069 r = xmlTextWriterStartElement(writer, BAD_CAST(element));
1071 archive_set_error(&a->archive,
1073 "xmlTextWriterStartElement() failed: %d", r);
1074 return (ARCHIVE_FATAL);
1076 for (i = 0; i < n; i++) {
1077 r = xmlwrite_string(a, writer,
1078 avail[i]->xarname, NULL);
1079 if (r != ARCHIVE_OK)
1083 r = xmlTextWriterEndElement(writer);
1085 archive_set_error(&a->archive,
1087 "xmlTextWriterEndElement() failed: %d", r);
1088 return (ARCHIVE_FATAL);
1091 return (ARCHIVE_OK);
1095 make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
1099 const char *filetype, *filelink, *fflags;
1100 struct archive_string linkto;
1101 struct heap_data *heap;
1107 xar = (struct xar *)a->format_data;
1111 * Make a file name entry, "<name>".
1113 l = ll = archive_strlen(&(file->basename));
1116 archive_set_error(&a->archive, ENOMEM,
1117 "Can't allocate memory");
1118 return (ARCHIVE_FATAL);
1120 r = UTF8Toisolat1(tmp, &l, BAD_CAST(file->basename.s), &ll);
1123 r = xmlTextWriterStartElement(writer, BAD_CAST("name"));
1125 archive_set_error(&a->archive,
1127 "xmlTextWriterStartElement() failed: %d", r);
1128 return (ARCHIVE_FATAL);
1130 r = xmlTextWriterWriteAttribute(writer,
1131 BAD_CAST("enctype"), BAD_CAST("base64"));
1133 archive_set_error(&a->archive,
1135 "xmlTextWriterWriteAttribute() failed: %d", r);
1136 return (ARCHIVE_FATAL);
1138 r = xmlTextWriterWriteBase64(writer, file->basename.s,
1139 0, archive_strlen(&(file->basename)));
1141 archive_set_error(&a->archive,
1143 "xmlTextWriterWriteBase64() failed: %d", r);
1144 return (ARCHIVE_FATAL);
1146 r = xmlTextWriterEndElement(writer);
1148 archive_set_error(&a->archive,
1150 "xmlTextWriterEndElement() failed: %d", r);
1151 return (ARCHIVE_FATAL);
1154 r = xmlwrite_string(a, writer, "name", file->basename.s);
1156 return (ARCHIVE_FATAL);
1160 * Make a file type entry, "<type>".
1163 archive_string_init(&linkto);
1164 switch (archive_entry_filetype(file->entry)) {
1166 filetype = "directory"; break;
1168 filetype = "symlink"; break;
1170 filetype = "character special"; break;
1172 filetype = "block special"; break;
1174 filetype = "socket"; break;
1176 filetype = "fifo"; break;
1179 if (file->hardlink_target != NULL) {
1180 filetype = "hardlink";
1182 if (file->hardlink_target == file)
1183 archive_strcpy(&linkto, "original");
1185 archive_string_sprintf(&linkto, "%d",
1186 file->hardlink_target->id);
1191 r = xmlwrite_string_attr(a, writer, "type", filetype,
1192 filelink, linkto.s);
1193 archive_string_free(&linkto);
1195 return (ARCHIVE_FATAL);
1198 * On a virtual directory, we record "name" and "type" only.
1201 return (ARCHIVE_OK);
1203 switch (archive_entry_filetype(file->entry)) {
1206 * xar utility has checked a file type, which
1207 * a symblic-link file has referenced.
1209 * <link type="directory">../ref/</link>
1210 * The symlink target file is "../ref/" and its
1211 * file type is a directory.
1213 * <link type="file">../f</link>
1214 * The symlink target file is "../f" and its
1215 * file type is a regular file.
1217 * But our implemention cannot do it, and then we
1218 * always record that a attribute "type" is "borken",
1220 * <link type="broken">foo/bar</link>
1221 * It means "foo/bar" is not reachable.
1223 r = xmlwrite_string_attr(a, writer, "link",
1227 return (ARCHIVE_FATAL);
1231 r = xmlTextWriterStartElement(writer, BAD_CAST("device"));
1233 archive_set_error(&a->archive,
1235 "xmlTextWriterStartElement() failed: %d", r);
1236 return (ARCHIVE_FATAL);
1238 r = xmlwrite_fstring(a, writer, "major",
1239 "%d", archive_entry_rdevmajor(file->entry));
1241 return (ARCHIVE_FATAL);
1242 r = xmlwrite_fstring(a, writer, "minor",
1243 "%d", archive_entry_rdevminor(file->entry));
1245 return (ARCHIVE_FATAL);
1246 r = xmlTextWriterEndElement(writer);
1248 archive_set_error(&a->archive,
1250 "xmlTextWriterEndElement() failed: %d", r);
1251 return (ARCHIVE_FATAL);
1259 * Make a inode entry, "<inode>".
1261 r = xmlwrite_fstring(a, writer, "inode",
1262 "%jd", archive_entry_ino64(file->entry));
1264 return (ARCHIVE_FATAL);
1265 if (archive_entry_dev(file->entry) != 0) {
1266 r = xmlwrite_fstring(a, writer, "deviceno",
1267 "%d", archive_entry_dev(file->entry));
1269 return (ARCHIVE_FATAL);
1273 * Make a file mode entry, "<mode>".
1275 r = xmlwrite_mode(a, writer, "mode",
1276 archive_entry_mode(file->entry));
1278 return (ARCHIVE_FATAL);
1281 * Make a user entry, "<uid>" and "<user>.
1283 r = xmlwrite_fstring(a, writer, "uid",
1284 "%d", archive_entry_uid(file->entry));
1286 return (ARCHIVE_FATAL);
1287 r = archive_entry_uname_l(file->entry, &p, &len, xar->sconv);
1289 if (errno == ENOMEM) {
1290 archive_set_error(&a->archive, ENOMEM,
1291 "Can't allocate memory for Uname");
1292 return (ARCHIVE_FATAL);
1294 archive_set_error(&a->archive,
1295 ARCHIVE_ERRNO_FILE_FORMAT,
1296 "Can't translate uname '%s' to UTF-8",
1297 archive_entry_uname(file->entry));
1301 r = xmlwrite_string(a, writer, "user", p);
1303 return (ARCHIVE_FATAL);
1307 * Make a group entry, "<gid>" and "<group>.
1309 r = xmlwrite_fstring(a, writer, "gid",
1310 "%d", archive_entry_gid(file->entry));
1312 return (ARCHIVE_FATAL);
1313 r = archive_entry_gname_l(file->entry, &p, &len, xar->sconv);
1315 if (errno == ENOMEM) {
1316 archive_set_error(&a->archive, ENOMEM,
1317 "Can't allocate memory for Gname");
1318 return (ARCHIVE_FATAL);
1320 archive_set_error(&a->archive,
1321 ARCHIVE_ERRNO_FILE_FORMAT,
1322 "Can't translate gname '%s' to UTF-8",
1323 archive_entry_gname(file->entry));
1327 r = xmlwrite_string(a, writer, "group", p);
1329 return (ARCHIVE_FATAL);
1333 * Make a ctime entry, "<ctime>".
1335 if (archive_entry_ctime_is_set(file->entry)) {
1336 r = xmlwrite_time(a, writer, "ctime",
1337 archive_entry_ctime(file->entry), 1);
1339 return (ARCHIVE_FATAL);
1343 * Make a mtime entry, "<mtime>".
1345 if (archive_entry_mtime_is_set(file->entry)) {
1346 r = xmlwrite_time(a, writer, "mtime",
1347 archive_entry_mtime(file->entry), 1);
1349 return (ARCHIVE_FATAL);
1353 * Make a atime entry, "<atime>".
1355 if (archive_entry_atime_is_set(file->entry)) {
1356 r = xmlwrite_time(a, writer, "atime",
1357 archive_entry_atime(file->entry), 1);
1359 return (ARCHIVE_FATAL);
1363 * Make fflags entries, "<flags>" and "<ext2>".
1365 fflags = archive_entry_fflags_text(file->entry);
1366 if (fflags != NULL) {
1367 r = make_fflags_entry(a, writer, "flags", fflags);
1370 r = make_fflags_entry(a, writer, "ext2", fflags);
1376 * Make extended attribute entries, "<ea>".
1378 archive_entry_xattr_reset(file->entry);
1379 for (heap = file->xattr.first; heap != NULL; heap = heap->next) {
1384 archive_entry_xattr_next(file->entry,
1385 &name, &value, &size);
1386 r = xmlTextWriterStartElement(writer, BAD_CAST("ea"));
1388 archive_set_error(&a->archive,
1390 "xmlTextWriterStartElement() failed: %d", r);
1391 return (ARCHIVE_FATAL);
1393 r = xmlTextWriterWriteFormatAttribute(writer,
1394 BAD_CAST("id"), "%d", heap->id);
1396 archive_set_error(&a->archive,
1398 "xmlTextWriterWriteAttribute() failed: %d", r);
1399 return (ARCHIVE_FATAL);
1401 r = xmlwrite_heap(a, writer, heap);
1403 return (ARCHIVE_FATAL);
1404 r = xmlwrite_string(a, writer, "name", name);
1406 return (ARCHIVE_FATAL);
1408 r = xmlTextWriterEndElement(writer);
1410 archive_set_error(&a->archive,
1412 "xmlTextWriterEndElement() failed: %d", r);
1413 return (ARCHIVE_FATAL);
1418 * Make a file data entry, "<data>".
1420 if (file->data.length > 0) {
1421 r = xmlTextWriterStartElement(writer, BAD_CAST("data"));
1423 archive_set_error(&a->archive,
1425 "xmlTextWriterStartElement() failed: %d", r);
1426 return (ARCHIVE_FATAL);
1429 r = xmlwrite_heap(a, writer, &(file->data));
1431 return (ARCHIVE_FATAL);
1433 r = xmlTextWriterEndElement(writer);
1435 archive_set_error(&a->archive,
1437 "xmlTextWriterEndElement() failed: %d", r);
1438 return (ARCHIVE_FATAL);
1442 if (archive_strlen(&file->script) > 0) {
1443 r = xmlTextWriterStartElement(writer, BAD_CAST("content"));
1445 archive_set_error(&a->archive,
1447 "xmlTextWriterStartElement() failed: %d", r);
1448 return (ARCHIVE_FATAL);
1451 r = xmlwrite_string(a, writer,
1452 "interpreter", file->script.s);
1454 return (ARCHIVE_FATAL);
1456 r = xmlwrite_string(a, writer, "type", "script");
1458 return (ARCHIVE_FATAL);
1460 r = xmlTextWriterEndElement(writer);
1462 archive_set_error(&a->archive,
1464 "xmlTextWriterEndElement() failed: %d", r);
1465 return (ARCHIVE_FATAL);
1476 make_toc(struct archive_write *a)
1481 xmlTextWriterPtr writer;
1485 xar = (struct xar *)a->format_data;
1487 ret = ARCHIVE_FATAL;
1490 * Initialize xml writer.
1493 bp = xmlBufferCreate();
1495 archive_set_error(&a->archive, ENOMEM,
1496 "xmlBufferCreate() "
1497 "couldn't create xml buffer");
1500 writer = xmlNewTextWriterMemory(bp, 0);
1501 if (writer == NULL) {
1502 archive_set_error(&a->archive,
1504 "xmlNewTextWriterMemory() "
1505 "couldn't create xml writer");
1508 r = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL);
1510 archive_set_error(&a->archive,
1512 "xmlTextWriterStartDocument() failed: %d", r);
1515 r = xmlTextWriterSetIndent(writer, 4);
1517 archive_set_error(&a->archive,
1519 "xmlTextWriterSetIndent() failed: %d", r);
1524 * Start recoding TOC
1526 r = xmlTextWriterStartElement(writer, BAD_CAST("xar"));
1528 archive_set_error(&a->archive,
1530 "xmlTextWriterStartElement() failed: %d", r);
1533 r = xmlTextWriterStartElement(writer, BAD_CAST("toc"));
1535 archive_set_error(&a->archive,
1537 "xmlTextWriterStartDocument() failed: %d", r);
1542 * Record the creation time of the archive file.
1544 r = xmlwrite_time(a, writer, "creation-time", time(NULL), 0);
1549 * Record the checksum value of TOC
1551 algsize = getalgsize(xar->opt_toc_sumalg);
1554 * Record TOC checksum
1556 r = xmlTextWriterStartElement(writer, BAD_CAST("checksum"));
1558 archive_set_error(&a->archive,
1560 "xmlTextWriterStartElement() failed: %d", r);
1563 r = xmlTextWriterWriteAttribute(writer, BAD_CAST("style"),
1564 BAD_CAST(getalgname(xar->opt_toc_sumalg)));
1566 archive_set_error(&a->archive,
1568 "xmlTextWriterWriteAttribute() failed: %d", r);
1573 * Record the offset of the value of checksum of TOC
1575 r = xmlwrite_string(a, writer, "offset", "0");
1580 * Record the size of the value of checksum of TOC
1582 r = xmlwrite_fstring(a, writer, "size", "%d", algsize);
1586 r = xmlTextWriterEndElement(writer);
1588 archive_set_error(&a->archive,
1590 "xmlTextWriterEndElement() failed: %d", r);
1597 if (np != np->parent) {
1598 r = make_file_entry(a, writer, np);
1599 if (r != ARCHIVE_OK)
1603 if (np->dir && np->children.first != NULL) {
1604 /* Enter to sub directories. */
1605 np = np->children.first;
1606 r = xmlTextWriterStartElement(writer,
1609 archive_set_error(&a->archive,
1611 "xmlTextWriterStartElement() "
1615 r = xmlTextWriterWriteFormatAttribute(
1616 writer, BAD_CAST("id"), "%d", np->id);
1618 archive_set_error(&a->archive,
1620 "xmlTextWriterWriteAttribute() "
1626 while (np != np->parent) {
1627 r = xmlTextWriterEndElement(writer);
1629 archive_set_error(&a->archive,
1631 "xmlTextWriterEndElement() "
1635 if (np->chnext == NULL) {
1636 /* Return to the parent directory. */
1640 r = xmlTextWriterStartElement(writer,
1643 archive_set_error(&a->archive,
1645 "xmlTextWriterStartElement() "
1649 r = xmlTextWriterWriteFormatAttribute(
1650 writer, BAD_CAST("id"), "%d", np->id);
1652 archive_set_error(&a->archive,
1654 "xmlTextWriterWriteAttribute() "
1661 } while (np != np->parent);
1663 r = xmlTextWriterEndDocument(writer);
1665 archive_set_error(&a->archive,
1667 "xmlTextWriterEndDocument() failed: %d", r);
1671 fprintf(stderr, "\n---TOC-- %d bytes --\n%s\n",
1672 strlen((const char *)bp->content), bp->content);
1676 * Compress the TOC and calculate the sum of the TOC.
1678 xar->toc.temp_offset = xar->temp_offset;
1679 xar->toc.size = bp->use;
1680 checksum_init(&(xar->a_sumwrk), xar->opt_toc_sumalg);
1682 r = compression_init_encoder_gzip(&(a->archive),
1683 &(xar->stream), 6, 1);
1684 if (r != ARCHIVE_OK)
1686 xar->stream.next_in = bp->content;
1687 xar->stream.avail_in = bp->use;
1688 xar->stream.total_in = 0;
1689 xar->stream.next_out = xar->wbuff;
1690 xar->stream.avail_out = sizeof(xar->wbuff);
1691 xar->stream.total_out = 0;
1695 r = compression_code(&(a->archive),
1696 &(xar->stream), ARCHIVE_Z_FINISH);
1697 if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
1699 size = sizeof(xar->wbuff) - xar->stream.avail_out;
1700 checksum_update(&(xar->a_sumwrk), xar->wbuff, size);
1701 if (write_to_temp(a, xar->wbuff, size) != ARCHIVE_OK)
1703 if (r == ARCHIVE_EOF)
1705 xar->stream.next_out = xar->wbuff;
1706 xar->stream.avail_out = sizeof(xar->wbuff);
1708 r = compression_end(&(a->archive), &(xar->stream));
1709 if (r != ARCHIVE_OK)
1711 xar->toc.length = xar->stream.total_out;
1712 xar->toc.compression = GZIP;
1713 checksum_final(&(xar->a_sumwrk), &(xar->toc.a_sum));
1718 xmlFreeTextWriter(writer);
1726 flush_wbuff(struct archive_write *a)
1732 xar = (struct xar *)a->format_data;
1733 s = sizeof(xar->wbuff) - xar->wbuff_remaining;
1734 r = __archive_write_output(a, xar->wbuff, s);
1735 if (r != ARCHIVE_OK)
1737 xar->wbuff_remaining = sizeof(xar->wbuff);
1742 copy_out(struct archive_write *a, uint64_t offset, uint64_t length)
1747 xar = (struct xar *)a->format_data;
1748 if (lseek(xar->temp_fd, offset, SEEK_SET) < 0) {
1749 archive_set_error(&(a->archive), errno, "lseek failed");
1750 return (ARCHIVE_FATAL);
1757 if (length > xar->wbuff_remaining)
1758 rsize = xar->wbuff_remaining;
1760 rsize = (size_t)length;
1761 wb = xar->wbuff + (sizeof(xar->wbuff) - xar->wbuff_remaining);
1762 rs = read(xar->temp_fd, wb, rsize);
1764 archive_set_error(&(a->archive), errno,
1765 "Can't read temporary file(%jd)",
1767 return (ARCHIVE_FATAL);
1770 archive_set_error(&(a->archive), 0,
1771 "Truncated xar archive");
1772 return (ARCHIVE_FATAL);
1774 xar->wbuff_remaining -= rs;
1776 if (xar->wbuff_remaining == 0) {
1778 if (r != ARCHIVE_OK)
1782 return (ARCHIVE_OK);
1786 xar_close(struct archive_write *a)
1793 xar = (struct xar *)a->format_data;
1796 if (xar->root->children.first == NULL)
1797 return (ARCHIVE_OK);
1799 /* Save the length of all file extended attributes and contents. */
1800 length = xar->temp_offset;
1802 /* Connect hardlinked files */
1803 file_connect_hardlink_files(xar);
1807 if (r != ARCHIVE_OK)
1810 * Make the xar header on wbuff(write buffer).
1813 xar->wbuff_remaining = sizeof(xar->wbuff);
1814 archive_be32enc(&wb[0], HEADER_MAGIC);
1815 archive_be16enc(&wb[4], HEADER_SIZE);
1816 archive_be16enc(&wb[6], HEADER_VERSION);
1817 archive_be64enc(&wb[8], xar->toc.length);
1818 archive_be64enc(&wb[16], xar->toc.size);
1819 archive_be32enc(&wb[24], xar->toc.a_sum.alg);
1820 xar->wbuff_remaining -= HEADER_SIZE;
1825 r = copy_out(a, xar->toc.temp_offset, xar->toc.length);
1826 if (r != ARCHIVE_OK)
1829 /* Write the checksum value of the TOC. */
1830 if (xar->toc.a_sum.len) {
1831 if (xar->wbuff_remaining < xar->toc.a_sum.len) {
1833 if (r != ARCHIVE_OK)
1836 wb = xar->wbuff + (sizeof(xar->wbuff) - xar->wbuff_remaining);
1837 memcpy(wb, xar->toc.a_sum.val, xar->toc.a_sum.len);
1838 xar->wbuff_remaining -= xar->toc.a_sum.len;
1842 * Write all file extended attributes and contents.
1844 r = copy_out(a, xar->toc.a_sum.len, length);
1845 if (r != ARCHIVE_OK)
1852 xar_free(struct archive_write *a)
1856 xar = (struct xar *)a->format_data;
1857 archive_string_free(&(xar->cur_dirstr));
1858 archive_string_free(&(xar->tstr));
1859 archive_string_free(&(xar->vstr));
1860 file_free_hardlinks(xar);
1861 file_free_register(xar);
1862 compression_end(&(a->archive), &(xar->stream));
1865 return (ARCHIVE_OK);
1869 file_cmp_node(const struct archive_rb_node *n1,
1870 const struct archive_rb_node *n2)
1872 struct file *f1 = (struct file *)n1;
1873 struct file *f2 = (struct file *)n2;
1875 return (strcmp(f1->basename.s, f2->basename.s));
1879 file_cmp_key(const struct archive_rb_node *n, const void *key)
1881 struct file *f = (struct file *)n;
1883 return (strcmp(f->basename.s, (const char *)key));
1886 static struct file *
1887 file_new(struct archive_write *a, struct archive_entry *entry)
1890 static const struct archive_rb_tree_ops rb_ops = {
1891 file_cmp_node, file_cmp_key
1894 file = calloc(1, sizeof(*file));
1899 file->entry = archive_entry_clone(entry);
1901 file->entry = archive_entry_new2(&a->archive);
1902 if (file->entry == NULL) {
1906 __archive_rb_tree_init(&(file->rbtree), &rb_ops);
1907 file->children.first = NULL;
1908 file->children.last = &(file->children.first);
1909 file->xattr.first = NULL;
1910 file->xattr.last = &(file->xattr.first);
1911 archive_string_init(&(file->parentdir));
1912 archive_string_init(&(file->basename));
1913 archive_string_init(&(file->symlink));
1914 archive_string_init(&(file->script));
1915 if (entry != NULL && archive_entry_filetype(entry) == AE_IFDIR)
1922 file_free(struct file *file)
1924 struct heap_data *heap, *next_heap;
1926 heap = file->xattr.first;
1927 while (heap != NULL) {
1928 next_heap = heap->next;
1932 archive_string_free(&(file->parentdir));
1933 archive_string_free(&(file->basename));
1934 archive_string_free(&(file->symlink));
1935 archive_string_free(&(file->script));
1939 static struct file *
1940 file_create_virtual_dir(struct archive_write *a, struct xar *xar,
1941 const char *pathname)
1945 file = file_new(a, NULL);
1948 archive_entry_set_pathname(file->entry, pathname);
1949 archive_entry_set_mode(file->entry, 0555 | AE_IFDIR);
1958 file_add_child_tail(struct file *parent, struct file *child)
1960 if (!__archive_rb_tree_insert_node(
1961 &(parent->rbtree), (struct archive_rb_node *)child))
1963 child->chnext = NULL;
1964 *parent->children.last = child;
1965 parent->children.last = &(child->chnext);
1966 child->parent = parent;
1971 * Find a entry from `parent'
1973 static struct file *
1974 file_find_child(struct file *parent, const char *child_name)
1978 np = (struct file *)__archive_rb_tree_find_node(
1979 &(parent->rbtree), child_name);
1983 #if defined(_WIN32) || defined(__CYGWIN__)
1985 cleanup_backslash(char *utf8, size_t len)
1988 /* Convert a path-separator from '\' to '/' */
1989 while (*utf8 != '\0' && len) {
1997 #define cleanup_backslash(p, len) /* nop */
2001 * Generate a parent directory name and a base name from a pathname.
2004 file_gen_utility_names(struct archive_write *a, struct file *file)
2008 char *p, *dirname, *slash;
2012 xar = (struct xar *)a->format_data;
2013 archive_string_empty(&(file->parentdir));
2014 archive_string_empty(&(file->basename));
2015 archive_string_empty(&(file->symlink));
2017 if (file->parent == file)/* virtual root */
2018 return (ARCHIVE_OK);
2020 if (archive_entry_pathname_l(file->entry, &pp, &len, xar->sconv)
2022 if (errno == ENOMEM) {
2023 archive_set_error(&a->archive, ENOMEM,
2024 "Can't allocate memory for Pathname");
2025 return (ARCHIVE_FATAL);
2027 archive_set_error(&a->archive,
2028 ARCHIVE_ERRNO_FILE_FORMAT,
2029 "Can't translate pathname '%s' to UTF-8",
2030 archive_entry_pathname(file->entry));
2033 archive_strncpy(&(file->parentdir), pp, len);
2034 len = file->parentdir.length;
2035 p = dirname = file->parentdir.s;
2037 * Convert a path-separator from '\' to '/'
2039 cleanup_backslash(p, len);
2042 * Remove leading '/', '../' and './' elements
2048 } else if (p[0] != '.')
2050 else if (p[1] == '.' && p[2] == '/') {
2053 } else if (p[1] == '/' || (p[1] == '.' && p[2] == '\0')) {
2056 } else if (p[1] == '\0') {
2063 memmove(dirname, p, len+1);
2067 * Remove "/","/." and "/.." elements from tail.
2072 if (len > 0 && p[len-1] == '/') {
2076 if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
2080 if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
2091 /* Convert '//' --> '/' */
2093 else if (p[1] == '.' && p[2] == '/')
2094 /* Convert '/./' --> '/' */
2096 else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
2097 /* Convert 'dir/dir1/../dir2/'
2101 while (rp >= dirname) {
2110 strcpy(dirname, p+4);
2121 if (archive_entry_filetype(file->entry) == AE_IFLNK) {
2123 /* Convert symlink name too. */
2124 if (archive_entry_symlink_l(file->entry, &pp, &len2,
2126 if (errno == ENOMEM) {
2127 archive_set_error(&a->archive, ENOMEM,
2128 "Can't allocate memory for Linkname");
2129 return (ARCHIVE_FATAL);
2131 archive_set_error(&a->archive,
2132 ARCHIVE_ERRNO_FILE_FORMAT,
2133 "Can't translate symlink '%s' to UTF-8",
2134 archive_entry_symlink(file->entry));
2137 archive_strncpy(&(file->symlink), pp, len2);
2138 cleanup_backslash(file->symlink.s, file->symlink.length);
2141 * - Count up directory elements.
2142 * - Find out the position which points the last position of
2143 * path separator('/').
2146 for (; *p != '\0'; p++)
2149 if (slash == NULL) {
2150 /* The pathname doesn't have a parent directory. */
2151 file->parentdir.length = len;
2152 archive_string_copy(&(file->basename), &(file->parentdir));
2153 archive_string_empty(&(file->parentdir));
2154 file->parentdir.s = '\0';
2158 /* Make a basename from dirname and slash */
2160 file->parentdir.length = slash - dirname;
2161 archive_strcpy(&(file->basename), slash + 1);
2166 get_path_component(char *name, int n, const char *fn)
2171 p = strchr(fn, '/');
2173 if ((l = strlen(fn)) == 0)
2179 memcpy(name, fn, l);
2186 * Add a new entry into the tree.
2189 file_tree(struct archive_write *a, struct file **filepp)
2191 #if defined(_WIN32) && !defined(__CYGWIN__)
2192 char name[_MAX_FNAME];/* Included null terminator size. */
2193 #elif defined(NAME_MAX) && NAME_MAX >= 255
2194 char name[NAME_MAX+1];
2198 struct xar *xar = (struct xar *)a->format_data;
2199 struct file *dent, *file, *np;
2200 struct archive_entry *ent;
2206 if (file->parentdir.length > 0)
2207 fn = p = file->parentdir.s;
2212 * If the path of the parent directory of `file' entry is
2213 * the same as the path of `cur_dirent', add isoent to
2216 if (archive_strlen(&(xar->cur_dirstr))
2217 == archive_strlen(&(file->parentdir)) &&
2218 strcmp(xar->cur_dirstr.s, fn) == 0) {
2219 if (!file_add_child_tail(xar->cur_dirent, file)) {
2220 np = (struct file *)__archive_rb_tree_find_node(
2221 &(xar->cur_dirent->rbtree),
2225 return (ARCHIVE_OK);
2229 l = get_path_component(name, sizeof(name), fn);
2235 archive_set_error(&a->archive,
2237 "A name buffer is too small");
2240 return (ARCHIVE_FATAL);
2243 np = file_find_child(dent, name);
2244 if (np == NULL || fn[0] == '\0')
2247 /* Find next subdirectory. */
2249 /* NOT Directory! */
2250 archive_set_error(&a->archive,
2252 "`%s' is not directory, we cannot insert `%s' ",
2253 archive_entry_pathname(np->entry),
2254 archive_entry_pathname(file->entry));
2257 return (ARCHIVE_FAILED);
2266 * Create virtual parent directories.
2268 while (fn[0] != '\0') {
2270 struct archive_string as;
2272 archive_string_init(&as);
2273 archive_strncat(&as, p, fn - p + l);
2274 if (as.s[as.length-1] == '/') {
2275 as.s[as.length-1] = '\0';
2278 vp = file_create_virtual_dir(a, xar, as.s);
2280 archive_string_free(&as);
2281 archive_set_error(&a->archive, ENOMEM,
2282 "Can't allocate memory");
2285 return (ARCHIVE_FATAL);
2287 archive_string_free(&as);
2288 if (file_gen_utility_names(a, vp) <= ARCHIVE_FAILED)
2289 return (ARCHIVE_FATAL);
2290 file_add_child_tail(dent, vp);
2291 file_register(xar, vp);
2297 l = get_path_component(name, sizeof(name), fn);
2299 archive_string_free(&as);
2300 archive_set_error(&a->archive,
2302 "A name buffer is too small");
2305 return (ARCHIVE_FATAL);
2310 /* Found out the parent directory where isoent can be
2312 xar->cur_dirent = dent;
2313 archive_string_empty(&(xar->cur_dirstr));
2314 archive_string_ensure(&(xar->cur_dirstr),
2315 archive_strlen(&(dent->parentdir)) +
2316 archive_strlen(&(dent->basename)) + 2);
2317 if (archive_strlen(&(dent->parentdir)) +
2318 archive_strlen(&(dent->basename)) == 0)
2319 xar->cur_dirstr.s[0] = 0;
2321 if (archive_strlen(&(dent->parentdir)) > 0) {
2322 archive_string_copy(&(xar->cur_dirstr),
2323 &(dent->parentdir));
2324 archive_strappend_char(&(xar->cur_dirstr), '/');
2326 archive_string_concat(&(xar->cur_dirstr),
2330 if (!file_add_child_tail(dent, file)) {
2331 np = (struct file *)__archive_rb_tree_find_node(
2332 &(dent->rbtree), file->basename.s);
2335 return (ARCHIVE_OK);
2340 * We have already has the entry the filename of which is
2343 if (archive_entry_filetype(np->entry) !=
2344 archive_entry_filetype(file->entry)) {
2345 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2346 "Found duplicate entries `%s' and its file type is "
2348 archive_entry_pathname(np->entry));
2351 return (ARCHIVE_FAILED);
2356 np->entry = file->entry;
2362 return (ARCHIVE_OK);
2366 file_register(struct xar *xar, struct file *file)
2368 file->id = xar->file_idx++;
2370 *xar->file_list.last = file;
2371 xar->file_list.last = &(file->next);
2375 file_init_register(struct xar *xar)
2377 xar->file_list.first = NULL;
2378 xar->file_list.last = &(xar->file_list.first);
2382 file_free_register(struct xar *xar)
2384 struct file *file, *file_next;
2386 file = xar->file_list.first;
2387 while (file != NULL) {
2388 file_next = file->next;
2395 * Register entry to get a hardlink target.
2398 file_register_hardlink(struct archive_write *a, struct file *file)
2400 struct xar *xar = (struct xar *)a->format_data;
2401 struct hardlink *hl;
2402 const char *pathname;
2404 archive_entry_set_nlink(file->entry, 1);
2405 pathname = archive_entry_hardlink(file->entry);
2406 if (pathname == NULL) {
2407 /* This `file` is a hardlink target. */
2408 hl = malloc(sizeof(*hl));
2410 archive_set_error(&a->archive, ENOMEM,
2411 "Can't allocate memory");
2412 return (ARCHIVE_FATAL);
2415 /* A hardlink target must be the first position. */
2416 file->hlnext = NULL;
2417 hl->file_list.first = file;
2418 hl->file_list.last = &(file->hlnext);
2419 __archive_rb_tree_insert_node(&(xar->hardlink_rbtree),
2420 (struct archive_rb_node *)hl);
2422 hl = (struct hardlink *)__archive_rb_tree_find_node(
2423 &(xar->hardlink_rbtree), pathname);
2425 /* Insert `file` entry into the tail. */
2426 file->hlnext = NULL;
2427 *hl->file_list.last = file;
2428 hl->file_list.last = &(file->hlnext);
2431 archive_entry_unset_size(file->entry);
2434 return (ARCHIVE_OK);
2438 * Hardlinked files have to have the same location of extent.
2439 * We have to find out hardlink target entries for entries which
2440 * have a hardlink target name.
2443 file_connect_hardlink_files(struct xar *xar)
2445 struct archive_rb_node *n;
2446 struct hardlink *hl;
2447 struct file *target, *nf;
2449 ARCHIVE_RB_TREE_FOREACH(n, &(xar->hardlink_rbtree)) {
2450 hl = (struct hardlink *)n;
2452 /* The first entry must be a hardlink target. */
2453 target = hl->file_list.first;
2454 archive_entry_set_nlink(target->entry, hl->nlink);
2456 /* It means this file is a hardlink
2458 target->hardlink_target = target;
2459 for (nf = target->hlnext;
2460 nf != NULL; nf = nf->hlnext) {
2461 nf->hardlink_target = target;
2462 archive_entry_set_nlink(nf->entry, hl->nlink);
2468 file_hd_cmp_node(const struct archive_rb_node *n1,
2469 const struct archive_rb_node *n2)
2471 struct hardlink *h1 = (struct hardlink *)n1;
2472 struct hardlink *h2 = (struct hardlink *)n2;
2474 return (strcmp(archive_entry_pathname(h1->file_list.first->entry),
2475 archive_entry_pathname(h2->file_list.first->entry)));
2479 file_hd_cmp_key(const struct archive_rb_node *n, const void *key)
2481 struct hardlink *h = (struct hardlink *)n;
2483 return (strcmp(archive_entry_pathname(h->file_list.first->entry),
2484 (const char *)key));
2489 file_init_hardlinks(struct xar *xar)
2491 static const struct archive_rb_tree_ops rb_ops = {
2492 file_hd_cmp_node, file_hd_cmp_key,
2495 __archive_rb_tree_init(&(xar->hardlink_rbtree), &rb_ops);
2499 file_free_hardlinks(struct xar *xar)
2501 struct archive_rb_node *n, *next;
2503 for (n = ARCHIVE_RB_TREE_MIN(&(xar->hardlink_rbtree)); n;) {
2504 next = __archive_rb_tree_iterate(&(xar->hardlink_rbtree),
2505 n, ARCHIVE_RB_DIR_RIGHT);
2512 checksum_init(struct chksumwork *sumwrk, enum sumalg sum_alg)
2514 sumwrk->alg = sum_alg;
2519 archive_sha1_init(&(sumwrk->sha1ctx));
2522 archive_md5_init(&(sumwrk->md5ctx));
2528 checksum_update(struct chksumwork *sumwrk, const void *buff, size_t size)
2531 switch (sumwrk->alg) {
2535 archive_sha1_update(&(sumwrk->sha1ctx), buff, size);
2538 archive_md5_update(&(sumwrk->md5ctx), buff, size);
2544 checksum_final(struct chksumwork *sumwrk, struct chksumval *sumval)
2547 switch (sumwrk->alg) {
2552 archive_sha1_final(&(sumwrk->sha1ctx), sumval->val);
2553 sumval->len = SHA1_SIZE;
2556 archive_md5_final(&(sumwrk->md5ctx), sumval->val);
2557 sumval->len = MD5_SIZE;
2560 sumval->alg = sumwrk->alg;
2563 #if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
2565 compression_unsupported_encoder(struct archive *a,
2566 struct la_zstream *lastrm, const char *name)
2569 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2570 "%s compression not supported on this platform", name);
2572 lastrm->real_stream = NULL;
2573 return (ARCHIVE_FAILED);
2578 compression_init_encoder_gzip(struct archive *a,
2579 struct la_zstream *lastrm, int level, int withheader)
2584 compression_end(a, lastrm);
2585 strm = calloc(1, sizeof(*strm));
2587 archive_set_error(a, ENOMEM,
2588 "Can't allocate memory for gzip stream");
2589 return (ARCHIVE_FATAL);
2591 /* zlib.h is not const-correct, so we need this one bit
2592 * of ugly hackery to convert a const * pointer to
2593 * a non-const pointer. */
2594 strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
2595 strm->avail_in = lastrm->avail_in;
2596 strm->total_in = lastrm->total_in;
2597 strm->next_out = lastrm->next_out;
2598 strm->avail_out = lastrm->avail_out;
2599 strm->total_out = lastrm->total_out;
2600 if (deflateInit2(strm, level, Z_DEFLATED,
2601 (withheader)?15:-15,
2602 8, Z_DEFAULT_STRATEGY) != Z_OK) {
2604 lastrm->real_stream = NULL;
2605 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2606 "Internal error initializing compression library");
2607 return (ARCHIVE_FATAL);
2609 lastrm->real_stream = strm;
2611 lastrm->code = compression_code_gzip;
2612 lastrm->end = compression_end_gzip;
2613 return (ARCHIVE_OK);
2617 compression_code_gzip(struct archive *a,
2618 struct la_zstream *lastrm, enum la_zaction action)
2623 strm = (z_stream *)lastrm->real_stream;
2624 /* zlib.h is not const-correct, so we need this one bit
2625 * of ugly hackery to convert a const * pointer to
2626 * a non-const pointer. */
2627 strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
2628 strm->avail_in = lastrm->avail_in;
2629 strm->total_in = lastrm->total_in;
2630 strm->next_out = lastrm->next_out;
2631 strm->avail_out = lastrm->avail_out;
2632 strm->total_out = lastrm->total_out;
2634 (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH);
2635 lastrm->next_in = strm->next_in;
2636 lastrm->avail_in = strm->avail_in;
2637 lastrm->total_in = strm->total_in;
2638 lastrm->next_out = strm->next_out;
2639 lastrm->avail_out = strm->avail_out;
2640 lastrm->total_out = strm->total_out;
2643 return (ARCHIVE_OK);
2645 return (ARCHIVE_EOF);
2647 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2648 "GZip compression failed:"
2649 " deflate() call returned status %d", r);
2650 return (ARCHIVE_FATAL);
2655 compression_end_gzip(struct archive *a, struct la_zstream *lastrm)
2660 strm = (z_stream *)lastrm->real_stream;
2661 r = deflateEnd(strm);
2663 lastrm->real_stream = NULL;
2666 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2667 "Failed to clean up compressor");
2668 return (ARCHIVE_FATAL);
2670 return (ARCHIVE_OK);
2673 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
2675 compression_init_encoder_bzip2(struct archive *a,
2676 struct la_zstream *lastrm, int level)
2681 compression_end(a, lastrm);
2682 strm = calloc(1, sizeof(*strm));
2684 archive_set_error(a, ENOMEM,
2685 "Can't allocate memory for bzip2 stream");
2686 return (ARCHIVE_FATAL);
2688 /* bzlib.h is not const-correct, so we need this one bit
2689 * of ugly hackery to convert a const * pointer to
2690 * a non-const pointer. */
2691 strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
2692 strm->avail_in = lastrm->avail_in;
2693 strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
2694 strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
2695 strm->next_out = (char *)lastrm->next_out;
2696 strm->avail_out = lastrm->avail_out;
2697 strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
2698 strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
2699 if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) {
2701 lastrm->real_stream = NULL;
2702 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2703 "Internal error initializing compression library");
2704 return (ARCHIVE_FATAL);
2706 lastrm->real_stream = strm;
2708 lastrm->code = compression_code_bzip2;
2709 lastrm->end = compression_end_bzip2;
2710 return (ARCHIVE_OK);
2714 compression_code_bzip2(struct archive *a,
2715 struct la_zstream *lastrm, enum la_zaction action)
2720 strm = (bz_stream *)lastrm->real_stream;
2721 /* bzlib.h is not const-correct, so we need this one bit
2722 * of ugly hackery to convert a const * pointer to
2723 * a non-const pointer. */
2724 strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
2725 strm->avail_in = lastrm->avail_in;
2726 strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
2727 strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
2728 strm->next_out = (char *)lastrm->next_out;
2729 strm->avail_out = lastrm->avail_out;
2730 strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
2731 strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
2732 r = BZ2_bzCompress(strm,
2733 (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN);
2734 lastrm->next_in = (const unsigned char *)strm->next_in;
2735 lastrm->avail_in = strm->avail_in;
2737 (((uint64_t)(uint32_t)strm->total_in_hi32) << 32)
2738 + (uint64_t)(uint32_t)strm->total_in_lo32;
2739 lastrm->next_out = (unsigned char *)strm->next_out;
2740 lastrm->avail_out = strm->avail_out;
2742 (((uint64_t)(uint32_t)strm->total_out_hi32) << 32)
2743 + (uint64_t)(uint32_t)strm->total_out_lo32;
2745 case BZ_RUN_OK: /* Non-finishing */
2746 case BZ_FINISH_OK: /* Finishing: There's more work to do */
2747 return (ARCHIVE_OK);
2748 case BZ_STREAM_END: /* Finishing: all done */
2749 /* Only occurs in finishing case */
2750 return (ARCHIVE_EOF);
2752 /* Any other return value indicates an error */
2753 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2754 "Bzip2 compression failed:"
2755 " BZ2_bzCompress() call returned status %d", r);
2756 return (ARCHIVE_FATAL);
2761 compression_end_bzip2(struct archive *a, struct la_zstream *lastrm)
2766 strm = (bz_stream *)lastrm->real_stream;
2767 r = BZ2_bzCompressEnd(strm);
2769 lastrm->real_stream = NULL;
2772 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2773 "Failed to clean up compressor");
2774 return (ARCHIVE_FATAL);
2776 return (ARCHIVE_OK);
2781 compression_init_encoder_bzip2(struct archive *a,
2782 struct la_zstream *lastrm, int level)
2785 (void) level; /* UNUSED */
2787 compression_end(a, lastrm);
2788 return (compression_unsupported_encoder(a, lastrm, "bzip2"));
2792 #if defined(HAVE_LZMA_H)
2794 compression_init_encoder_lzma(struct archive *a,
2795 struct la_zstream *lastrm, int level)
2797 static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
2799 lzma_options_lzma lzma_opt;
2803 compression_end(a, lastrm);
2804 if (lzma_lzma_preset(&lzma_opt, level)) {
2805 lastrm->real_stream = NULL;
2806 archive_set_error(a, ENOMEM,
2807 "Internal error initializing compression library");
2808 return (ARCHIVE_FATAL);
2810 strm = calloc(1, sizeof(*strm));
2812 archive_set_error(a, ENOMEM,
2813 "Can't allocate memory for lzma stream");
2814 return (ARCHIVE_FATAL);
2816 *strm = lzma_init_data;
2817 r = lzma_alone_encoder(strm, &lzma_opt);
2820 lastrm->real_stream = strm;
2822 lastrm->code = compression_code_lzma;
2823 lastrm->end = compression_end_lzma;
2826 case LZMA_MEM_ERROR:
2828 lastrm->real_stream = NULL;
2829 archive_set_error(a, ENOMEM,
2830 "Internal error initializing compression library: "
2831 "Cannot allocate memory");
2836 lastrm->real_stream = NULL;
2837 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2838 "Internal error initializing compression library: "
2839 "It's a bug in liblzma");
2847 compression_init_encoder_xz(struct archive *a,
2848 struct la_zstream *lastrm, int level)
2850 static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
2852 lzma_filter *lzmafilters;
2853 lzma_options_lzma lzma_opt;
2857 compression_end(a, lastrm);
2858 strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2);
2860 archive_set_error(a, ENOMEM,
2861 "Can't allocate memory for xz stream");
2862 return (ARCHIVE_FATAL);
2864 lzmafilters = (lzma_filter *)(strm+1);
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 lzmafilters[0].id = LZMA_FILTER_LZMA2;
2874 lzmafilters[0].options = &lzma_opt;
2875 lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
2877 *strm = lzma_init_data;
2878 r = lzma_stream_encoder(strm, lzmafilters, LZMA_CHECK_CRC64);
2881 lastrm->real_stream = strm;
2883 lastrm->code = compression_code_lzma;
2884 lastrm->end = compression_end_lzma;
2887 case LZMA_MEM_ERROR:
2889 lastrm->real_stream = NULL;
2890 archive_set_error(a, ENOMEM,
2891 "Internal error initializing compression library: "
2892 "Cannot allocate memory");
2897 lastrm->real_stream = NULL;
2898 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2899 "Internal error initializing compression library: "
2900 "It's a bug in liblzma");
2908 compression_code_lzma(struct archive *a,
2909 struct la_zstream *lastrm, enum la_zaction action)
2914 strm = (lzma_stream *)lastrm->real_stream;
2915 strm->next_in = lastrm->next_in;
2916 strm->avail_in = lastrm->avail_in;
2917 strm->total_in = lastrm->total_in;
2918 strm->next_out = lastrm->next_out;
2919 strm->avail_out = lastrm->avail_out;
2920 strm->total_out = lastrm->total_out;
2922 (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN);
2923 lastrm->next_in = strm->next_in;
2924 lastrm->avail_in = strm->avail_in;
2925 lastrm->total_in = strm->total_in;
2926 lastrm->next_out = strm->next_out;
2927 lastrm->avail_out = strm->avail_out;
2928 lastrm->total_out = strm->total_out;
2931 /* Non-finishing case */
2932 return (ARCHIVE_OK);
2933 case LZMA_STREAM_END:
2934 /* This return can only occur in finishing case. */
2935 return (ARCHIVE_EOF);
2936 case LZMA_MEMLIMIT_ERROR:
2937 archive_set_error(a, ENOMEM,
2938 "lzma compression error:"
2939 " %ju MiB would have been needed",
2940 (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1)
2942 return (ARCHIVE_FATAL);
2944 /* Any other return value indicates an error */
2945 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2946 "lzma compression failed:"
2947 " lzma_code() call returned status %d", r);
2948 return (ARCHIVE_FATAL);
2953 compression_end_lzma(struct archive *a, struct la_zstream *lastrm)
2957 (void)a; /* UNUSED */
2958 strm = (lzma_stream *)lastrm->real_stream;
2962 lastrm->real_stream = NULL;
2963 return (ARCHIVE_OK);
2967 compression_init_encoder_lzma(struct archive *a,
2968 struct la_zstream *lastrm, int level)
2971 (void) level; /* UNUSED */
2973 compression_end(a, lastrm);
2974 return (compression_unsupported_encoder(a, lastrm, "lzma"));
2977 compression_init_encoder_xz(struct archive *a,
2978 struct la_zstream *lastrm, int level)
2981 (void) level; /* UNUSED */
2983 compression_end(a, lastrm);
2984 return (compression_unsupported_encoder(a, lastrm, "xz"));
2989 xar_compression_init_encoder(struct archive_write *a)
2994 xar = (struct xar *)a->format_data;
2995 switch (xar->opt_compression) {
2997 r = compression_init_encoder_gzip(
2998 &(a->archive), &(xar->stream),
2999 xar->opt_compression_level, 1);
3002 r = compression_init_encoder_bzip2(
3003 &(a->archive), &(xar->stream),
3004 xar->opt_compression_level);
3007 r = compression_init_encoder_lzma(
3008 &(a->archive), &(xar->stream),
3009 xar->opt_compression_level);
3012 r = compression_init_encoder_xz(
3013 &(a->archive), &(xar->stream),
3014 xar->opt_compression_level);
3020 if (r == ARCHIVE_OK) {
3021 xar->stream.total_in = 0;
3022 xar->stream.next_out = xar->wbuff;
3023 xar->stream.avail_out = sizeof(xar->wbuff);
3024 xar->stream.total_out = 0;
3031 compression_code(struct archive *a, struct la_zstream *lastrm,
3032 enum la_zaction action)
3035 return (lastrm->code(a, lastrm, action));
3036 return (ARCHIVE_OK);
3040 compression_end(struct archive *a, struct la_zstream *lastrm)
3043 return (lastrm->end(a, lastrm));
3044 return (ARCHIVE_OK);
3049 save_xattrs(struct archive_write *a, struct file *file)
3054 struct heap_data *heap;
3058 xar = (struct xar *)a->format_data;
3059 count = archive_entry_xattr_reset(file->entry);
3061 return (ARCHIVE_OK);
3063 archive_entry_xattr_next(file->entry,
3064 &name, &value, &size);
3065 checksum_init(&(xar->a_sumwrk), xar->opt_sumalg);
3066 checksum_init(&(xar->e_sumwrk), xar->opt_sumalg);
3068 heap = calloc(1, sizeof(*heap));
3070 archive_set_error(&a->archive, ENOMEM,
3071 "Can't allocate memory for xattr");
3072 return (ARCHIVE_FATAL);
3074 heap->id = file->ea_idx++;
3075 heap->temp_offset = xar->temp_offset;
3076 heap->size = size;/* save a extracted size */
3077 heap->compression = xar->opt_compression;
3078 /* Get a extracted sumcheck value. */
3079 checksum_update(&(xar->e_sumwrk), value, size);
3080 checksum_final(&(xar->e_sumwrk), &(heap->e_sum));
3083 * Not compression to xattr is simple way.
3085 if (heap->compression == NONE) {
3086 checksum_update(&(xar->a_sumwrk), value, size);
3087 checksum_final(&(xar->a_sumwrk), &(heap->a_sum));
3088 if (write_to_temp(a, value, size)
3090 return (ARCHIVE_FATAL);
3091 heap->length = size;
3092 /* Add heap to the tail of file->xattr. */
3094 *file->xattr.last = heap;
3095 file->xattr.last = &(heap->next);
3101 * Init compression library.
3103 r = xar_compression_init_encoder(a);
3104 if (r != ARCHIVE_OK) {
3106 return (ARCHIVE_FATAL);
3109 xar->stream.next_in = (const unsigned char *)value;
3110 xar->stream.avail_in = size;
3112 r = compression_code(&(a->archive),
3113 &(xar->stream), ARCHIVE_Z_FINISH);
3114 if (r != ARCHIVE_OK && r != ARCHIVE_EOF) {
3116 return (ARCHIVE_FATAL);
3118 size = sizeof(xar->wbuff) - xar->stream.avail_out;
3119 checksum_update(&(xar->a_sumwrk),
3121 if (write_to_temp(a, xar->wbuff, size)
3123 return (ARCHIVE_FATAL);
3124 if (r == ARCHIVE_OK) {
3125 xar->stream.next_out = xar->wbuff;
3126 xar->stream.avail_out = sizeof(xar->wbuff);
3128 checksum_final(&(xar->a_sumwrk),
3130 heap->length = xar->stream.total_out;
3131 /* Add heap to the tail of file->xattr. */
3133 *file->xattr.last = heap;
3134 file->xattr.last = &(heap->next);
3138 /* Clean up compression library. */
3139 r = compression_end(&(a->archive), &(xar->stream));
3140 if (r != ARCHIVE_OK)
3141 return (ARCHIVE_FATAL);
3143 return (ARCHIVE_OK);
3147 getalgsize(enum sumalg sumalg)
3161 getalgname(enum sumalg sumalg)
3174 #endif /* Support xar format */