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_crypto_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 * libarcive 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 menber 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;
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;
246 struct chksumwork a_sumwrk; /* archived checksum. */
247 struct chksumwork e_sumwrk; /* extracted checksum. */
248 struct la_zstream stream;
249 struct archive_string_conv *sconv;
251 * Compressed data buffer.
253 unsigned char wbuff[1024 * 64];
254 size_t wbuff_remaining;
256 struct heap_data toc;
258 * The list of all file entries is used to manage struct file
260 * We use 'next' a menber of struct file to chain.
267 * The list of hard-linked file entries.
268 * We use 'hlnext' a menber of struct file to chain.
270 struct archive_rb_tree hardlink_rbtree;
273 static int xar_options(struct archive_write *,
274 const char *, const char *);
275 static int xar_write_header(struct archive_write *,
276 struct archive_entry *);
277 static ssize_t xar_write_data(struct archive_write *,
278 const void *, size_t);
279 static int xar_finish_entry(struct archive_write *);
280 static int xar_close(struct archive_write *);
281 static int xar_free(struct archive_write *);
283 static struct file *file_new(struct archive_write *a, struct archive_entry *);
284 static void file_free(struct file *);
285 static struct file *file_create_virtual_dir(struct archive_write *a, struct xar *,
287 static int file_add_child_tail(struct file *, struct file *);
288 static struct file *file_find_child(struct file *, const char *);
289 static int file_gen_utility_names(struct archive_write *,
291 static int get_path_component(char *, int, const char *);
292 static int file_tree(struct archive_write *, struct file **);
293 static void file_register(struct xar *, struct file *);
294 static void file_init_register(struct xar *);
295 static void file_free_register(struct xar *);
296 static int file_register_hardlink(struct archive_write *,
298 static void file_connect_hardlink_files(struct xar *);
299 static void file_init_hardlinks(struct xar *);
300 static void file_free_hardlinks(struct xar *);
302 static void checksum_init(struct chksumwork *, enum sumalg);
303 static void checksum_update(struct chksumwork *, const void *, size_t);
304 static void checksum_final(struct chksumwork *, struct chksumval *);
305 static int compression_init_encoder_gzip(struct archive *,
306 struct la_zstream *, int, int);
307 static int compression_code_gzip(struct archive *,
308 struct la_zstream *, enum la_zaction);
309 static int compression_end_gzip(struct archive *, struct la_zstream *);
310 static int compression_init_encoder_bzip2(struct archive *,
311 struct la_zstream *, int);
312 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
313 static int compression_code_bzip2(struct archive *,
314 struct la_zstream *, enum la_zaction);
315 static int compression_end_bzip2(struct archive *, struct la_zstream *);
317 static int compression_init_encoder_lzma(struct archive *,
318 struct la_zstream *, int);
319 static int compression_init_encoder_xz(struct archive *,
320 struct la_zstream *, int);
321 #if defined(HAVE_LZMA_H)
322 static int compression_code_lzma(struct archive *,
323 struct la_zstream *, enum la_zaction);
324 static int compression_end_lzma(struct archive *, struct la_zstream *);
326 static int xar_compression_init_encoder(struct archive_write *);
327 static int compression_code(struct archive *,
328 struct la_zstream *, enum la_zaction);
329 static int compression_end(struct archive *,
330 struct la_zstream *);
331 static int save_xattrs(struct archive_write *, struct file *);
332 static int getalgsize(enum sumalg);
333 static const char *getalgname(enum sumalg);
336 archive_write_set_format_xar(struct archive *_a)
338 struct archive_write *a = (struct archive_write *)_a;
341 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
342 ARCHIVE_STATE_NEW, "archive_write_set_format_xar");
344 /* If another format was already registered, unregister it. */
345 if (a->format_free != NULL)
348 xar = calloc(1, sizeof(*xar));
350 archive_set_error(&a->archive, ENOMEM,
351 "Can't allocate xar data");
352 return (ARCHIVE_FATAL);
355 file_init_register(xar);
356 file_init_hardlinks(xar);
357 archive_string_init(&(xar->tstr));
358 archive_string_init(&(xar->vstr));
361 * Create the root directory.
363 xar->root = file_create_virtual_dir(a, xar, "");
364 if (xar->root == NULL) {
366 archive_set_error(&a->archive, ENOMEM,
367 "Can't allocate xar data");
368 return (ARCHIVE_FATAL);
370 xar->root->parent = xar->root;
371 file_register(xar, xar->root);
372 xar->cur_dirent = xar->root;
373 archive_string_init(&(xar->cur_dirstr));
374 archive_string_ensure(&(xar->cur_dirstr), 1);
375 xar->cur_dirstr.s[0] = 0;
380 /* Set default checksum type. */
381 xar->opt_toc_sumalg = CKSUM_SHA1;
382 xar->opt_sumalg = CKSUM_SHA1;
383 /* Set default compression type and level. */
384 xar->opt_compression = GZIP;
385 xar->opt_compression_level = 6;
387 a->format_data = xar;
389 a->format_name = "xar";
390 a->format_options = xar_options;
391 a->format_write_header = xar_write_header;
392 a->format_write_data = xar_write_data;
393 a->format_finish_entry = xar_finish_entry;
394 a->format_close = xar_close;
395 a->format_free = xar_free;
396 a->archive.archive_format = ARCHIVE_FORMAT_XAR;
397 a->archive.archive_format_name = "xar";
403 xar_options(struct archive_write *a, const char *key, const char *value)
407 xar = (struct xar *)a->format_data;
409 if (strcmp(key, "checksum") == 0) {
411 xar->opt_sumalg = CKSUM_NONE;
412 else if (strcmp(value, "sha1") == 0)
413 xar->opt_sumalg = CKSUM_SHA1;
414 else if (strcmp(value, "md5") == 0)
415 xar->opt_sumalg = CKSUM_MD5;
417 archive_set_error(&(a->archive),
419 "Unknown checksum name: `%s'",
421 return (ARCHIVE_FAILED);
425 if (strcmp(key, "compression") == 0) {
426 const char *name = NULL;
429 xar->opt_compression = NONE;
430 else if (strcmp(value, "gzip") == 0)
431 xar->opt_compression = GZIP;
432 else if (strcmp(value, "bzip2") == 0)
433 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
434 xar->opt_compression = BZIP2;
438 else if (strcmp(value, "lzma") == 0)
440 xar->opt_compression = LZMA;
444 else if (strcmp(value, "xz") == 0)
446 xar->opt_compression = XZ;
451 archive_set_error(&(a->archive),
453 "Unknown compression name: `%s'",
455 return (ARCHIVE_FAILED);
458 archive_set_error(&(a->archive),
460 "`%s' compression not supported "
463 return (ARCHIVE_FAILED);
467 if (strcmp(key, "compression-level") == 0) {
469 !(value[0] >= '0' && value[0] <= '9') ||
471 archive_set_error(&(a->archive),
473 "Illegal value `%s'",
475 return (ARCHIVE_FAILED);
477 xar->opt_compression_level = value[0] - '0';
480 if (strcmp(key, "toc-checksum") == 0) {
482 xar->opt_toc_sumalg = CKSUM_NONE;
483 else if (strcmp(value, "sha1") == 0)
484 xar->opt_toc_sumalg = CKSUM_SHA1;
485 else if (strcmp(value, "md5") == 0)
486 xar->opt_toc_sumalg = CKSUM_MD5;
488 archive_set_error(&(a->archive),
490 "Unknown checksum name: `%s'",
492 return (ARCHIVE_FAILED);
497 /* Note: The "warn" return is just to inform the options
498 * supervisor that we didn't handle it. It will generate
499 * a suitable error if no one used this option. */
500 return (ARCHIVE_WARN);
504 xar_write_header(struct archive_write *a, struct archive_entry *entry)
508 struct archive_entry *file_entry;
511 xar = (struct xar *)a->format_data;
512 xar->cur_file = NULL;
513 xar->bytes_remaining = 0;
515 if (xar->sconv == NULL) {
516 xar->sconv = archive_string_conversion_to_charset(
517 &a->archive, "UTF-8", 1);
518 if (xar->sconv == NULL)
519 return (ARCHIVE_FATAL);
522 file = file_new(a, entry);
524 archive_set_error(&a->archive, ENOMEM,
525 "Can't allocate data");
526 return (ARCHIVE_FATAL);
528 r2 = file_gen_utility_names(a, file);
529 if (r2 < ARCHIVE_WARN)
533 * Ignore a path which looks like the top of directory name
534 * since we have already made the root directory of an Xar archive.
536 if (archive_strlen(&(file->parentdir)) == 0 &&
537 archive_strlen(&(file->basename)) == 0) {
542 /* Add entry into tree */
543 file_entry = file->entry;
544 r = file_tree(a, &file);
547 /* There is the same file in tree and
548 * the current file is older than the file in tree.
549 * So we don't need the current file data anymore. */
550 if (file->entry != file_entry)
553 file_register(xar, file);
555 /* A virtual file, which is a directory, does not have
556 * any contents and we won't store it into a archive
557 * file other than its name. */
562 * Prepare to save the contents of the file.
564 if (xar->temp_fd == -1) {
566 xar->temp_offset = 0;
567 xar->temp_fd = __archive_mktemp(NULL);
568 if (xar->temp_fd < 0) {
569 archive_set_error(&a->archive, errno,
570 "Couldn't create temporary file");
571 return (ARCHIVE_FATAL);
573 algsize = getalgsize(xar->opt_toc_sumalg);
575 if (lseek(xar->temp_fd, algsize, SEEK_SET) < 0) {
576 archive_set_error(&(a->archive), errno,
578 return (ARCHIVE_FATAL);
580 xar->temp_offset = algsize;
584 if (archive_entry_hardlink(file->entry) == NULL) {
585 r = save_xattrs(a, file);
587 return (ARCHIVE_FATAL);
590 /* Non regular files contents are unneeded to be saved to
591 * a temporary file. */
592 if (archive_entry_filetype(file->entry) != AE_IFREG)
596 * Set the current file to cur_file to read its contents.
598 xar->cur_file = file;
600 if (archive_entry_nlink(file->entry) > 1) {
601 r = file_register_hardlink(a, file);
604 if (archive_entry_hardlink(file->entry) != NULL) {
605 archive_entry_unset_size(file->entry);
610 /* Save a offset of current file in temporary file. */
611 file->data.temp_offset = xar->temp_offset;
612 file->data.size = archive_entry_size(file->entry);
613 file->data.compression = xar->opt_compression;
614 xar->bytes_remaining = archive_entry_size(file->entry);
615 checksum_init(&(xar->a_sumwrk), xar->opt_sumalg);
616 checksum_init(&(xar->e_sumwrk), xar->opt_sumalg);
617 r = xar_compression_init_encoder(a);
626 write_to_temp(struct archive_write *a, const void *buff, size_t s)
629 const unsigned char *p;
632 xar = (struct xar *)a->format_data;
633 p = (const unsigned char *)buff;
635 ws = write(xar->temp_fd, p, s);
637 archive_set_error(&(a->archive), errno,
638 "fwrite function failed");
639 return (ARCHIVE_FATAL);
643 xar->temp_offset += ws;
649 xar_write_data(struct archive_write *a, const void *buff, size_t s)
656 xar = (struct xar *)a->format_data;
658 if (s > xar->bytes_remaining)
659 s = (size_t)xar->bytes_remaining;
660 if (s == 0 || xar->cur_file == NULL)
662 if (xar->cur_file->data.compression == NONE) {
663 checksum_update(&(xar->e_sumwrk), buff, s);
664 checksum_update(&(xar->a_sumwrk), buff, s);
667 xar->stream.next_in = (const unsigned char *)buff;
668 xar->stream.avail_in = s;
669 if (xar->bytes_remaining > s)
672 run = ARCHIVE_Z_FINISH;
673 /* Compress file data. */
674 r = compression_code(&(a->archive), &(xar->stream), run);
675 if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
676 return (ARCHIVE_FATAL);
677 rsize = s - xar->stream.avail_in;
678 checksum_update(&(xar->e_sumwrk), buff, rsize);
679 size = sizeof(xar->wbuff) - xar->stream.avail_out;
680 checksum_update(&(xar->a_sumwrk), xar->wbuff, size);
682 #if !defined(_WIN32) || defined(__CYGWIN__)
683 if (xar->bytes_remaining ==
684 (uint64_t)archive_entry_size(xar->cur_file->entry)) {
686 * Get the path of a shell script if so.
688 const unsigned char *b = (const unsigned char *)buff;
690 archive_string_empty(&(xar->cur_file->script));
691 if (rsize > 2 && b[0] == '#' && b[1] == '!') {
698 if ((rsize - off) > PATH_MAX)
699 end = off + PATH_MAX;
703 /* Find the end of a script path. */
704 for (i = off; i < end && b[i] != '\0' &&
705 b[i] != '\n' && b[i] != '\r' &&
706 b[i] != ' ' && b[i] != '\t'; i++)
708 archive_strncpy(&(xar->cur_file->script), b + off,
714 if (xar->cur_file->data.compression == NONE) {
715 if (write_to_temp(a, buff, size) != ARCHIVE_OK)
716 return (ARCHIVE_FATAL);
718 if (write_to_temp(a, xar->wbuff, size) != ARCHIVE_OK)
719 return (ARCHIVE_FATAL);
721 xar->bytes_remaining -= rsize;
722 xar->cur_file->data.length += size;
728 xar_finish_entry(struct archive_write *a)
735 xar = (struct xar *)a->format_data;
736 if (xar->cur_file == NULL)
739 while (xar->bytes_remaining > 0) {
740 s = (size_t)xar->bytes_remaining;
741 if (s > a->null_length)
743 w = xar_write_data(a, a->nulls, s);
745 xar->bytes_remaining -= w;
749 file = xar->cur_file;
750 checksum_final(&(xar->e_sumwrk), &(file->data.e_sum));
751 checksum_final(&(xar->a_sumwrk), &(file->data.a_sum));
752 xar->cur_file = NULL;
758 xmlwrite_string_attr(struct archive_write *a, xmlTextWriterPtr writer,
759 const char *key, const char *value,
760 const char *attrkey, const char *attrvalue)
764 r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key));
766 archive_set_error(&a->archive,
768 "xmlTextWriterStartElement() failed: %d", r);
769 return (ARCHIVE_FATAL);
771 if (attrkey != NULL && attrvalue != NULL) {
772 r = xmlTextWriterWriteAttribute(writer,
773 BAD_CAST_CONST(attrkey), BAD_CAST_CONST(attrvalue));
775 archive_set_error(&a->archive,
777 "xmlTextWriterWriteAttribute() failed: %d", r);
778 return (ARCHIVE_FATAL);
782 r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value));
784 archive_set_error(&a->archive,
786 "xmlTextWriterWriteString() failed: %d", r);
787 return (ARCHIVE_FATAL);
790 r = xmlTextWriterEndElement(writer);
792 archive_set_error(&a->archive,
794 "xmlTextWriterEndElement() failed: %d", r);
795 return (ARCHIVE_FATAL);
801 xmlwrite_string(struct archive_write *a, xmlTextWriterPtr writer,
802 const char *key, const char *value)
809 r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key));
811 archive_set_error(&a->archive,
813 "xmlTextWriterStartElement() failed: %d", r);
814 return (ARCHIVE_FATAL);
817 r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value));
819 archive_set_error(&a->archive,
821 "xmlTextWriterWriteString() failed: %d", r);
822 return (ARCHIVE_FATAL);
825 r = xmlTextWriterEndElement(writer);
827 archive_set_error(&a->archive,
829 "xmlTextWriterEndElement() failed: %d", r);
830 return (ARCHIVE_FATAL);
836 xmlwrite_fstring(struct archive_write *a, xmlTextWriterPtr writer,
837 const char *key, const char *fmt, ...)
842 xar = (struct xar *)a->format_data;
844 archive_string_empty(&xar->vstr);
845 archive_string_vsprintf(&xar->vstr, fmt, ap);
847 return (xmlwrite_string(a, writer, key, xar->vstr.s));
851 xmlwrite_time(struct archive_write *a, xmlTextWriterPtr writer,
852 const char *key, time_t t, int z)
857 #if defined(HAVE_GMTIME_R)
859 #elif defined(HAVE__GMTIME64_S)
860 _gmtime64_s(&tm, &t);
862 memcpy(&tm, gmtime(&t), sizeof(tm));
864 memset(×tr, 0, sizeof(timestr));
865 /* Do not use %F and %T for portability. */
866 strftime(timestr, sizeof(timestr), "%Y-%m-%dT%H:%M:%S", &tm);
868 strcat(timestr, "Z");
869 return (xmlwrite_string(a, writer, key, timestr));
873 xmlwrite_mode(struct archive_write *a, xmlTextWriterPtr writer,
874 const char *key, mode_t mode)
879 ms[1] = '0' + ((mode >> 6) & 07);
880 ms[2] = '0' + ((mode >> 3) & 07);
881 ms[3] = '0' + (mode & 07);
884 return (xmlwrite_string(a, writer, key, ms));
888 xmlwrite_sum(struct archive_write *a, xmlTextWriterPtr writer,
889 const char *key, struct chksumval *sum)
893 char buff[MAX_SUM_SIZE*2 + 1];
899 algname = getalgname(sum->alg);
900 algsize = getalgsize(sum->alg);
901 if (algname != NULL) {
902 const char *hex = "0123456789abcdef";
905 for (i = 0; i < algsize; i++) {
906 *p++ = hex[(*s >> 4)];
907 *p++ = hex[(*s & 0x0f)];
911 r = xmlwrite_string_attr(a, writer,
915 return (ARCHIVE_FATAL);
922 xmlwrite_heap(struct archive_write *a, xmlTextWriterPtr writer,
923 struct heap_data *heap)
928 r = xmlwrite_fstring(a, writer, "length", "%ju", heap->length);
930 return (ARCHIVE_FATAL);
931 r = xmlwrite_fstring(a, writer, "offset", "%ju", heap->temp_offset);
933 return (ARCHIVE_FATAL);
934 r = xmlwrite_fstring(a, writer, "size", "%ju", heap->size);
936 return (ARCHIVE_FATAL);
937 switch (heap->compression) {
939 encname = "application/x-gzip"; break;
941 encname = "application/x-bzip2"; break;
943 encname = "application/x-lzma"; break;
945 encname = "application/x-xz"; break;
947 encname = "application/octet-stream"; break;
949 r = xmlwrite_string_attr(a, writer, "encoding", NULL,
952 return (ARCHIVE_FATAL);
953 r = xmlwrite_sum(a, writer, "archived-checksum", &(heap->a_sum));
955 return (ARCHIVE_FATAL);
956 r = xmlwrite_sum(a, writer, "extracted-checksum", &(heap->e_sum));
958 return (ARCHIVE_FATAL);
963 * xar utility records fflags as following xml elements:
973 * If xar is running on BSD platform, records <flags>..</flags>;
974 * if xar is running on linux platform, records <ext2>..</ext2>;
975 * otherwise does not record.
977 * Our implements records both <flags> and <ext2> if it's necessary.
980 make_fflags_entry(struct archive_write *a, xmlTextWriterPtr writer,
981 const char *element, const char *fflags_text)
983 static const struct flagentry {
988 { "sappnd", "SystemAppend"},
989 { "sappend", "SystemAppend"},
990 { "arch", "SystemArchived"},
991 { "archived", "SystemArchived"},
992 { "schg", "SystemImmutable"},
993 { "schange", "SystemImmutable"},
994 { "simmutable", "SystemImmutable"},
995 { "nosunlnk", "SystemNoUnlink"},
996 { "nosunlink", "SystemNoUnlink"},
997 { "snapshot", "SystemSnapshot"},
998 { "uappnd", "UserAppend"},
999 { "uappend", "UserAppend"},
1000 { "uchg", "UserImmutable"},
1001 { "uchange", "UserImmutable"},
1002 { "uimmutable", "UserImmutable"},
1003 { "nodump", "UserNoDump"},
1004 { "noopaque", "UserOpaque"},
1005 { "nouunlnk", "UserNoUnlink"},
1006 { "nouunlink", "UserNoUnlink"},
1010 { "sappnd", "AppendOnly"},
1011 { "sappend", "AppendOnly"},
1012 { "schg", "Immutable"},
1013 { "schange", "Immutable"},
1014 { "simmutable", "Immutable"},
1015 { "nodump", "NoDump"},
1016 { "nouunlnk", "Undelete"},
1017 { "nouunlink", "Undelete"},
1018 { "btree", "BTree"},
1019 { "comperr", "CompError"},
1020 { "compress", "Compress"},
1021 { "noatime", "NoAtime"},
1022 { "compdirty", "CompDirty"},
1023 { "comprblk", "CompBlock"},
1024 { "dirsync", "DirSync"},
1025 { "hashidx", "HashIndexed"},
1026 { "imagic", "iMagic"},
1027 { "journal", "Journaled"},
1028 { "securedeletion", "SecureDeletion"},
1029 { "sync", "Synchronous"},
1030 { "notail", "NoTail"},
1031 { "topdir", "TopDir"},
1032 { "reserved", "Reserved"},
1035 const struct flagentry *fe, *flagentry;
1036 #define FLAGENTRY_MAXSIZE ((sizeof(flagbsd)+sizeof(flagext2))/sizeof(flagbsd))
1037 const struct flagentry *avail[FLAGENTRY_MAXSIZE];
1041 if (strcmp(element, "ext2") == 0)
1042 flagentry = flagext2;
1044 flagentry = flagbsd;
1050 cp = strchr(p, ',');
1054 for (fe = flagentry; fe->name != NULL; fe++) {
1055 if (fe->name[cp - p] != '\0'
1056 || p[0] != fe->name[0])
1058 if (strncmp(p, fe->name, cp - p) == 0) {
1067 } while (p != NULL);
1070 r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(element));
1072 archive_set_error(&a->archive,
1074 "xmlTextWriterStartElement() failed: %d", r);
1075 return (ARCHIVE_FATAL);
1077 for (i = 0; i < n; i++) {
1078 r = xmlwrite_string(a, writer,
1079 avail[i]->xarname, NULL);
1080 if (r != ARCHIVE_OK)
1084 r = xmlTextWriterEndElement(writer);
1086 archive_set_error(&a->archive,
1088 "xmlTextWriterEndElement() failed: %d", r);
1089 return (ARCHIVE_FATAL);
1092 return (ARCHIVE_OK);
1096 make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
1100 const char *filetype, *filelink, *fflags;
1101 struct archive_string linkto;
1102 struct heap_data *heap;
1108 xar = (struct xar *)a->format_data;
1112 * Make a file name entry, "<name>".
1114 l = ll = archive_strlen(&(file->basename));
1117 archive_set_error(&a->archive, ENOMEM,
1118 "Can't allocate memory");
1119 return (ARCHIVE_FATAL);
1121 r = UTF8Toisolat1(tmp, &l, BAD_CAST(file->basename.s), &ll);
1124 r = xmlTextWriterStartElement(writer, BAD_CAST("name"));
1126 archive_set_error(&a->archive,
1128 "xmlTextWriterStartElement() failed: %d", r);
1129 return (ARCHIVE_FATAL);
1131 r = xmlTextWriterWriteAttribute(writer,
1132 BAD_CAST("enctype"), BAD_CAST("base64"));
1134 archive_set_error(&a->archive,
1136 "xmlTextWriterWriteAttribute() failed: %d", r);
1137 return (ARCHIVE_FATAL);
1139 r = xmlTextWriterWriteBase64(writer, file->basename.s,
1140 0, archive_strlen(&(file->basename)));
1142 archive_set_error(&a->archive,
1144 "xmlTextWriterWriteBase64() failed: %d", r);
1145 return (ARCHIVE_FATAL);
1147 r = xmlTextWriterEndElement(writer);
1149 archive_set_error(&a->archive,
1151 "xmlTextWriterEndElement() failed: %d", r);
1152 return (ARCHIVE_FATAL);
1155 r = xmlwrite_string(a, writer, "name", file->basename.s);
1157 return (ARCHIVE_FATAL);
1161 * Make a file type entry, "<type>".
1164 archive_string_init(&linkto);
1165 switch (archive_entry_filetype(file->entry)) {
1167 filetype = "directory"; break;
1169 filetype = "symlink"; break;
1171 filetype = "character special"; break;
1173 filetype = "block special"; break;
1175 filetype = "socket"; break;
1177 filetype = "fifo"; break;
1180 if (file->hardlink_target != NULL) {
1181 filetype = "hardlink";
1183 if (file->hardlink_target == file)
1184 archive_strcpy(&linkto, "original");
1186 archive_string_sprintf(&linkto, "%d",
1187 file->hardlink_target->id);
1192 r = xmlwrite_string_attr(a, writer, "type", filetype,
1193 filelink, linkto.s);
1194 archive_string_free(&linkto);
1196 return (ARCHIVE_FATAL);
1199 * On a virtual directory, we record "name" and "type" only.
1202 return (ARCHIVE_OK);
1204 switch (archive_entry_filetype(file->entry)) {
1207 * xar utility has checked a file type, which
1208 * a symblic-link file has referenced.
1210 * <link type="directory">../ref/</link>
1211 * The symlink target file is "../ref/" and its
1212 * file type is a directory.
1214 * <link type="file">../f</link>
1215 * The symlink target file is "../f" and its
1216 * file type is a regular file.
1218 * But our implemention cannot do it, and then we
1219 * always record that a attribute "type" is "borken",
1221 * <link type="broken">foo/bar</link>
1222 * It means "foo/bar" is not reachable.
1224 r = xmlwrite_string_attr(a, writer, "link",
1228 return (ARCHIVE_FATAL);
1232 r = xmlTextWriterStartElement(writer, BAD_CAST("device"));
1234 archive_set_error(&a->archive,
1236 "xmlTextWriterStartElement() failed: %d", r);
1237 return (ARCHIVE_FATAL);
1239 r = xmlwrite_fstring(a, writer, "major",
1240 "%d", archive_entry_rdevmajor(file->entry));
1242 return (ARCHIVE_FATAL);
1243 r = xmlwrite_fstring(a, writer, "minor",
1244 "%d", archive_entry_rdevminor(file->entry));
1246 return (ARCHIVE_FATAL);
1247 r = xmlTextWriterEndElement(writer);
1249 archive_set_error(&a->archive,
1251 "xmlTextWriterEndElement() failed: %d", r);
1252 return (ARCHIVE_FATAL);
1260 * Make a inode entry, "<inode>".
1262 r = xmlwrite_fstring(a, writer, "inode",
1263 "%jd", archive_entry_ino64(file->entry));
1265 return (ARCHIVE_FATAL);
1266 if (archive_entry_dev(file->entry) != 0) {
1267 r = xmlwrite_fstring(a, writer, "deviceno",
1268 "%d", archive_entry_dev(file->entry));
1270 return (ARCHIVE_FATAL);
1274 * Make a file mode entry, "<mode>".
1276 r = xmlwrite_mode(a, writer, "mode",
1277 archive_entry_mode(file->entry));
1279 return (ARCHIVE_FATAL);
1282 * Make a user entry, "<uid>" and "<user>.
1284 r = xmlwrite_fstring(a, writer, "uid",
1285 "%d", archive_entry_uid(file->entry));
1287 return (ARCHIVE_FATAL);
1288 r = archive_entry_uname_l(file->entry, &p, &len, xar->sconv);
1290 if (errno == ENOMEM) {
1291 archive_set_error(&a->archive, ENOMEM,
1292 "Can't allocate memory for Uname");
1293 return (ARCHIVE_FATAL);
1295 archive_set_error(&a->archive,
1296 ARCHIVE_ERRNO_FILE_FORMAT,
1297 "Can't translate uname '%s' to UTF-8",
1298 archive_entry_uname(file->entry));
1302 r = xmlwrite_string(a, writer, "user", p);
1304 return (ARCHIVE_FATAL);
1308 * Make a group entry, "<gid>" and "<group>.
1310 r = xmlwrite_fstring(a, writer, "gid",
1311 "%d", archive_entry_gid(file->entry));
1313 return (ARCHIVE_FATAL);
1314 r = archive_entry_gname_l(file->entry, &p, &len, xar->sconv);
1316 if (errno == ENOMEM) {
1317 archive_set_error(&a->archive, ENOMEM,
1318 "Can't allocate memory for Gname");
1319 return (ARCHIVE_FATAL);
1321 archive_set_error(&a->archive,
1322 ARCHIVE_ERRNO_FILE_FORMAT,
1323 "Can't translate gname '%s' to UTF-8",
1324 archive_entry_gname(file->entry));
1328 r = xmlwrite_string(a, writer, "group", p);
1330 return (ARCHIVE_FATAL);
1334 * Make a ctime entry, "<ctime>".
1336 if (archive_entry_ctime_is_set(file->entry)) {
1337 r = xmlwrite_time(a, writer, "ctime",
1338 archive_entry_ctime(file->entry), 1);
1340 return (ARCHIVE_FATAL);
1344 * Make a mtime entry, "<mtime>".
1346 if (archive_entry_mtime_is_set(file->entry)) {
1347 r = xmlwrite_time(a, writer, "mtime",
1348 archive_entry_mtime(file->entry), 1);
1350 return (ARCHIVE_FATAL);
1354 * Make a atime entry, "<atime>".
1356 if (archive_entry_atime_is_set(file->entry)) {
1357 r = xmlwrite_time(a, writer, "atime",
1358 archive_entry_atime(file->entry), 1);
1360 return (ARCHIVE_FATAL);
1364 * Make fflags entries, "<flags>" and "<ext2>".
1366 fflags = archive_entry_fflags_text(file->entry);
1367 if (fflags != NULL) {
1368 r = make_fflags_entry(a, writer, "flags", fflags);
1371 r = make_fflags_entry(a, writer, "ext2", fflags);
1377 * Make extended attribute entries, "<ea>".
1379 archive_entry_xattr_reset(file->entry);
1380 for (heap = file->xattr.first; heap != NULL; heap = heap->next) {
1385 archive_entry_xattr_next(file->entry,
1386 &name, &value, &size);
1387 r = xmlTextWriterStartElement(writer, BAD_CAST("ea"));
1389 archive_set_error(&a->archive,
1391 "xmlTextWriterStartElement() failed: %d", r);
1392 return (ARCHIVE_FATAL);
1394 r = xmlTextWriterWriteFormatAttribute(writer,
1395 BAD_CAST("id"), "%d", heap->id);
1397 archive_set_error(&a->archive,
1399 "xmlTextWriterWriteAttribute() failed: %d", r);
1400 return (ARCHIVE_FATAL);
1402 r = xmlwrite_heap(a, writer, heap);
1404 return (ARCHIVE_FATAL);
1405 r = xmlwrite_string(a, writer, "name", name);
1407 return (ARCHIVE_FATAL);
1409 r = xmlTextWriterEndElement(writer);
1411 archive_set_error(&a->archive,
1413 "xmlTextWriterEndElement() failed: %d", r);
1414 return (ARCHIVE_FATAL);
1419 * Make a file data entry, "<data>".
1421 if (file->data.length > 0) {
1422 r = xmlTextWriterStartElement(writer, BAD_CAST("data"));
1424 archive_set_error(&a->archive,
1426 "xmlTextWriterStartElement() failed: %d", r);
1427 return (ARCHIVE_FATAL);
1430 r = xmlwrite_heap(a, writer, &(file->data));
1432 return (ARCHIVE_FATAL);
1434 r = xmlTextWriterEndElement(writer);
1436 archive_set_error(&a->archive,
1438 "xmlTextWriterEndElement() failed: %d", r);
1439 return (ARCHIVE_FATAL);
1443 if (archive_strlen(&file->script) > 0) {
1444 r = xmlTextWriterStartElement(writer, BAD_CAST("content"));
1446 archive_set_error(&a->archive,
1448 "xmlTextWriterStartElement() failed: %d", r);
1449 return (ARCHIVE_FATAL);
1452 r = xmlwrite_string(a, writer,
1453 "interpreter", file->script.s);
1455 return (ARCHIVE_FATAL);
1457 r = xmlwrite_string(a, writer, "type", "script");
1459 return (ARCHIVE_FATAL);
1461 r = xmlTextWriterEndElement(writer);
1463 archive_set_error(&a->archive,
1465 "xmlTextWriterEndElement() failed: %d", r);
1466 return (ARCHIVE_FATAL);
1477 make_toc(struct archive_write *a)
1482 xmlTextWriterPtr writer;
1486 xar = (struct xar *)a->format_data;
1488 ret = ARCHIVE_FATAL;
1491 * Initialize xml writer.
1494 bp = xmlBufferCreate();
1496 archive_set_error(&a->archive, ENOMEM,
1497 "xmlBufferCreate() "
1498 "couldn't create xml buffer");
1501 writer = xmlNewTextWriterMemory(bp, 0);
1502 if (writer == NULL) {
1503 archive_set_error(&a->archive,
1505 "xmlNewTextWriterMemory() "
1506 "couldn't create xml writer");
1509 r = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL);
1511 archive_set_error(&a->archive,
1513 "xmlTextWriterStartDocument() failed: %d", r);
1516 r = xmlTextWriterSetIndent(writer, 4);
1518 archive_set_error(&a->archive,
1520 "xmlTextWriterSetIndent() failed: %d", r);
1525 * Start recoding TOC
1527 r = xmlTextWriterStartElement(writer, BAD_CAST("xar"));
1529 archive_set_error(&a->archive,
1531 "xmlTextWriterStartElement() failed: %d", r);
1534 r = xmlTextWriterStartElement(writer, BAD_CAST("toc"));
1536 archive_set_error(&a->archive,
1538 "xmlTextWriterStartDocument() failed: %d", r);
1543 * Record the creation time of the archive file.
1545 r = xmlwrite_time(a, writer, "creation-time", time(NULL), 0);
1550 * Record the checksum value of TOC
1552 algsize = getalgsize(xar->opt_toc_sumalg);
1555 * Record TOC checksum
1557 r = xmlTextWriterStartElement(writer, BAD_CAST("checksum"));
1559 archive_set_error(&a->archive,
1561 "xmlTextWriterStartElement() failed: %d", r);
1564 r = xmlTextWriterWriteAttribute(writer, BAD_CAST("style"),
1565 BAD_CAST_CONST(getalgname(xar->opt_toc_sumalg)));
1567 archive_set_error(&a->archive,
1569 "xmlTextWriterWriteAttribute() failed: %d", r);
1574 * Record the offset of the value of checksum of TOC
1576 r = xmlwrite_string(a, writer, "offset", "0");
1581 * Record the size of the value of checksum of TOC
1583 r = xmlwrite_fstring(a, writer, "size", "%d", algsize);
1587 r = xmlTextWriterEndElement(writer);
1589 archive_set_error(&a->archive,
1591 "xmlTextWriterEndElement() failed: %d", r);
1598 if (np != np->parent) {
1599 r = make_file_entry(a, writer, np);
1600 if (r != ARCHIVE_OK)
1604 if (np->dir && np->children.first != NULL) {
1605 /* Enter to sub directories. */
1606 np = np->children.first;
1607 r = xmlTextWriterStartElement(writer,
1610 archive_set_error(&a->archive,
1612 "xmlTextWriterStartElement() "
1616 r = xmlTextWriterWriteFormatAttribute(
1617 writer, BAD_CAST("id"), "%d", np->id);
1619 archive_set_error(&a->archive,
1621 "xmlTextWriterWriteAttribute() "
1627 while (np != np->parent) {
1628 r = xmlTextWriterEndElement(writer);
1630 archive_set_error(&a->archive,
1632 "xmlTextWriterEndElement() "
1636 if (np->chnext == NULL) {
1637 /* Return to the parent directory. */
1641 r = xmlTextWriterStartElement(writer,
1644 archive_set_error(&a->archive,
1646 "xmlTextWriterStartElement() "
1650 r = xmlTextWriterWriteFormatAttribute(
1651 writer, BAD_CAST("id"), "%d", np->id);
1653 archive_set_error(&a->archive,
1655 "xmlTextWriterWriteAttribute() "
1662 } while (np != np->parent);
1664 r = xmlTextWriterEndDocument(writer);
1666 archive_set_error(&a->archive,
1668 "xmlTextWriterEndDocument() failed: %d", r);
1672 fprintf(stderr, "\n---TOC-- %d bytes --\n%s\n",
1673 strlen((const char *)bp->content), bp->content);
1677 * Compress the TOC and calculate the sum of the TOC.
1679 xar->toc.temp_offset = xar->temp_offset;
1680 xar->toc.size = bp->use;
1681 checksum_init(&(xar->a_sumwrk), xar->opt_toc_sumalg);
1683 r = compression_init_encoder_gzip(&(a->archive),
1684 &(xar->stream), 6, 1);
1685 if (r != ARCHIVE_OK)
1687 xar->stream.next_in = bp->content;
1688 xar->stream.avail_in = bp->use;
1689 xar->stream.total_in = 0;
1690 xar->stream.next_out = xar->wbuff;
1691 xar->stream.avail_out = sizeof(xar->wbuff);
1692 xar->stream.total_out = 0;
1696 r = compression_code(&(a->archive),
1697 &(xar->stream), ARCHIVE_Z_FINISH);
1698 if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
1700 size = sizeof(xar->wbuff) - xar->stream.avail_out;
1701 checksum_update(&(xar->a_sumwrk), xar->wbuff, size);
1702 if (write_to_temp(a, xar->wbuff, size) != ARCHIVE_OK)
1704 if (r == ARCHIVE_EOF)
1706 xar->stream.next_out = xar->wbuff;
1707 xar->stream.avail_out = sizeof(xar->wbuff);
1709 r = compression_end(&(a->archive), &(xar->stream));
1710 if (r != ARCHIVE_OK)
1712 xar->toc.length = xar->stream.total_out;
1713 xar->toc.compression = GZIP;
1714 checksum_final(&(xar->a_sumwrk), &(xar->toc.a_sum));
1719 xmlFreeTextWriter(writer);
1727 flush_wbuff(struct archive_write *a)
1733 xar = (struct xar *)a->format_data;
1734 s = sizeof(xar->wbuff) - xar->wbuff_remaining;
1735 r = __archive_write_output(a, xar->wbuff, s);
1736 if (r != ARCHIVE_OK)
1738 xar->wbuff_remaining = sizeof(xar->wbuff);
1743 copy_out(struct archive_write *a, uint64_t offset, uint64_t length)
1748 xar = (struct xar *)a->format_data;
1749 if (lseek(xar->temp_fd, offset, SEEK_SET) < 0) {
1750 archive_set_error(&(a->archive), errno, "lseek failed");
1751 return (ARCHIVE_FATAL);
1758 if (length > xar->wbuff_remaining)
1759 rsize = xar->wbuff_remaining;
1761 rsize = (size_t)length;
1762 wb = xar->wbuff + (sizeof(xar->wbuff) - xar->wbuff_remaining);
1763 rs = read(xar->temp_fd, wb, rsize);
1765 archive_set_error(&(a->archive), errno,
1766 "Can't read temporary file(%jd)",
1768 return (ARCHIVE_FATAL);
1771 archive_set_error(&(a->archive), 0,
1772 "Truncated xar archive");
1773 return (ARCHIVE_FATAL);
1775 xar->wbuff_remaining -= rs;
1777 if (xar->wbuff_remaining == 0) {
1779 if (r != ARCHIVE_OK)
1783 return (ARCHIVE_OK);
1787 xar_close(struct archive_write *a)
1794 xar = (struct xar *)a->format_data;
1797 if (xar->root->children.first == NULL)
1798 return (ARCHIVE_OK);
1800 /* Save the length of all file extended attributes and contents. */
1801 length = xar->temp_offset;
1803 /* Connect hardlinked files */
1804 file_connect_hardlink_files(xar);
1808 if (r != ARCHIVE_OK)
1811 * Make the xar header on wbuff(write buffer).
1814 xar->wbuff_remaining = sizeof(xar->wbuff);
1815 archive_be32enc(&wb[0], HEADER_MAGIC);
1816 archive_be16enc(&wb[4], HEADER_SIZE);
1817 archive_be16enc(&wb[6], HEADER_VERSION);
1818 archive_be64enc(&wb[8], xar->toc.length);
1819 archive_be64enc(&wb[16], xar->toc.size);
1820 archive_be32enc(&wb[24], xar->toc.a_sum.alg);
1821 xar->wbuff_remaining -= HEADER_SIZE;
1826 r = copy_out(a, xar->toc.temp_offset, xar->toc.length);
1827 if (r != ARCHIVE_OK)
1830 /* Write the checksum value of the TOC. */
1831 if (xar->toc.a_sum.len) {
1832 if (xar->wbuff_remaining < xar->toc.a_sum.len) {
1834 if (r != ARCHIVE_OK)
1837 wb = xar->wbuff + (sizeof(xar->wbuff) - xar->wbuff_remaining);
1838 memcpy(wb, xar->toc.a_sum.val, xar->toc.a_sum.len);
1839 xar->wbuff_remaining -= xar->toc.a_sum.len;
1843 * Write all file extended attributes and contents.
1845 r = copy_out(a, xar->toc.a_sum.len, length);
1846 if (r != ARCHIVE_OK)
1853 xar_free(struct archive_write *a)
1857 xar = (struct xar *)a->format_data;
1858 archive_string_free(&(xar->cur_dirstr));
1859 archive_string_free(&(xar->tstr));
1860 archive_string_free(&(xar->vstr));
1861 file_free_hardlinks(xar);
1862 file_free_register(xar);
1863 compression_end(&(a->archive), &(xar->stream));
1866 return (ARCHIVE_OK);
1870 file_cmp_node(const struct archive_rb_node *n1,
1871 const struct archive_rb_node *n2)
1873 const struct file *f1 = (const struct file *)n1;
1874 const struct file *f2 = (const struct file *)n2;
1876 return (strcmp(f1->basename.s, f2->basename.s));
1880 file_cmp_key(const struct archive_rb_node *n, const void *key)
1882 const struct file *f = (const struct file *)n;
1884 return (strcmp(f->basename.s, (const char *)key));
1887 static struct file *
1888 file_new(struct archive_write *a, struct archive_entry *entry)
1891 static const struct archive_rb_tree_ops rb_ops = {
1892 file_cmp_node, file_cmp_key
1895 file = calloc(1, sizeof(*file));
1900 file->entry = archive_entry_clone(entry);
1902 file->entry = archive_entry_new2(&a->archive);
1903 if (file->entry == NULL) {
1907 __archive_rb_tree_init(&(file->rbtree), &rb_ops);
1908 file->children.first = NULL;
1909 file->children.last = &(file->children.first);
1910 file->xattr.first = NULL;
1911 file->xattr.last = &(file->xattr.first);
1912 archive_string_init(&(file->parentdir));
1913 archive_string_init(&(file->basename));
1914 archive_string_init(&(file->symlink));
1915 archive_string_init(&(file->script));
1916 if (entry != NULL && archive_entry_filetype(entry) == AE_IFDIR)
1923 file_free(struct file *file)
1925 struct heap_data *heap, *next_heap;
1927 heap = file->xattr.first;
1928 while (heap != NULL) {
1929 next_heap = heap->next;
1933 archive_string_free(&(file->parentdir));
1934 archive_string_free(&(file->basename));
1935 archive_string_free(&(file->symlink));
1936 archive_string_free(&(file->script));
1940 static struct file *
1941 file_create_virtual_dir(struct archive_write *a, struct xar *xar,
1942 const char *pathname)
1946 (void)xar; /* UNUSED */
1948 file = file_new(a, NULL);
1951 archive_entry_set_pathname(file->entry, pathname);
1952 archive_entry_set_mode(file->entry, 0555 | AE_IFDIR);
1961 file_add_child_tail(struct file *parent, struct file *child)
1963 if (!__archive_rb_tree_insert_node(
1964 &(parent->rbtree), (struct archive_rb_node *)child))
1966 child->chnext = NULL;
1967 *parent->children.last = child;
1968 parent->children.last = &(child->chnext);
1969 child->parent = parent;
1974 * Find a entry from `parent'
1976 static struct file *
1977 file_find_child(struct file *parent, const char *child_name)
1981 np = (struct file *)__archive_rb_tree_find_node(
1982 &(parent->rbtree), child_name);
1986 #if defined(_WIN32) || defined(__CYGWIN__)
1988 cleanup_backslash(char *utf8, size_t len)
1991 /* Convert a path-separator from '\' to '/' */
1992 while (*utf8 != '\0' && len) {
2000 #define cleanup_backslash(p, len) /* nop */
2004 * Generate a parent directory name and a base name from a pathname.
2007 file_gen_utility_names(struct archive_write *a, struct file *file)
2011 char *p, *dirname, *slash;
2015 xar = (struct xar *)a->format_data;
2016 archive_string_empty(&(file->parentdir));
2017 archive_string_empty(&(file->basename));
2018 archive_string_empty(&(file->symlink));
2020 if (file->parent == file)/* virtual root */
2021 return (ARCHIVE_OK);
2023 if (archive_entry_pathname_l(file->entry, &pp, &len, xar->sconv)
2025 if (errno == ENOMEM) {
2026 archive_set_error(&a->archive, ENOMEM,
2027 "Can't allocate memory for Pathname");
2028 return (ARCHIVE_FATAL);
2030 archive_set_error(&a->archive,
2031 ARCHIVE_ERRNO_FILE_FORMAT,
2032 "Can't translate pathname '%s' to UTF-8",
2033 archive_entry_pathname(file->entry));
2036 archive_strncpy(&(file->parentdir), pp, len);
2037 len = file->parentdir.length;
2038 p = dirname = file->parentdir.s;
2040 * Convert a path-separator from '\' to '/'
2042 cleanup_backslash(p, len);
2045 * Remove leading '/', '../' and './' elements
2051 } else if (p[0] != '.')
2053 else if (p[1] == '.' && p[2] == '/') {
2056 } else if (p[1] == '/' || (p[1] == '.' && p[2] == '\0')) {
2059 } else if (p[1] == '\0') {
2066 memmove(dirname, p, len+1);
2070 * Remove "/","/." and "/.." elements from tail.
2075 if (len > 0 && p[len-1] == '/') {
2079 if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
2083 if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
2094 /* Convert '//' --> '/' */
2096 else if (p[1] == '.' && p[2] == '/')
2097 /* Convert '/./' --> '/' */
2099 else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
2100 /* Convert 'dir/dir1/../dir2/'
2104 while (rp >= dirname) {
2113 strcpy(dirname, p+4);
2124 if (archive_entry_filetype(file->entry) == AE_IFLNK) {
2126 /* Convert symlink name too. */
2127 if (archive_entry_symlink_l(file->entry, &pp, &len2,
2129 if (errno == ENOMEM) {
2130 archive_set_error(&a->archive, ENOMEM,
2131 "Can't allocate memory for Linkname");
2132 return (ARCHIVE_FATAL);
2134 archive_set_error(&a->archive,
2135 ARCHIVE_ERRNO_FILE_FORMAT,
2136 "Can't translate symlink '%s' to UTF-8",
2137 archive_entry_symlink(file->entry));
2140 archive_strncpy(&(file->symlink), pp, len2);
2141 cleanup_backslash(file->symlink.s, file->symlink.length);
2144 * - Count up directory elements.
2145 * - Find out the position which points the last position of
2146 * path separator('/').
2149 for (; *p != '\0'; p++)
2152 if (slash == NULL) {
2153 /* The pathname doesn't have a parent directory. */
2154 file->parentdir.length = len;
2155 archive_string_copy(&(file->basename), &(file->parentdir));
2156 archive_string_empty(&(file->parentdir));
2157 file->parentdir.s = '\0';
2161 /* Make a basename from dirname and slash */
2163 file->parentdir.length = slash - dirname;
2164 archive_strcpy(&(file->basename), slash + 1);
2169 get_path_component(char *name, int n, const char *fn)
2174 p = strchr(fn, '/');
2176 if ((l = strlen(fn)) == 0)
2182 memcpy(name, fn, l);
2189 * Add a new entry into the tree.
2192 file_tree(struct archive_write *a, struct file **filepp)
2194 #if defined(_WIN32) && !defined(__CYGWIN__)
2195 char name[_MAX_FNAME];/* Included null terminator size. */
2196 #elif defined(NAME_MAX) && NAME_MAX >= 255
2197 char name[NAME_MAX+1];
2201 struct xar *xar = (struct xar *)a->format_data;
2202 struct file *dent, *file, *np;
2203 struct archive_entry *ent;
2209 if (file->parentdir.length > 0)
2210 fn = p = file->parentdir.s;
2215 * If the path of the parent directory of `file' entry is
2216 * the same as the path of `cur_dirent', add isoent to
2219 if (archive_strlen(&(xar->cur_dirstr))
2220 == archive_strlen(&(file->parentdir)) &&
2221 strcmp(xar->cur_dirstr.s, fn) == 0) {
2222 if (!file_add_child_tail(xar->cur_dirent, file)) {
2223 np = (struct file *)__archive_rb_tree_find_node(
2224 &(xar->cur_dirent->rbtree),
2228 return (ARCHIVE_OK);
2232 l = get_path_component(name, sizeof(name), fn);
2238 archive_set_error(&a->archive,
2240 "A name buffer is too small");
2243 return (ARCHIVE_FATAL);
2246 np = file_find_child(dent, name);
2247 if (np == NULL || fn[0] == '\0')
2250 /* Find next subdirectory. */
2252 /* NOT Directory! */
2253 archive_set_error(&a->archive,
2255 "`%s' is not directory, we cannot insert `%s' ",
2256 archive_entry_pathname(np->entry),
2257 archive_entry_pathname(file->entry));
2260 return (ARCHIVE_FAILED);
2269 * Create virtual parent directories.
2271 while (fn[0] != '\0') {
2273 struct archive_string as;
2275 archive_string_init(&as);
2276 archive_strncat(&as, p, fn - p + l);
2277 if (as.s[as.length-1] == '/') {
2278 as.s[as.length-1] = '\0';
2281 vp = file_create_virtual_dir(a, xar, as.s);
2283 archive_string_free(&as);
2284 archive_set_error(&a->archive, ENOMEM,
2285 "Can't allocate memory");
2288 return (ARCHIVE_FATAL);
2290 archive_string_free(&as);
2291 if (file_gen_utility_names(a, vp) <= ARCHIVE_FAILED)
2292 return (ARCHIVE_FATAL);
2293 file_add_child_tail(dent, vp);
2294 file_register(xar, vp);
2300 l = get_path_component(name, sizeof(name), fn);
2302 archive_string_free(&as);
2303 archive_set_error(&a->archive,
2305 "A name buffer is too small");
2308 return (ARCHIVE_FATAL);
2313 /* Found out the parent directory where isoent can be
2315 xar->cur_dirent = dent;
2316 archive_string_empty(&(xar->cur_dirstr));
2317 archive_string_ensure(&(xar->cur_dirstr),
2318 archive_strlen(&(dent->parentdir)) +
2319 archive_strlen(&(dent->basename)) + 2);
2320 if (archive_strlen(&(dent->parentdir)) +
2321 archive_strlen(&(dent->basename)) == 0)
2322 xar->cur_dirstr.s[0] = 0;
2324 if (archive_strlen(&(dent->parentdir)) > 0) {
2325 archive_string_copy(&(xar->cur_dirstr),
2326 &(dent->parentdir));
2327 archive_strappend_char(&(xar->cur_dirstr), '/');
2329 archive_string_concat(&(xar->cur_dirstr),
2333 if (!file_add_child_tail(dent, file)) {
2334 np = (struct file *)__archive_rb_tree_find_node(
2335 &(dent->rbtree), file->basename.s);
2338 return (ARCHIVE_OK);
2343 * We have already has the entry the filename of which is
2346 if (archive_entry_filetype(np->entry) !=
2347 archive_entry_filetype(file->entry)) {
2348 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2349 "Found duplicate entries `%s' and its file type is "
2351 archive_entry_pathname(np->entry));
2354 return (ARCHIVE_FAILED);
2359 np->entry = file->entry;
2365 return (ARCHIVE_OK);
2369 file_register(struct xar *xar, struct file *file)
2371 file->id = xar->file_idx++;
2373 *xar->file_list.last = file;
2374 xar->file_list.last = &(file->next);
2378 file_init_register(struct xar *xar)
2380 xar->file_list.first = NULL;
2381 xar->file_list.last = &(xar->file_list.first);
2385 file_free_register(struct xar *xar)
2387 struct file *file, *file_next;
2389 file = xar->file_list.first;
2390 while (file != NULL) {
2391 file_next = file->next;
2398 * Register entry to get a hardlink target.
2401 file_register_hardlink(struct archive_write *a, struct file *file)
2403 struct xar *xar = (struct xar *)a->format_data;
2404 struct hardlink *hl;
2405 const char *pathname;
2407 archive_entry_set_nlink(file->entry, 1);
2408 pathname = archive_entry_hardlink(file->entry);
2409 if (pathname == NULL) {
2410 /* This `file` is a hardlink target. */
2411 hl = malloc(sizeof(*hl));
2413 archive_set_error(&a->archive, ENOMEM,
2414 "Can't allocate memory");
2415 return (ARCHIVE_FATAL);
2418 /* A hardlink target must be the first position. */
2419 file->hlnext = NULL;
2420 hl->file_list.first = file;
2421 hl->file_list.last = &(file->hlnext);
2422 __archive_rb_tree_insert_node(&(xar->hardlink_rbtree),
2423 (struct archive_rb_node *)hl);
2425 hl = (struct hardlink *)__archive_rb_tree_find_node(
2426 &(xar->hardlink_rbtree), pathname);
2428 /* Insert `file` entry into the tail. */
2429 file->hlnext = NULL;
2430 *hl->file_list.last = file;
2431 hl->file_list.last = &(file->hlnext);
2434 archive_entry_unset_size(file->entry);
2437 return (ARCHIVE_OK);
2441 * Hardlinked files have to have the same location of extent.
2442 * We have to find out hardlink target entries for entries which
2443 * have a hardlink target name.
2446 file_connect_hardlink_files(struct xar *xar)
2448 struct archive_rb_node *n;
2449 struct hardlink *hl;
2450 struct file *target, *nf;
2452 ARCHIVE_RB_TREE_FOREACH(n, &(xar->hardlink_rbtree)) {
2453 hl = (struct hardlink *)n;
2455 /* The first entry must be a hardlink target. */
2456 target = hl->file_list.first;
2457 archive_entry_set_nlink(target->entry, hl->nlink);
2459 /* It means this file is a hardlink
2461 target->hardlink_target = target;
2462 for (nf = target->hlnext;
2463 nf != NULL; nf = nf->hlnext) {
2464 nf->hardlink_target = target;
2465 archive_entry_set_nlink(nf->entry, hl->nlink);
2471 file_hd_cmp_node(const struct archive_rb_node *n1,
2472 const struct archive_rb_node *n2)
2474 const struct hardlink *h1 = (const struct hardlink *)n1;
2475 const struct hardlink *h2 = (const struct hardlink *)n2;
2477 return (strcmp(archive_entry_pathname(h1->file_list.first->entry),
2478 archive_entry_pathname(h2->file_list.first->entry)));
2482 file_hd_cmp_key(const struct archive_rb_node *n, const void *key)
2484 const struct hardlink *h = (const struct hardlink *)n;
2486 return (strcmp(archive_entry_pathname(h->file_list.first->entry),
2487 (const char *)key));
2492 file_init_hardlinks(struct xar *xar)
2494 static const struct archive_rb_tree_ops rb_ops = {
2495 file_hd_cmp_node, file_hd_cmp_key,
2498 __archive_rb_tree_init(&(xar->hardlink_rbtree), &rb_ops);
2502 file_free_hardlinks(struct xar *xar)
2504 struct archive_rb_node *n, *next;
2506 for (n = ARCHIVE_RB_TREE_MIN(&(xar->hardlink_rbtree)); n;) {
2507 next = __archive_rb_tree_iterate(&(xar->hardlink_rbtree),
2508 n, ARCHIVE_RB_DIR_RIGHT);
2515 checksum_init(struct chksumwork *sumwrk, enum sumalg sum_alg)
2517 sumwrk->alg = sum_alg;
2522 archive_sha1_init(&(sumwrk->sha1ctx));
2525 archive_md5_init(&(sumwrk->md5ctx));
2531 checksum_update(struct chksumwork *sumwrk, const void *buff, size_t size)
2534 switch (sumwrk->alg) {
2538 archive_sha1_update(&(sumwrk->sha1ctx), buff, size);
2541 archive_md5_update(&(sumwrk->md5ctx), buff, size);
2547 checksum_final(struct chksumwork *sumwrk, struct chksumval *sumval)
2550 switch (sumwrk->alg) {
2555 archive_sha1_final(&(sumwrk->sha1ctx), sumval->val);
2556 sumval->len = SHA1_SIZE;
2559 archive_md5_final(&(sumwrk->md5ctx), sumval->val);
2560 sumval->len = MD5_SIZE;
2563 sumval->alg = sumwrk->alg;
2566 #if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
2568 compression_unsupported_encoder(struct archive *a,
2569 struct la_zstream *lastrm, const char *name)
2572 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2573 "%s compression not supported on this platform", name);
2575 lastrm->real_stream = NULL;
2576 return (ARCHIVE_FAILED);
2581 compression_init_encoder_gzip(struct archive *a,
2582 struct la_zstream *lastrm, int level, int withheader)
2587 compression_end(a, lastrm);
2588 strm = calloc(1, sizeof(*strm));
2590 archive_set_error(a, ENOMEM,
2591 "Can't allocate memory for gzip stream");
2592 return (ARCHIVE_FATAL);
2594 /* zlib.h is not const-correct, so we need this one bit
2595 * of ugly hackery to convert a const * pointer to
2596 * a non-const pointer. */
2597 strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
2598 strm->avail_in = lastrm->avail_in;
2599 strm->total_in = (uLong)lastrm->total_in;
2600 strm->next_out = lastrm->next_out;
2601 strm->avail_out = lastrm->avail_out;
2602 strm->total_out = (uLong)lastrm->total_out;
2603 if (deflateInit2(strm, level, Z_DEFLATED,
2604 (withheader)?15:-15,
2605 8, Z_DEFAULT_STRATEGY) != Z_OK) {
2607 lastrm->real_stream = NULL;
2608 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2609 "Internal error initializing compression library");
2610 return (ARCHIVE_FATAL);
2612 lastrm->real_stream = strm;
2614 lastrm->code = compression_code_gzip;
2615 lastrm->end = compression_end_gzip;
2616 return (ARCHIVE_OK);
2620 compression_code_gzip(struct archive *a,
2621 struct la_zstream *lastrm, enum la_zaction action)
2626 strm = (z_stream *)lastrm->real_stream;
2627 /* zlib.h is not const-correct, so we need this one bit
2628 * of ugly hackery to convert a const * pointer to
2629 * a non-const pointer. */
2630 strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
2631 strm->avail_in = lastrm->avail_in;
2632 strm->total_in = (uLong)lastrm->total_in;
2633 strm->next_out = lastrm->next_out;
2634 strm->avail_out = lastrm->avail_out;
2635 strm->total_out = (uLong)lastrm->total_out;
2637 (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH);
2638 lastrm->next_in = strm->next_in;
2639 lastrm->avail_in = strm->avail_in;
2640 lastrm->total_in = strm->total_in;
2641 lastrm->next_out = strm->next_out;
2642 lastrm->avail_out = strm->avail_out;
2643 lastrm->total_out = strm->total_out;
2646 return (ARCHIVE_OK);
2648 return (ARCHIVE_EOF);
2650 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2651 "GZip compression failed:"
2652 " deflate() call returned status %d", r);
2653 return (ARCHIVE_FATAL);
2658 compression_end_gzip(struct archive *a, struct la_zstream *lastrm)
2663 strm = (z_stream *)lastrm->real_stream;
2664 r = deflateEnd(strm);
2666 lastrm->real_stream = NULL;
2669 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2670 "Failed to clean up compressor");
2671 return (ARCHIVE_FATAL);
2673 return (ARCHIVE_OK);
2676 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
2678 compression_init_encoder_bzip2(struct archive *a,
2679 struct la_zstream *lastrm, int level)
2684 compression_end(a, lastrm);
2685 strm = calloc(1, sizeof(*strm));
2687 archive_set_error(a, ENOMEM,
2688 "Can't allocate memory for bzip2 stream");
2689 return (ARCHIVE_FATAL);
2691 /* bzlib.h is not const-correct, so we need this one bit
2692 * of ugly hackery to convert a const * pointer to
2693 * a non-const pointer. */
2694 strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
2695 strm->avail_in = lastrm->avail_in;
2696 strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
2697 strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
2698 strm->next_out = (char *)lastrm->next_out;
2699 strm->avail_out = lastrm->avail_out;
2700 strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
2701 strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
2702 if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) {
2704 lastrm->real_stream = NULL;
2705 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2706 "Internal error initializing compression library");
2707 return (ARCHIVE_FATAL);
2709 lastrm->real_stream = strm;
2711 lastrm->code = compression_code_bzip2;
2712 lastrm->end = compression_end_bzip2;
2713 return (ARCHIVE_OK);
2717 compression_code_bzip2(struct archive *a,
2718 struct la_zstream *lastrm, enum la_zaction action)
2723 strm = (bz_stream *)lastrm->real_stream;
2724 /* bzlib.h is not const-correct, so we need this one bit
2725 * of ugly hackery to convert a const * pointer to
2726 * a non-const pointer. */
2727 strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
2728 strm->avail_in = lastrm->avail_in;
2729 strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
2730 strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
2731 strm->next_out = (char *)lastrm->next_out;
2732 strm->avail_out = lastrm->avail_out;
2733 strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
2734 strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
2735 r = BZ2_bzCompress(strm,
2736 (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN);
2737 lastrm->next_in = (const unsigned char *)strm->next_in;
2738 lastrm->avail_in = strm->avail_in;
2740 (((uint64_t)(uint32_t)strm->total_in_hi32) << 32)
2741 + (uint64_t)(uint32_t)strm->total_in_lo32;
2742 lastrm->next_out = (unsigned char *)strm->next_out;
2743 lastrm->avail_out = strm->avail_out;
2745 (((uint64_t)(uint32_t)strm->total_out_hi32) << 32)
2746 + (uint64_t)(uint32_t)strm->total_out_lo32;
2748 case BZ_RUN_OK: /* Non-finishing */
2749 case BZ_FINISH_OK: /* Finishing: There's more work to do */
2750 return (ARCHIVE_OK);
2751 case BZ_STREAM_END: /* Finishing: all done */
2752 /* Only occurs in finishing case */
2753 return (ARCHIVE_EOF);
2755 /* Any other return value indicates an error */
2756 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2757 "Bzip2 compression failed:"
2758 " BZ2_bzCompress() call returned status %d", r);
2759 return (ARCHIVE_FATAL);
2764 compression_end_bzip2(struct archive *a, struct la_zstream *lastrm)
2769 strm = (bz_stream *)lastrm->real_stream;
2770 r = BZ2_bzCompressEnd(strm);
2772 lastrm->real_stream = NULL;
2775 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2776 "Failed to clean up compressor");
2777 return (ARCHIVE_FATAL);
2779 return (ARCHIVE_OK);
2784 compression_init_encoder_bzip2(struct archive *a,
2785 struct la_zstream *lastrm, int level)
2788 (void) level; /* UNUSED */
2790 compression_end(a, lastrm);
2791 return (compression_unsupported_encoder(a, lastrm, "bzip2"));
2795 #if defined(HAVE_LZMA_H)
2797 compression_init_encoder_lzma(struct archive *a,
2798 struct la_zstream *lastrm, int level)
2800 static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
2802 lzma_options_lzma lzma_opt;
2806 compression_end(a, lastrm);
2807 if (lzma_lzma_preset(&lzma_opt, level)) {
2808 lastrm->real_stream = NULL;
2809 archive_set_error(a, ENOMEM,
2810 "Internal error initializing compression library");
2811 return (ARCHIVE_FATAL);
2813 strm = calloc(1, sizeof(*strm));
2815 archive_set_error(a, ENOMEM,
2816 "Can't allocate memory for lzma stream");
2817 return (ARCHIVE_FATAL);
2819 *strm = lzma_init_data;
2820 r = lzma_alone_encoder(strm, &lzma_opt);
2823 lastrm->real_stream = strm;
2825 lastrm->code = compression_code_lzma;
2826 lastrm->end = compression_end_lzma;
2829 case LZMA_MEM_ERROR:
2831 lastrm->real_stream = NULL;
2832 archive_set_error(a, ENOMEM,
2833 "Internal error initializing compression library: "
2834 "Cannot allocate memory");
2839 lastrm->real_stream = NULL;
2840 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2841 "Internal error initializing compression library: "
2842 "It's a bug in liblzma");
2850 compression_init_encoder_xz(struct archive *a,
2851 struct la_zstream *lastrm, int level)
2853 static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
2855 lzma_filter *lzmafilters;
2856 lzma_options_lzma lzma_opt;
2860 compression_end(a, lastrm);
2861 strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2);
2863 archive_set_error(a, ENOMEM,
2864 "Can't allocate memory for xz stream");
2865 return (ARCHIVE_FATAL);
2867 lzmafilters = (lzma_filter *)(strm+1);
2870 if (lzma_lzma_preset(&lzma_opt, level)) {
2872 lastrm->real_stream = NULL;
2873 archive_set_error(a, ENOMEM,
2874 "Internal error initializing compression library");
2875 return (ARCHIVE_FATAL);
2877 lzmafilters[0].id = LZMA_FILTER_LZMA2;
2878 lzmafilters[0].options = &lzma_opt;
2879 lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
2881 *strm = lzma_init_data;
2882 r = lzma_stream_encoder(strm, lzmafilters, LZMA_CHECK_CRC64);
2885 lastrm->real_stream = strm;
2887 lastrm->code = compression_code_lzma;
2888 lastrm->end = compression_end_lzma;
2891 case LZMA_MEM_ERROR:
2893 lastrm->real_stream = NULL;
2894 archive_set_error(a, ENOMEM,
2895 "Internal error initializing compression library: "
2896 "Cannot allocate memory");
2901 lastrm->real_stream = NULL;
2902 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2903 "Internal error initializing compression library: "
2904 "It's a bug in liblzma");
2912 compression_code_lzma(struct archive *a,
2913 struct la_zstream *lastrm, enum la_zaction action)
2918 strm = (lzma_stream *)lastrm->real_stream;
2919 strm->next_in = lastrm->next_in;
2920 strm->avail_in = lastrm->avail_in;
2921 strm->total_in = lastrm->total_in;
2922 strm->next_out = lastrm->next_out;
2923 strm->avail_out = lastrm->avail_out;
2924 strm->total_out = lastrm->total_out;
2926 (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN);
2927 lastrm->next_in = strm->next_in;
2928 lastrm->avail_in = strm->avail_in;
2929 lastrm->total_in = strm->total_in;
2930 lastrm->next_out = strm->next_out;
2931 lastrm->avail_out = strm->avail_out;
2932 lastrm->total_out = strm->total_out;
2935 /* Non-finishing case */
2936 return (ARCHIVE_OK);
2937 case LZMA_STREAM_END:
2938 /* This return can only occur in finishing case. */
2939 return (ARCHIVE_EOF);
2940 case LZMA_MEMLIMIT_ERROR:
2941 archive_set_error(a, ENOMEM,
2942 "lzma compression error:"
2943 " %ju MiB would have been needed",
2944 (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1)
2946 return (ARCHIVE_FATAL);
2948 /* Any other return value indicates an error */
2949 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2950 "lzma compression failed:"
2951 " lzma_code() call returned status %d", r);
2952 return (ARCHIVE_FATAL);
2957 compression_end_lzma(struct archive *a, struct la_zstream *lastrm)
2961 (void)a; /* UNUSED */
2962 strm = (lzma_stream *)lastrm->real_stream;
2966 lastrm->real_stream = NULL;
2967 return (ARCHIVE_OK);
2971 compression_init_encoder_lzma(struct archive *a,
2972 struct la_zstream *lastrm, int level)
2975 (void) level; /* UNUSED */
2977 compression_end(a, lastrm);
2978 return (compression_unsupported_encoder(a, lastrm, "lzma"));
2981 compression_init_encoder_xz(struct archive *a,
2982 struct la_zstream *lastrm, int level)
2985 (void) level; /* UNUSED */
2987 compression_end(a, lastrm);
2988 return (compression_unsupported_encoder(a, lastrm, "xz"));
2993 xar_compression_init_encoder(struct archive_write *a)
2998 xar = (struct xar *)a->format_data;
2999 switch (xar->opt_compression) {
3001 r = compression_init_encoder_gzip(
3002 &(a->archive), &(xar->stream),
3003 xar->opt_compression_level, 1);
3006 r = compression_init_encoder_bzip2(
3007 &(a->archive), &(xar->stream),
3008 xar->opt_compression_level);
3011 r = compression_init_encoder_lzma(
3012 &(a->archive), &(xar->stream),
3013 xar->opt_compression_level);
3016 r = compression_init_encoder_xz(
3017 &(a->archive), &(xar->stream),
3018 xar->opt_compression_level);
3024 if (r == ARCHIVE_OK) {
3025 xar->stream.total_in = 0;
3026 xar->stream.next_out = xar->wbuff;
3027 xar->stream.avail_out = sizeof(xar->wbuff);
3028 xar->stream.total_out = 0;
3035 compression_code(struct archive *a, struct la_zstream *lastrm,
3036 enum la_zaction action)
3039 return (lastrm->code(a, lastrm, action));
3040 return (ARCHIVE_OK);
3044 compression_end(struct archive *a, struct la_zstream *lastrm)
3047 return (lastrm->end(a, lastrm));
3048 return (ARCHIVE_OK);
3053 save_xattrs(struct archive_write *a, struct file *file)
3058 struct heap_data *heap;
3062 xar = (struct xar *)a->format_data;
3063 count = archive_entry_xattr_reset(file->entry);
3065 return (ARCHIVE_OK);
3067 archive_entry_xattr_next(file->entry,
3068 &name, &value, &size);
3069 checksum_init(&(xar->a_sumwrk), xar->opt_sumalg);
3070 checksum_init(&(xar->e_sumwrk), xar->opt_sumalg);
3072 heap = calloc(1, sizeof(*heap));
3074 archive_set_error(&a->archive, ENOMEM,
3075 "Can't allocate memory for xattr");
3076 return (ARCHIVE_FATAL);
3078 heap->id = file->ea_idx++;
3079 heap->temp_offset = xar->temp_offset;
3080 heap->size = size;/* save a extracted size */
3081 heap->compression = xar->opt_compression;
3082 /* Get a extracted sumcheck value. */
3083 checksum_update(&(xar->e_sumwrk), value, size);
3084 checksum_final(&(xar->e_sumwrk), &(heap->e_sum));
3087 * Not compression to xattr is simple way.
3089 if (heap->compression == NONE) {
3090 checksum_update(&(xar->a_sumwrk), value, size);
3091 checksum_final(&(xar->a_sumwrk), &(heap->a_sum));
3092 if (write_to_temp(a, value, size)
3095 return (ARCHIVE_FATAL);
3097 heap->length = size;
3098 /* Add heap to the tail of file->xattr. */
3100 *file->xattr.last = heap;
3101 file->xattr.last = &(heap->next);
3107 * Init compression library.
3109 r = xar_compression_init_encoder(a);
3110 if (r != ARCHIVE_OK) {
3112 return (ARCHIVE_FATAL);
3115 xar->stream.next_in = (const unsigned char *)value;
3116 xar->stream.avail_in = size;
3118 r = compression_code(&(a->archive),
3119 &(xar->stream), ARCHIVE_Z_FINISH);
3120 if (r != ARCHIVE_OK && r != ARCHIVE_EOF) {
3122 return (ARCHIVE_FATAL);
3124 size = sizeof(xar->wbuff) - xar->stream.avail_out;
3125 checksum_update(&(xar->a_sumwrk),
3127 if (write_to_temp(a, xar->wbuff, size)
3129 return (ARCHIVE_FATAL);
3130 if (r == ARCHIVE_OK) {
3131 xar->stream.next_out = xar->wbuff;
3132 xar->stream.avail_out = sizeof(xar->wbuff);
3134 checksum_final(&(xar->a_sumwrk),
3136 heap->length = xar->stream.total_out;
3137 /* Add heap to the tail of file->xattr. */
3139 *file->xattr.last = heap;
3140 file->xattr.last = &(heap->next);
3144 /* Clean up compression library. */
3145 r = compression_end(&(a->archive), &(xar->stream));
3146 if (r != ARCHIVE_OK)
3147 return (ARCHIVE_FATAL);
3149 return (ARCHIVE_OK);
3153 getalgsize(enum sumalg sumalg)
3167 getalgname(enum sumalg sumalg)
3180 #endif /* Support xar format */