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>
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 BAD_CAST_CONST (const xmlChar *)
106 #define HEADER_MAGIC 0x78617221
107 #define HEADER_SIZE 28
108 #define HEADER_VERSION 1
118 #define MAX_SUM_SIZE 20
119 #define MD5_NAME "md5"
120 #define SHA1_NAME "sha1"
132 #ifdef ARCHIVE_HAS_MD5
133 archive_md5_ctx md5ctx;
135 #ifdef ARCHIVE_HAS_SHA1
136 archive_sha1_ctx sha1ctx;
149 const unsigned char *next_in;
153 unsigned char *next_out;
159 int (*code) (struct archive *a,
160 struct la_zstream *lastrm,
161 enum la_zaction action);
162 int (*end)(struct archive *a,
163 struct la_zstream *lastrm);
169 unsigned char val[MAX_SUM_SIZE];
174 struct heap_data *next;
175 uint64_t temp_offset;
176 uint64_t length; /* archived size. */
177 uint64_t size; /* extracted size. */
178 enum enctype compression;
179 struct chksumval a_sum; /* archived checksum. */
180 struct chksumval e_sum; /* extracted checksum. */
184 struct archive_rb_node rbnode;
187 struct archive_entry *entry;
189 struct archive_rb_tree rbtree;
193 /* For hardlinked files.
194 * Use only when archive_entry_nlink() > 1 */
195 struct file *hardlink_target;
196 struct file *parent; /* parent directory entry */
198 * To manage sub directory files.
199 * We use 'chnext' a menber of struct file to chain.
206 /* For making a directory tree. */
207 struct archive_string parentdir;
208 struct archive_string basename;
209 struct archive_string symlink;
213 struct heap_data *first;
214 struct heap_data **last;
216 struct heap_data data;
217 struct archive_string script;
224 struct archive_rb_node rbnode;
234 uint64_t temp_offset;
238 struct file *cur_dirent;
239 struct archive_string cur_dirstr;
240 struct file *cur_file;
241 uint64_t bytes_remaining;
242 struct archive_string tstr;
243 struct archive_string vstr;
245 enum sumalg opt_toc_sumalg;
246 enum sumalg opt_sumalg;
247 enum enctype opt_compression;
248 int opt_compression_level;
250 struct chksumwork a_sumwrk; /* archived checksum. */
251 struct chksumwork e_sumwrk; /* extracted checksum. */
252 struct la_zstream stream;
253 struct archive_string_conv *sconv;
255 * Compressed data buffer.
257 unsigned char wbuff[1024 * 64];
258 size_t wbuff_remaining;
260 struct heap_data toc;
262 * The list of all file entries is used to manage struct file
264 * We use 'next' a menber of struct file to chain.
271 * The list of hard-linked file entries.
272 * We use 'hlnext' a menber of struct file to chain.
274 struct archive_rb_tree hardlink_rbtree;
277 static int xar_options(struct archive_write *,
278 const char *, const char *);
279 static int xar_write_header(struct archive_write *,
280 struct archive_entry *);
281 static ssize_t xar_write_data(struct archive_write *,
282 const void *, size_t);
283 static int xar_finish_entry(struct archive_write *);
284 static int xar_close(struct archive_write *);
285 static int xar_free(struct archive_write *);
287 static struct file *file_new(struct archive_write *a, struct archive_entry *);
288 static void file_free(struct file *);
289 static struct file *file_create_virtual_dir(struct archive_write *a, struct xar *,
291 static int file_add_child_tail(struct file *, struct file *);
292 static struct file *file_find_child(struct file *, const char *);
293 static int file_gen_utility_names(struct archive_write *,
295 static int get_path_component(char *, int, const char *);
296 static int file_tree(struct archive_write *, struct file **);
297 static void file_register(struct xar *, struct file *);
298 static void file_init_register(struct xar *);
299 static void file_free_register(struct xar *);
300 static int file_register_hardlink(struct archive_write *,
302 static void file_connect_hardlink_files(struct xar *);
303 static void file_init_hardlinks(struct xar *);
304 static void file_free_hardlinks(struct xar *);
306 static void checksum_init(struct chksumwork *, enum sumalg);
307 static void checksum_update(struct chksumwork *, const void *, size_t);
308 static void checksum_final(struct chksumwork *, struct chksumval *);
309 static int compression_init_encoder_gzip(struct archive *,
310 struct la_zstream *, int, int);
311 static int compression_code_gzip(struct archive *,
312 struct la_zstream *, enum la_zaction);
313 static int compression_end_gzip(struct archive *, struct la_zstream *);
314 static int compression_init_encoder_bzip2(struct archive *,
315 struct la_zstream *, int);
316 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
317 static int compression_code_bzip2(struct archive *,
318 struct la_zstream *, enum la_zaction);
319 static int compression_end_bzip2(struct archive *, struct la_zstream *);
321 static int compression_init_encoder_lzma(struct archive *,
322 struct la_zstream *, int);
323 static int compression_init_encoder_xz(struct archive *,
324 struct la_zstream *, int);
325 #if defined(HAVE_LZMA_H)
326 static int compression_code_lzma(struct archive *,
327 struct la_zstream *, enum la_zaction);
328 static int compression_end_lzma(struct archive *, struct la_zstream *);
330 static int xar_compression_init_encoder(struct archive_write *);
331 static int compression_code(struct archive *,
332 struct la_zstream *, enum la_zaction);
333 static int compression_end(struct archive *,
334 struct la_zstream *);
335 static int save_xattrs(struct archive_write *, struct file *);
336 static int getalgsize(enum sumalg);
337 static const char *getalgname(enum sumalg);
340 archive_write_set_format_xar(struct archive *_a)
342 struct archive_write *a = (struct archive_write *)_a;
345 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
346 ARCHIVE_STATE_NEW, "archive_write_set_format_xar");
348 /* If another format was already registered, unregister it. */
349 if (a->format_free != NULL)
352 xar = calloc(1, sizeof(*xar));
354 archive_set_error(&a->archive, ENOMEM,
355 "Can't allocate xar data");
356 return (ARCHIVE_FATAL);
359 file_init_register(xar);
360 file_init_hardlinks(xar);
361 archive_string_init(&(xar->tstr));
362 archive_string_init(&(xar->vstr));
365 * Create the root directory.
367 xar->root = file_create_virtual_dir(a, xar, "");
368 if (xar->root == NULL) {
370 archive_set_error(&a->archive, ENOMEM,
371 "Can't allocate xar data");
372 return (ARCHIVE_FATAL);
374 xar->root->parent = xar->root;
375 file_register(xar, xar->root);
376 xar->cur_dirent = xar->root;
377 archive_string_init(&(xar->cur_dirstr));
378 archive_string_ensure(&(xar->cur_dirstr), 1);
379 xar->cur_dirstr.s[0] = 0;
384 /* Set default checksum type. */
385 xar->opt_toc_sumalg = CKSUM_SHA1;
386 xar->opt_sumalg = CKSUM_SHA1;
387 /* Set default compression type and level. */
388 xar->opt_compression = GZIP;
389 xar->opt_compression_level = 6;
391 a->format_data = xar;
393 a->format_name = "xar";
394 a->format_options = xar_options;
395 a->format_write_header = xar_write_header;
396 a->format_write_data = xar_write_data;
397 a->format_finish_entry = xar_finish_entry;
398 a->format_close = xar_close;
399 a->format_free = xar_free;
400 a->archive.archive_format = ARCHIVE_FORMAT_XAR;
401 a->archive.archive_format_name = "xar";
407 xar_options(struct archive_write *a, const char *key, const char *value)
411 xar = (struct xar *)a->format_data;
413 if (strcmp(key, "checksum") == 0) {
415 xar->opt_sumalg = CKSUM_NONE;
416 else if (strcmp(value, "sha1") == 0)
417 xar->opt_sumalg = CKSUM_SHA1;
418 else if (strcmp(value, "md5") == 0)
419 xar->opt_sumalg = CKSUM_MD5;
421 archive_set_error(&(a->archive),
423 "Unkonwn checksum name: `%s'",
425 return (ARCHIVE_FAILED);
429 if (strcmp(key, "compression") == 0) {
430 const char *name = NULL;
433 xar->opt_compression = NONE;
434 else if (strcmp(value, "gzip") == 0)
435 xar->opt_compression = GZIP;
436 else if (strcmp(value, "bzip2") == 0)
437 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
438 xar->opt_compression = BZIP2;
442 else if (strcmp(value, "lzma") == 0)
444 xar->opt_compression = LZMA;
448 else if (strcmp(value, "xz") == 0)
450 xar->opt_compression = XZ;
455 archive_set_error(&(a->archive),
457 "Unkonwn compression name: `%s'",
459 return (ARCHIVE_FAILED);
462 archive_set_error(&(a->archive),
464 "`%s' compression not supported "
467 return (ARCHIVE_FAILED);
471 if (strcmp(key, "compression-level") == 0) {
473 !(value[0] >= '0' && value[0] <= '9') ||
475 archive_set_error(&(a->archive),
477 "Illeagal value `%s'",
479 return (ARCHIVE_FAILED);
481 xar->opt_compression_level = value[0] - '0';
484 if (strcmp(key, "toc-checksum") == 0) {
486 xar->opt_toc_sumalg = CKSUM_NONE;
487 else if (strcmp(value, "sha1") == 0)
488 xar->opt_toc_sumalg = CKSUM_SHA1;
489 else if (strcmp(value, "md5") == 0)
490 xar->opt_toc_sumalg = CKSUM_MD5;
492 archive_set_error(&(a->archive),
494 "Unkonwn checksum name: `%s'",
496 return (ARCHIVE_FAILED);
501 /* Note: The "warn" return is just to inform the options
502 * supervisor that we didn't handle it. It will generate
503 * a suitable error if no one used this option. */
504 return (ARCHIVE_WARN);
508 xar_write_header(struct archive_write *a, struct archive_entry *entry)
512 struct archive_entry *file_entry;
515 xar = (struct xar *)a->format_data;
516 xar->cur_file = NULL;
517 xar->bytes_remaining = 0;
519 if (xar->sconv == NULL) {
520 xar->sconv = archive_string_conversion_to_charset(
521 &a->archive, "UTF-8", 1);
522 if (xar->sconv == NULL)
523 return (ARCHIVE_FATAL);
526 file = file_new(a, entry);
528 archive_set_error(&a->archive, ENOMEM,
529 "Can't allocate data");
530 return (ARCHIVE_FATAL);
532 r2 = file_gen_utility_names(a, file);
533 if (r2 < ARCHIVE_WARN)
537 * Ignore a path which looks like the top of directory name
538 * since we have already made the root directory of an Xar archive.
540 if (archive_strlen(&(file->parentdir)) == 0 &&
541 archive_strlen(&(file->basename)) == 0) {
546 /* Add entry into tree */
547 file_entry = file->entry;
548 r = file_tree(a, &file);
551 /* There is the same file in tree and
552 * the current file is older than the file in tree.
553 * So we don't need the current file data anymore. */
554 if (file->entry != file_entry)
557 file_register(xar, file);
559 /* A virtual file, which is a directory, does not have
560 * any contents and we won't store it into a archive
561 * file other than its name. */
566 * Prepare to save the contents of the file.
568 if (xar->temp_fd == -1) {
570 xar->temp_offset = 0;
571 xar->temp_fd = __archive_mktemp(NULL);
572 if (xar->temp_fd < 0) {
573 archive_set_error(&a->archive, errno,
574 "Couldn't create temporary file");
575 return (ARCHIVE_FATAL);
577 algsize = getalgsize(xar->opt_toc_sumalg);
579 if (lseek(xar->temp_fd, algsize, SEEK_SET) < 0) {
580 archive_set_error(&(a->archive), errno,
582 return (ARCHIVE_FATAL);
584 xar->temp_offset = algsize;
588 if (archive_entry_hardlink(file->entry) == NULL) {
589 r = save_xattrs(a, file);
591 return (ARCHIVE_FATAL);
594 /* Non regular files contents are unneeded to be saved to
595 * a temporary file. */
596 if (archive_entry_filetype(file->entry) != AE_IFREG)
600 * Set the current file to cur_file to read its contents.
602 xar->cur_file = file;
604 if (archive_entry_nlink(file->entry) > 1) {
605 r = file_register_hardlink(a, file);
608 if (archive_entry_hardlink(file->entry) != NULL) {
609 archive_entry_unset_size(file->entry);
614 /* Save a offset of current file in temporary file. */
615 file->data.temp_offset = xar->temp_offset;
616 file->data.size = archive_entry_size(file->entry);
617 file->data.compression = xar->opt_compression;
618 xar->bytes_remaining = archive_entry_size(file->entry);
619 checksum_init(&(xar->a_sumwrk), xar->opt_sumalg);
620 checksum_init(&(xar->e_sumwrk), xar->opt_sumalg);
621 r = xar_compression_init_encoder(a);
630 write_to_temp(struct archive_write *a, const void *buff, size_t s)
633 const unsigned char *p;
636 xar = (struct xar *)a->format_data;
637 p = (const unsigned char *)buff;
639 ws = write(xar->temp_fd, p, s);
641 archive_set_error(&(a->archive), errno,
642 "fwrite function failed");
643 return (ARCHIVE_FATAL);
647 xar->temp_offset += ws;
653 xar_write_data(struct archive_write *a, const void *buff, size_t s)
660 xar = (struct xar *)a->format_data;
662 if (s > xar->bytes_remaining)
663 s = xar->bytes_remaining;
664 if (s == 0 || xar->cur_file == NULL)
666 if (xar->cur_file->data.compression == NONE) {
667 checksum_update(&(xar->e_sumwrk), buff, s);
668 checksum_update(&(xar->a_sumwrk), buff, s);
671 xar->stream.next_in = (const unsigned char *)buff;
672 xar->stream.avail_in = s;
673 if (xar->bytes_remaining > s)
676 run = ARCHIVE_Z_FINISH;
677 /* Compress file data. */
678 r = compression_code(&(a->archive), &(xar->stream), run);
679 if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
680 return (ARCHIVE_FATAL);
681 rsize = s - xar->stream.avail_in;
682 checksum_update(&(xar->e_sumwrk), buff, rsize);
683 size = sizeof(xar->wbuff) - xar->stream.avail_out;
684 checksum_update(&(xar->a_sumwrk), xar->wbuff, size);
686 #if !defined(_WIN32) || defined(__CYGWIN__)
687 if (xar->bytes_remaining ==
688 (uint64_t)archive_entry_size(xar->cur_file->entry)) {
690 * Get the path of a shell script if so.
692 const unsigned char *b = (const unsigned char *)buff;
694 archive_string_empty(&(xar->cur_file->script));
695 if (rsize > 2 && b[0] == '#' && b[1] == '!') {
702 if ((rsize - off) > PATH_MAX)
703 end = off + PATH_MAX;
707 /* Find the end of a script path. */
708 for (i = off; i < end && b[i] != '\0' &&
709 b[i] != '\n' && b[i] != '\r' &&
710 b[i] != ' ' && b[i] != '\t'; i++)
712 archive_strncpy(&(xar->cur_file->script), b + off,
718 if (xar->cur_file->data.compression == NONE) {
719 if (write_to_temp(a, buff, size) != ARCHIVE_OK)
720 return (ARCHIVE_FATAL);
722 if (write_to_temp(a, xar->wbuff, size) != ARCHIVE_OK)
723 return (ARCHIVE_FATAL);
725 xar->bytes_remaining -= rsize;
726 xar->cur_file->data.length += size;
732 xar_finish_entry(struct archive_write *a)
739 xar = (struct xar *)a->format_data;
740 if (xar->cur_file == NULL)
743 while (xar->bytes_remaining > 0) {
744 s = xar->bytes_remaining;
745 if (s > a->null_length)
747 w = xar_write_data(a, a->nulls, s);
749 xar->bytes_remaining -= w;
753 file = xar->cur_file;
754 checksum_final(&(xar->e_sumwrk), &(file->data.e_sum));
755 checksum_final(&(xar->a_sumwrk), &(file->data.a_sum));
756 xar->cur_file = NULL;
762 xmlwrite_string_attr(struct archive_write *a, xmlTextWriterPtr writer,
763 const char *key, const char *value,
764 const char *attrkey, const char *attrvalue)
768 r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key));
770 archive_set_error(&a->archive,
772 "xmlTextWriterStartElement() failed: %d", r);
773 return (ARCHIVE_FATAL);
775 if (attrkey != NULL && attrvalue != NULL) {
776 r = xmlTextWriterWriteAttribute(writer,
777 BAD_CAST_CONST(attrkey), BAD_CAST_CONST(attrvalue));
779 archive_set_error(&a->archive,
781 "xmlTextWriterWriteAttribute() failed: %d", r);
782 return (ARCHIVE_FATAL);
786 r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value));
788 archive_set_error(&a->archive,
790 "xmlTextWriterWriteString() failed: %d", r);
791 return (ARCHIVE_FATAL);
794 r = xmlTextWriterEndElement(writer);
796 archive_set_error(&a->archive,
798 "xmlTextWriterEndElement() failed: %d", r);
799 return (ARCHIVE_FATAL);
805 xmlwrite_string(struct archive_write *a, xmlTextWriterPtr writer,
806 const char *key, const char *value)
813 r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key));
815 archive_set_error(&a->archive,
817 "xmlTextWriterStartElement() failed: %d", r);
818 return (ARCHIVE_FATAL);
821 r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value));
823 archive_set_error(&a->archive,
825 "xmlTextWriterWriteString() failed: %d", r);
826 return (ARCHIVE_FATAL);
829 r = xmlTextWriterEndElement(writer);
831 archive_set_error(&a->archive,
833 "xmlTextWriterEndElement() failed: %d", r);
834 return (ARCHIVE_FATAL);
840 xmlwrite_fstring(struct archive_write *a, xmlTextWriterPtr writer,
841 const char *key, const char *fmt, ...)
846 xar = (struct xar *)a->format_data;
848 archive_string_empty(&xar->vstr);
849 archive_string_vsprintf(&xar->vstr, fmt, ap);
851 return (xmlwrite_string(a, writer, key, xar->vstr.s));
855 xmlwrite_time(struct archive_write *a, xmlTextWriterPtr writer,
856 const char *key, time_t t, int z)
861 #if defined(HAVE_GMTIME_R)
863 #elif defined(HAVE__GMTIME64_S)
864 _gmtime64_s(&tm, &t);
866 memcpy(&tm, gmtime(&t), sizeof(tm));
868 memset(×tr, 0, sizeof(timestr));
869 /* Do not use %F and %T for portability. */
870 strftime(timestr, sizeof(timestr), "%Y-%m-%dT%H:%M:%S", &tm);
872 strcat(timestr, "Z");
873 return (xmlwrite_string(a, writer, key, timestr));
877 xmlwrite_mode(struct archive_write *a, xmlTextWriterPtr writer,
878 const char *key, mode_t mode)
883 ms[1] = '0' + ((mode >> 6) & 07);
884 ms[2] = '0' + ((mode >> 3) & 07);
885 ms[3] = '0' + (mode & 07);
888 return (xmlwrite_string(a, writer, key, ms));
892 xmlwrite_sum(struct archive_write *a, xmlTextWriterPtr writer,
893 const char *key, struct chksumval *sum)
897 char buff[MAX_SUM_SIZE*2 + 1];
903 algname = getalgname(sum->alg);
904 algsize = getalgsize(sum->alg);
905 if (algname != NULL) {
906 const char *hex = "0123456789abcdef";
909 for (i = 0; i < algsize; i++) {
910 *p++ = hex[(*s >> 4)];
911 *p++ = hex[(*s & 0x0f)];
915 r = xmlwrite_string_attr(a, writer,
919 return (ARCHIVE_FATAL);
926 xmlwrite_heap(struct archive_write *a, xmlTextWriterPtr writer,
927 struct heap_data *heap)
932 r = xmlwrite_fstring(a, writer, "length", "%ju", heap->length);
934 return (ARCHIVE_FATAL);
935 r = xmlwrite_fstring(a, writer, "offset", "%ju", heap->temp_offset);
937 return (ARCHIVE_FATAL);
938 r = xmlwrite_fstring(a, writer, "size", "%ju", heap->size);
940 return (ARCHIVE_FATAL);
941 switch (heap->compression) {
943 encname = "application/x-gzip"; break;
945 encname = "application/x-bzip2"; break;
947 encname = "application/x-lzma"; break;
949 encname = "application/x-xz"; break;
951 encname = "application/octet-stream"; break;
953 r = xmlwrite_string_attr(a, writer, "encoding", NULL,
956 return (ARCHIVE_FATAL);
957 r = xmlwrite_sum(a, writer, "archived-checksum", &(heap->a_sum));
959 return (ARCHIVE_FATAL);
960 r = xmlwrite_sum(a, writer, "extracted-checksum", &(heap->e_sum));
962 return (ARCHIVE_FATAL);
967 * xar utility records fflags as following xml elements:
977 * If xar is running on BSD platform, records <flags>..</flags>;
978 * if xar is running on linux platform, records <ext2>..</ext2>;
979 * otherwise does not record.
981 * Our implements records both <flags> and <ext2> if it's necessary.
984 make_fflags_entry(struct archive_write *a, xmlTextWriterPtr writer,
985 const char *element, const char *fflags_text)
987 static const struct flagentry {
992 { "sappnd", "SystemAppend"},
993 { "sappend", "SystemAppend"},
994 { "arch", "SystemArchived"},
995 { "archived", "SystemArchived"},
996 { "schg", "SystemImmutable"},
997 { "schange", "SystemImmutable"},
998 { "simmutable", "SystemImmutable"},
999 { "nosunlnk", "SystemNoUnlink"},
1000 { "nosunlink", "SystemNoUnlink"},
1001 { "snapshot", "SystemSnapshot"},
1002 { "uappnd", "UserAppend"},
1003 { "uappend", "UserAppend"},
1004 { "uchg", "UserImmutable"},
1005 { "uchange", "UserImmutable"},
1006 { "uimmutable", "UserImmutable"},
1007 { "nodump", "UserNoDump"},
1008 { "noopaque", "UserOpaque"},
1009 { "nouunlnk", "UserNoUnlink"},
1010 { "nouunlink", "UserNoUnlink"},
1014 { "sappnd", "AppendOnly"},
1015 { "sappend", "AppendOnly"},
1016 { "schg", "Immutable"},
1017 { "schange", "Immutable"},
1018 { "simmutable", "Immutable"},
1019 { "nodump", "NoDump"},
1020 { "nouunlnk", "Undelete"},
1021 { "nouunlink", "Undelete"},
1022 { "btree", "BTree"},
1023 { "comperr", "CompError"},
1024 { "compress", "Compress"},
1025 { "noatime", "NoAtime"},
1026 { "compdirty", "CompDirty"},
1027 { "comprblk", "CompBlock"},
1028 { "dirsync", "DirSync"},
1029 { "hashidx", "HashIndexed"},
1030 { "imagic", "iMagic"},
1031 { "journal", "Journaled"},
1032 { "securedeletion", "SecureDeletion"},
1033 { "sync", "Synchronous"},
1034 { "notail", "NoTail"},
1035 { "topdir", "TopDir"},
1036 { "reserved", "Reserved"},
1039 const struct flagentry *fe, *flagentry;
1040 #define FLAGENTRY_MAXSIZE ((sizeof(flagbsd)+sizeof(flagext2))/sizeof(flagbsd))
1041 const struct flagentry *avail[FLAGENTRY_MAXSIZE];
1045 if (strcmp(element, "ext2") == 0)
1046 flagentry = flagext2;
1048 flagentry = flagbsd;
1054 cp = strchr(p, ',');
1058 for (fe = flagentry; fe->name != NULL; fe++) {
1059 if (fe->name[cp - p] != '\0'
1060 || p[0] != fe->name[0])
1062 if (strncmp(p, fe->name, cp - p) == 0) {
1071 } while (p != NULL);
1074 r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(element));
1076 archive_set_error(&a->archive,
1078 "xmlTextWriterStartElement() failed: %d", r);
1079 return (ARCHIVE_FATAL);
1081 for (i = 0; i < n; i++) {
1082 r = xmlwrite_string(a, writer,
1083 avail[i]->xarname, NULL);
1084 if (r != ARCHIVE_OK)
1088 r = xmlTextWriterEndElement(writer);
1090 archive_set_error(&a->archive,
1092 "xmlTextWriterEndElement() failed: %d", r);
1093 return (ARCHIVE_FATAL);
1096 return (ARCHIVE_OK);
1100 make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
1104 const char *filetype, *filelink, *fflags;
1105 struct archive_string linkto;
1106 struct heap_data *heap;
1112 xar = (struct xar *)a->format_data;
1116 * Make a file name entry, "<name>".
1118 l = ll = archive_strlen(&(file->basename));
1121 archive_set_error(&a->archive, ENOMEM,
1122 "Can't allocate memory");
1123 return (ARCHIVE_FATAL);
1125 r = UTF8Toisolat1(tmp, &l, BAD_CAST(file->basename.s), &ll);
1128 r = xmlTextWriterStartElement(writer, BAD_CAST("name"));
1130 archive_set_error(&a->archive,
1132 "xmlTextWriterStartElement() failed: %d", r);
1133 return (ARCHIVE_FATAL);
1135 r = xmlTextWriterWriteAttribute(writer,
1136 BAD_CAST("enctype"), BAD_CAST("base64"));
1138 archive_set_error(&a->archive,
1140 "xmlTextWriterWriteAttribute() failed: %d", r);
1141 return (ARCHIVE_FATAL);
1143 r = xmlTextWriterWriteBase64(writer, file->basename.s,
1144 0, archive_strlen(&(file->basename)));
1146 archive_set_error(&a->archive,
1148 "xmlTextWriterWriteBase64() failed: %d", r);
1149 return (ARCHIVE_FATAL);
1151 r = xmlTextWriterEndElement(writer);
1153 archive_set_error(&a->archive,
1155 "xmlTextWriterEndElement() failed: %d", r);
1156 return (ARCHIVE_FATAL);
1159 r = xmlwrite_string(a, writer, "name", file->basename.s);
1161 return (ARCHIVE_FATAL);
1165 * Make a file type entry, "<type>".
1168 archive_string_init(&linkto);
1169 switch (archive_entry_filetype(file->entry)) {
1171 filetype = "directory"; break;
1173 filetype = "symlink"; break;
1175 filetype = "character special"; break;
1177 filetype = "block special"; break;
1179 filetype = "socket"; break;
1181 filetype = "fifo"; break;
1184 if (file->hardlink_target != NULL) {
1185 filetype = "hardlink";
1187 if (file->hardlink_target == file)
1188 archive_strcpy(&linkto, "original");
1190 archive_string_sprintf(&linkto, "%d",
1191 file->hardlink_target->id);
1196 r = xmlwrite_string_attr(a, writer, "type", filetype,
1197 filelink, linkto.s);
1198 archive_string_free(&linkto);
1200 return (ARCHIVE_FATAL);
1203 * On a virtual directory, we record "name" and "type" only.
1206 return (ARCHIVE_OK);
1208 switch (archive_entry_filetype(file->entry)) {
1211 * xar utility has checked a file type, which
1212 * a symblic-link file has referenced.
1214 * <link type="directory">../ref/</link>
1215 * The symlink target file is "../ref/" and its
1216 * file type is a directory.
1218 * <link type="file">../f</link>
1219 * The symlink target file is "../f" and its
1220 * file type is a regular file.
1222 * But our implemention cannot do it, and then we
1223 * always record that a attribute "type" is "borken",
1225 * <link type="broken">foo/bar</link>
1226 * It means "foo/bar" is not reachable.
1228 r = xmlwrite_string_attr(a, writer, "link",
1232 return (ARCHIVE_FATAL);
1236 r = xmlTextWriterStartElement(writer, BAD_CAST("device"));
1238 archive_set_error(&a->archive,
1240 "xmlTextWriterStartElement() failed: %d", r);
1241 return (ARCHIVE_FATAL);
1243 r = xmlwrite_fstring(a, writer, "major",
1244 "%d", archive_entry_rdevmajor(file->entry));
1246 return (ARCHIVE_FATAL);
1247 r = xmlwrite_fstring(a, writer, "minor",
1248 "%d", archive_entry_rdevminor(file->entry));
1250 return (ARCHIVE_FATAL);
1251 r = xmlTextWriterEndElement(writer);
1253 archive_set_error(&a->archive,
1255 "xmlTextWriterEndElement() failed: %d", r);
1256 return (ARCHIVE_FATAL);
1264 * Make a inode entry, "<inode>".
1266 r = xmlwrite_fstring(a, writer, "inode",
1267 "%jd", archive_entry_ino64(file->entry));
1269 return (ARCHIVE_FATAL);
1270 if (archive_entry_dev(file->entry) != 0) {
1271 r = xmlwrite_fstring(a, writer, "deviceno",
1272 "%d", archive_entry_dev(file->entry));
1274 return (ARCHIVE_FATAL);
1278 * Make a file mode entry, "<mode>".
1280 r = xmlwrite_mode(a, writer, "mode",
1281 archive_entry_mode(file->entry));
1283 return (ARCHIVE_FATAL);
1286 * Make a user entry, "<uid>" and "<user>.
1288 r = xmlwrite_fstring(a, writer, "uid",
1289 "%d", archive_entry_uid(file->entry));
1291 return (ARCHIVE_FATAL);
1292 r = archive_entry_uname_l(file->entry, &p, &len, xar->sconv);
1294 if (errno == ENOMEM) {
1295 archive_set_error(&a->archive, ENOMEM,
1296 "Can't allocate memory for Uname");
1297 return (ARCHIVE_FATAL);
1299 archive_set_error(&a->archive,
1300 ARCHIVE_ERRNO_FILE_FORMAT,
1301 "Can't translate uname '%s' to UTF-8",
1302 archive_entry_uname(file->entry));
1306 r = xmlwrite_string(a, writer, "user", p);
1308 return (ARCHIVE_FATAL);
1312 * Make a group entry, "<gid>" and "<group>.
1314 r = xmlwrite_fstring(a, writer, "gid",
1315 "%d", archive_entry_gid(file->entry));
1317 return (ARCHIVE_FATAL);
1318 r = archive_entry_gname_l(file->entry, &p, &len, xar->sconv);
1320 if (errno == ENOMEM) {
1321 archive_set_error(&a->archive, ENOMEM,
1322 "Can't allocate memory for Gname");
1323 return (ARCHIVE_FATAL);
1325 archive_set_error(&a->archive,
1326 ARCHIVE_ERRNO_FILE_FORMAT,
1327 "Can't translate gname '%s' to UTF-8",
1328 archive_entry_gname(file->entry));
1332 r = xmlwrite_string(a, writer, "group", p);
1334 return (ARCHIVE_FATAL);
1338 * Make a ctime entry, "<ctime>".
1340 if (archive_entry_ctime_is_set(file->entry)) {
1341 r = xmlwrite_time(a, writer, "ctime",
1342 archive_entry_ctime(file->entry), 1);
1344 return (ARCHIVE_FATAL);
1348 * Make a mtime entry, "<mtime>".
1350 if (archive_entry_mtime_is_set(file->entry)) {
1351 r = xmlwrite_time(a, writer, "mtime",
1352 archive_entry_mtime(file->entry), 1);
1354 return (ARCHIVE_FATAL);
1358 * Make a atime entry, "<atime>".
1360 if (archive_entry_atime_is_set(file->entry)) {
1361 r = xmlwrite_time(a, writer, "atime",
1362 archive_entry_atime(file->entry), 1);
1364 return (ARCHIVE_FATAL);
1368 * Make fflags entries, "<flags>" and "<ext2>".
1370 fflags = archive_entry_fflags_text(file->entry);
1371 if (fflags != NULL) {
1372 r = make_fflags_entry(a, writer, "flags", fflags);
1375 r = make_fflags_entry(a, writer, "ext2", fflags);
1381 * Make extended attribute entries, "<ea>".
1383 archive_entry_xattr_reset(file->entry);
1384 for (heap = file->xattr.first; heap != NULL; heap = heap->next) {
1389 archive_entry_xattr_next(file->entry,
1390 &name, &value, &size);
1391 r = xmlTextWriterStartElement(writer, BAD_CAST("ea"));
1393 archive_set_error(&a->archive,
1395 "xmlTextWriterStartElement() failed: %d", r);
1396 return (ARCHIVE_FATAL);
1398 r = xmlTextWriterWriteFormatAttribute(writer,
1399 BAD_CAST("id"), "%d", heap->id);
1401 archive_set_error(&a->archive,
1403 "xmlTextWriterWriteAttribute() failed: %d", r);
1404 return (ARCHIVE_FATAL);
1406 r = xmlwrite_heap(a, writer, heap);
1408 return (ARCHIVE_FATAL);
1409 r = xmlwrite_string(a, writer, "name", name);
1411 return (ARCHIVE_FATAL);
1413 r = xmlTextWriterEndElement(writer);
1415 archive_set_error(&a->archive,
1417 "xmlTextWriterEndElement() failed: %d", r);
1418 return (ARCHIVE_FATAL);
1423 * Make a file data entry, "<data>".
1425 if (file->data.length > 0) {
1426 r = xmlTextWriterStartElement(writer, BAD_CAST("data"));
1428 archive_set_error(&a->archive,
1430 "xmlTextWriterStartElement() failed: %d", r);
1431 return (ARCHIVE_FATAL);
1434 r = xmlwrite_heap(a, writer, &(file->data));
1436 return (ARCHIVE_FATAL);
1438 r = xmlTextWriterEndElement(writer);
1440 archive_set_error(&a->archive,
1442 "xmlTextWriterEndElement() failed: %d", r);
1443 return (ARCHIVE_FATAL);
1447 if (archive_strlen(&file->script) > 0) {
1448 r = xmlTextWriterStartElement(writer, BAD_CAST("content"));
1450 archive_set_error(&a->archive,
1452 "xmlTextWriterStartElement() failed: %d", r);
1453 return (ARCHIVE_FATAL);
1456 r = xmlwrite_string(a, writer,
1457 "interpreter", file->script.s);
1459 return (ARCHIVE_FATAL);
1461 r = xmlwrite_string(a, writer, "type", "script");
1463 return (ARCHIVE_FATAL);
1465 r = xmlTextWriterEndElement(writer);
1467 archive_set_error(&a->archive,
1469 "xmlTextWriterEndElement() failed: %d", r);
1470 return (ARCHIVE_FATAL);
1481 make_toc(struct archive_write *a)
1486 xmlTextWriterPtr writer;
1490 xar = (struct xar *)a->format_data;
1492 ret = ARCHIVE_FATAL;
1495 * Initialize xml writer.
1498 bp = xmlBufferCreate();
1500 archive_set_error(&a->archive, ENOMEM,
1501 "xmlBufferCreate() "
1502 "couldn't create xml buffer");
1505 writer = xmlNewTextWriterMemory(bp, 0);
1506 if (writer == NULL) {
1507 archive_set_error(&a->archive,
1509 "xmlNewTextWriterMemory() "
1510 "couldn't create xml writer");
1513 r = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL);
1515 archive_set_error(&a->archive,
1517 "xmlTextWriterStartDocument() failed: %d", r);
1520 r = xmlTextWriterSetIndent(writer, 4);
1522 archive_set_error(&a->archive,
1524 "xmlTextWriterSetIndent() failed: %d", r);
1529 * Start recoding TOC
1531 r = xmlTextWriterStartElement(writer, BAD_CAST("xar"));
1533 archive_set_error(&a->archive,
1535 "xmlTextWriterStartElement() failed: %d", r);
1538 r = xmlTextWriterStartElement(writer, BAD_CAST("toc"));
1540 archive_set_error(&a->archive,
1542 "xmlTextWriterStartDocument() failed: %d", r);
1547 * Record the creation time of the archive file.
1549 r = xmlwrite_time(a, writer, "creation-time", time(NULL), 0);
1554 * Record the checksum value of TOC
1556 algsize = getalgsize(xar->opt_toc_sumalg);
1559 * Record TOC checksum
1561 r = xmlTextWriterStartElement(writer, BAD_CAST("checksum"));
1563 archive_set_error(&a->archive,
1565 "xmlTextWriterStartElement() failed: %d", r);
1568 r = xmlTextWriterWriteAttribute(writer, BAD_CAST("style"),
1569 BAD_CAST_CONST(getalgname(xar->opt_toc_sumalg)));
1571 archive_set_error(&a->archive,
1573 "xmlTextWriterWriteAttribute() failed: %d", r);
1578 * Record the offset of the value of checksum of TOC
1580 r = xmlwrite_string(a, writer, "offset", "0");
1585 * Record the size of the value of checksum of TOC
1587 r = xmlwrite_fstring(a, writer, "size", "%d", algsize);
1591 r = xmlTextWriterEndElement(writer);
1593 archive_set_error(&a->archive,
1595 "xmlTextWriterEndElement() failed: %d", r);
1602 if (np != np->parent) {
1603 r = make_file_entry(a, writer, np);
1604 if (r != ARCHIVE_OK)
1608 if (np->dir && np->children.first != NULL) {
1609 /* Enter to sub directories. */
1610 np = np->children.first;
1611 r = xmlTextWriterStartElement(writer,
1614 archive_set_error(&a->archive,
1616 "xmlTextWriterStartElement() "
1620 r = xmlTextWriterWriteFormatAttribute(
1621 writer, BAD_CAST("id"), "%d", np->id);
1623 archive_set_error(&a->archive,
1625 "xmlTextWriterWriteAttribute() "
1631 while (np != np->parent) {
1632 r = xmlTextWriterEndElement(writer);
1634 archive_set_error(&a->archive,
1636 "xmlTextWriterEndElement() "
1640 if (np->chnext == NULL) {
1641 /* Return to the parent directory. */
1645 r = xmlTextWriterStartElement(writer,
1648 archive_set_error(&a->archive,
1650 "xmlTextWriterStartElement() "
1654 r = xmlTextWriterWriteFormatAttribute(
1655 writer, BAD_CAST("id"), "%d", np->id);
1657 archive_set_error(&a->archive,
1659 "xmlTextWriterWriteAttribute() "
1666 } while (np != np->parent);
1668 r = xmlTextWriterEndDocument(writer);
1670 archive_set_error(&a->archive,
1672 "xmlTextWriterEndDocument() failed: %d", r);
1676 fprintf(stderr, "\n---TOC-- %d bytes --\n%s\n",
1677 strlen((const char *)bp->content), bp->content);
1681 * Compress the TOC and calculate the sum of the TOC.
1683 xar->toc.temp_offset = xar->temp_offset;
1684 xar->toc.size = bp->use;
1685 checksum_init(&(xar->a_sumwrk), xar->opt_toc_sumalg);
1687 r = compression_init_encoder_gzip(&(a->archive),
1688 &(xar->stream), 6, 1);
1689 if (r != ARCHIVE_OK)
1691 xar->stream.next_in = bp->content;
1692 xar->stream.avail_in = bp->use;
1693 xar->stream.total_in = 0;
1694 xar->stream.next_out = xar->wbuff;
1695 xar->stream.avail_out = sizeof(xar->wbuff);
1696 xar->stream.total_out = 0;
1700 r = compression_code(&(a->archive),
1701 &(xar->stream), ARCHIVE_Z_FINISH);
1702 if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
1704 size = sizeof(xar->wbuff) - xar->stream.avail_out;
1705 checksum_update(&(xar->a_sumwrk), xar->wbuff, size);
1706 if (write_to_temp(a, xar->wbuff, size) != ARCHIVE_OK)
1708 if (r == ARCHIVE_EOF)
1710 xar->stream.next_out = xar->wbuff;
1711 xar->stream.avail_out = sizeof(xar->wbuff);
1713 r = compression_end(&(a->archive), &(xar->stream));
1714 if (r != ARCHIVE_OK)
1716 xar->toc.length = xar->stream.total_out;
1717 xar->toc.compression = GZIP;
1718 checksum_final(&(xar->a_sumwrk), &(xar->toc.a_sum));
1723 xmlFreeTextWriter(writer);
1731 flush_wbuff(struct archive_write *a)
1737 xar = (struct xar *)a->format_data;
1738 s = sizeof(xar->wbuff) - xar->wbuff_remaining;
1739 r = __archive_write_output(a, xar->wbuff, s);
1740 if (r != ARCHIVE_OK)
1742 xar->wbuff_remaining = sizeof(xar->wbuff);
1747 copy_out(struct archive_write *a, uint64_t offset, uint64_t length)
1752 xar = (struct xar *)a->format_data;
1753 if (lseek(xar->temp_fd, offset, SEEK_SET) < 0) {
1754 archive_set_error(&(a->archive), errno, "lseek failed");
1755 return (ARCHIVE_FATAL);
1762 if (length > xar->wbuff_remaining)
1763 rsize = xar->wbuff_remaining;
1765 rsize = (size_t)length;
1766 wb = xar->wbuff + (sizeof(xar->wbuff) - xar->wbuff_remaining);
1767 rs = read(xar->temp_fd, wb, rsize);
1769 archive_set_error(&(a->archive), errno,
1770 "Can't read temporary file(%jd)",
1772 return (ARCHIVE_FATAL);
1775 archive_set_error(&(a->archive), 0,
1776 "Truncated xar archive");
1777 return (ARCHIVE_FATAL);
1779 xar->wbuff_remaining -= rs;
1781 if (xar->wbuff_remaining == 0) {
1783 if (r != ARCHIVE_OK)
1787 return (ARCHIVE_OK);
1791 xar_close(struct archive_write *a)
1798 xar = (struct xar *)a->format_data;
1801 if (xar->root->children.first == NULL)
1802 return (ARCHIVE_OK);
1804 /* Save the length of all file extended attributes and contents. */
1805 length = xar->temp_offset;
1807 /* Connect hardlinked files */
1808 file_connect_hardlink_files(xar);
1812 if (r != ARCHIVE_OK)
1815 * Make the xar header on wbuff(write buffer).
1818 xar->wbuff_remaining = sizeof(xar->wbuff);
1819 archive_be32enc(&wb[0], HEADER_MAGIC);
1820 archive_be16enc(&wb[4], HEADER_SIZE);
1821 archive_be16enc(&wb[6], HEADER_VERSION);
1822 archive_be64enc(&wb[8], xar->toc.length);
1823 archive_be64enc(&wb[16], xar->toc.size);
1824 archive_be32enc(&wb[24], xar->toc.a_sum.alg);
1825 xar->wbuff_remaining -= HEADER_SIZE;
1830 r = copy_out(a, xar->toc.temp_offset, xar->toc.length);
1831 if (r != ARCHIVE_OK)
1834 /* Write the checksum value of the TOC. */
1835 if (xar->toc.a_sum.len) {
1836 if (xar->wbuff_remaining < xar->toc.a_sum.len) {
1838 if (r != ARCHIVE_OK)
1841 wb = xar->wbuff + (sizeof(xar->wbuff) - xar->wbuff_remaining);
1842 memcpy(wb, xar->toc.a_sum.val, xar->toc.a_sum.len);
1843 xar->wbuff_remaining -= xar->toc.a_sum.len;
1847 * Write all file extended attributes and contents.
1849 r = copy_out(a, xar->toc.a_sum.len, length);
1850 if (r != ARCHIVE_OK)
1857 xar_free(struct archive_write *a)
1861 xar = (struct xar *)a->format_data;
1862 archive_string_free(&(xar->cur_dirstr));
1863 archive_string_free(&(xar->tstr));
1864 archive_string_free(&(xar->vstr));
1865 file_free_hardlinks(xar);
1866 file_free_register(xar);
1867 compression_end(&(a->archive), &(xar->stream));
1870 return (ARCHIVE_OK);
1874 file_cmp_node(const struct archive_rb_node *n1,
1875 const struct archive_rb_node *n2)
1877 const struct file *f1 = (const struct file *)n1;
1878 const struct file *f2 = (const struct file *)n2;
1880 return (strcmp(f1->basename.s, f2->basename.s));
1884 file_cmp_key(const struct archive_rb_node *n, const void *key)
1886 const struct file *f = (const struct file *)n;
1888 return (strcmp(f->basename.s, (const char *)key));
1891 static struct file *
1892 file_new(struct archive_write *a, struct archive_entry *entry)
1895 static const struct archive_rb_tree_ops rb_ops = {
1896 file_cmp_node, file_cmp_key
1899 file = calloc(1, sizeof(*file));
1904 file->entry = archive_entry_clone(entry);
1906 file->entry = archive_entry_new2(&a->archive);
1907 if (file->entry == NULL) {
1911 __archive_rb_tree_init(&(file->rbtree), &rb_ops);
1912 file->children.first = NULL;
1913 file->children.last = &(file->children.first);
1914 file->xattr.first = NULL;
1915 file->xattr.last = &(file->xattr.first);
1916 archive_string_init(&(file->parentdir));
1917 archive_string_init(&(file->basename));
1918 archive_string_init(&(file->symlink));
1919 archive_string_init(&(file->script));
1920 if (entry != NULL && archive_entry_filetype(entry) == AE_IFDIR)
1927 file_free(struct file *file)
1929 struct heap_data *heap, *next_heap;
1931 heap = file->xattr.first;
1932 while (heap != NULL) {
1933 next_heap = heap->next;
1937 archive_string_free(&(file->parentdir));
1938 archive_string_free(&(file->basename));
1939 archive_string_free(&(file->symlink));
1940 archive_string_free(&(file->script));
1944 static struct file *
1945 file_create_virtual_dir(struct archive_write *a, struct xar *xar,
1946 const char *pathname)
1950 (void)xar; /* UNUSED */
1952 file = file_new(a, NULL);
1955 archive_entry_set_pathname(file->entry, pathname);
1956 archive_entry_set_mode(file->entry, 0555 | AE_IFDIR);
1965 file_add_child_tail(struct file *parent, struct file *child)
1967 if (!__archive_rb_tree_insert_node(
1968 &(parent->rbtree), (struct archive_rb_node *)child))
1970 child->chnext = NULL;
1971 *parent->children.last = child;
1972 parent->children.last = &(child->chnext);
1973 child->parent = parent;
1978 * Find a entry from `parent'
1980 static struct file *
1981 file_find_child(struct file *parent, const char *child_name)
1985 np = (struct file *)__archive_rb_tree_find_node(
1986 &(parent->rbtree), child_name);
1990 #if defined(_WIN32) || defined(__CYGWIN__)
1992 cleanup_backslash(char *utf8, size_t len)
1995 /* Convert a path-separator from '\' to '/' */
1996 while (*utf8 != '\0' && len) {
2004 #define cleanup_backslash(p, len) /* nop */
2008 * Generate a parent directory name and a base name from a pathname.
2011 file_gen_utility_names(struct archive_write *a, struct file *file)
2015 char *p, *dirname, *slash;
2019 xar = (struct xar *)a->format_data;
2020 archive_string_empty(&(file->parentdir));
2021 archive_string_empty(&(file->basename));
2022 archive_string_empty(&(file->symlink));
2024 if (file->parent == file)/* virtual root */
2025 return (ARCHIVE_OK);
2027 if (archive_entry_pathname_l(file->entry, &pp, &len, xar->sconv)
2029 if (errno == ENOMEM) {
2030 archive_set_error(&a->archive, ENOMEM,
2031 "Can't allocate memory for Pathname");
2032 return (ARCHIVE_FATAL);
2034 archive_set_error(&a->archive,
2035 ARCHIVE_ERRNO_FILE_FORMAT,
2036 "Can't translate pathname '%s' to UTF-8",
2037 archive_entry_pathname(file->entry));
2040 archive_strncpy(&(file->parentdir), pp, len);
2041 len = file->parentdir.length;
2042 p = dirname = file->parentdir.s;
2044 * Convert a path-separator from '\' to '/'
2046 cleanup_backslash(p, len);
2049 * Remove leading '/', '../' and './' elements
2055 } else if (p[0] != '.')
2057 else if (p[1] == '.' && p[2] == '/') {
2060 } else if (p[1] == '/' || (p[1] == '.' && p[2] == '\0')) {
2063 } else if (p[1] == '\0') {
2070 memmove(dirname, p, len+1);
2074 * Remove "/","/." and "/.." elements from tail.
2079 if (len > 0 && p[len-1] == '/') {
2083 if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
2087 if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
2098 /* Convert '//' --> '/' */
2100 else if (p[1] == '.' && p[2] == '/')
2101 /* Convert '/./' --> '/' */
2103 else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
2104 /* Convert 'dir/dir1/../dir2/'
2108 while (rp >= dirname) {
2117 strcpy(dirname, p+4);
2128 if (archive_entry_filetype(file->entry) == AE_IFLNK) {
2130 /* Convert symlink name too. */
2131 if (archive_entry_symlink_l(file->entry, &pp, &len2,
2133 if (errno == ENOMEM) {
2134 archive_set_error(&a->archive, ENOMEM,
2135 "Can't allocate memory for Linkname");
2136 return (ARCHIVE_FATAL);
2138 archive_set_error(&a->archive,
2139 ARCHIVE_ERRNO_FILE_FORMAT,
2140 "Can't translate symlink '%s' to UTF-8",
2141 archive_entry_symlink(file->entry));
2144 archive_strncpy(&(file->symlink), pp, len2);
2145 cleanup_backslash(file->symlink.s, file->symlink.length);
2148 * - Count up directory elements.
2149 * - Find out the position which points the last position of
2150 * path separator('/').
2153 for (; *p != '\0'; p++)
2156 if (slash == NULL) {
2157 /* The pathname doesn't have a parent directory. */
2158 file->parentdir.length = len;
2159 archive_string_copy(&(file->basename), &(file->parentdir));
2160 archive_string_empty(&(file->parentdir));
2161 file->parentdir.s = '\0';
2165 /* Make a basename from dirname and slash */
2167 file->parentdir.length = slash - dirname;
2168 archive_strcpy(&(file->basename), slash + 1);
2173 get_path_component(char *name, int n, const char *fn)
2178 p = strchr(fn, '/');
2180 if ((l = strlen(fn)) == 0)
2186 memcpy(name, fn, l);
2193 * Add a new entry into the tree.
2196 file_tree(struct archive_write *a, struct file **filepp)
2198 #if defined(_WIN32) && !defined(__CYGWIN__)
2199 char name[_MAX_FNAME];/* Included null terminator size. */
2200 #elif defined(NAME_MAX) && NAME_MAX >= 255
2201 char name[NAME_MAX+1];
2205 struct xar *xar = (struct xar *)a->format_data;
2206 struct file *dent, *file, *np;
2207 struct archive_entry *ent;
2213 if (file->parentdir.length > 0)
2214 fn = p = file->parentdir.s;
2219 * If the path of the parent directory of `file' entry is
2220 * the same as the path of `cur_dirent', add isoent to
2223 if (archive_strlen(&(xar->cur_dirstr))
2224 == archive_strlen(&(file->parentdir)) &&
2225 strcmp(xar->cur_dirstr.s, fn) == 0) {
2226 if (!file_add_child_tail(xar->cur_dirent, file)) {
2227 np = (struct file *)__archive_rb_tree_find_node(
2228 &(xar->cur_dirent->rbtree),
2232 return (ARCHIVE_OK);
2236 l = get_path_component(name, sizeof(name), fn);
2242 archive_set_error(&a->archive,
2244 "A name buffer is too small");
2247 return (ARCHIVE_FATAL);
2250 np = file_find_child(dent, name);
2251 if (np == NULL || fn[0] == '\0')
2254 /* Find next subdirectory. */
2256 /* NOT Directory! */
2257 archive_set_error(&a->archive,
2259 "`%s' is not directory, we cannot insert `%s' ",
2260 archive_entry_pathname(np->entry),
2261 archive_entry_pathname(file->entry));
2264 return (ARCHIVE_FAILED);
2273 * Create virtual parent directories.
2275 while (fn[0] != '\0') {
2277 struct archive_string as;
2279 archive_string_init(&as);
2280 archive_strncat(&as, p, fn - p + l);
2281 if (as.s[as.length-1] == '/') {
2282 as.s[as.length-1] = '\0';
2285 vp = file_create_virtual_dir(a, xar, as.s);
2287 archive_string_free(&as);
2288 archive_set_error(&a->archive, ENOMEM,
2289 "Can't allocate memory");
2292 return (ARCHIVE_FATAL);
2294 archive_string_free(&as);
2295 if (file_gen_utility_names(a, vp) <= ARCHIVE_FAILED)
2296 return (ARCHIVE_FATAL);
2297 file_add_child_tail(dent, vp);
2298 file_register(xar, vp);
2304 l = get_path_component(name, sizeof(name), fn);
2306 archive_string_free(&as);
2307 archive_set_error(&a->archive,
2309 "A name buffer is too small");
2312 return (ARCHIVE_FATAL);
2317 /* Found out the parent directory where isoent can be
2319 xar->cur_dirent = dent;
2320 archive_string_empty(&(xar->cur_dirstr));
2321 archive_string_ensure(&(xar->cur_dirstr),
2322 archive_strlen(&(dent->parentdir)) +
2323 archive_strlen(&(dent->basename)) + 2);
2324 if (archive_strlen(&(dent->parentdir)) +
2325 archive_strlen(&(dent->basename)) == 0)
2326 xar->cur_dirstr.s[0] = 0;
2328 if (archive_strlen(&(dent->parentdir)) > 0) {
2329 archive_string_copy(&(xar->cur_dirstr),
2330 &(dent->parentdir));
2331 archive_strappend_char(&(xar->cur_dirstr), '/');
2333 archive_string_concat(&(xar->cur_dirstr),
2337 if (!file_add_child_tail(dent, file)) {
2338 np = (struct file *)__archive_rb_tree_find_node(
2339 &(dent->rbtree), file->basename.s);
2342 return (ARCHIVE_OK);
2347 * We have already has the entry the filename of which is
2350 if (archive_entry_filetype(np->entry) !=
2351 archive_entry_filetype(file->entry)) {
2352 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2353 "Found duplicate entries `%s' and its file type is "
2355 archive_entry_pathname(np->entry));
2358 return (ARCHIVE_FAILED);
2363 np->entry = file->entry;
2369 return (ARCHIVE_OK);
2373 file_register(struct xar *xar, struct file *file)
2375 file->id = xar->file_idx++;
2377 *xar->file_list.last = file;
2378 xar->file_list.last = &(file->next);
2382 file_init_register(struct xar *xar)
2384 xar->file_list.first = NULL;
2385 xar->file_list.last = &(xar->file_list.first);
2389 file_free_register(struct xar *xar)
2391 struct file *file, *file_next;
2393 file = xar->file_list.first;
2394 while (file != NULL) {
2395 file_next = file->next;
2402 * Register entry to get a hardlink target.
2405 file_register_hardlink(struct archive_write *a, struct file *file)
2407 struct xar *xar = (struct xar *)a->format_data;
2408 struct hardlink *hl;
2409 const char *pathname;
2411 archive_entry_set_nlink(file->entry, 1);
2412 pathname = archive_entry_hardlink(file->entry);
2413 if (pathname == NULL) {
2414 /* This `file` is a hardlink target. */
2415 hl = malloc(sizeof(*hl));
2417 archive_set_error(&a->archive, ENOMEM,
2418 "Can't allocate memory");
2419 return (ARCHIVE_FATAL);
2422 /* A hardlink target must be the first position. */
2423 file->hlnext = NULL;
2424 hl->file_list.first = file;
2425 hl->file_list.last = &(file->hlnext);
2426 __archive_rb_tree_insert_node(&(xar->hardlink_rbtree),
2427 (struct archive_rb_node *)hl);
2429 hl = (struct hardlink *)__archive_rb_tree_find_node(
2430 &(xar->hardlink_rbtree), pathname);
2432 /* Insert `file` entry into the tail. */
2433 file->hlnext = NULL;
2434 *hl->file_list.last = file;
2435 hl->file_list.last = &(file->hlnext);
2438 archive_entry_unset_size(file->entry);
2441 return (ARCHIVE_OK);
2445 * Hardlinked files have to have the same location of extent.
2446 * We have to find out hardlink target entries for entries which
2447 * have a hardlink target name.
2450 file_connect_hardlink_files(struct xar *xar)
2452 struct archive_rb_node *n;
2453 struct hardlink *hl;
2454 struct file *target, *nf;
2456 ARCHIVE_RB_TREE_FOREACH(n, &(xar->hardlink_rbtree)) {
2457 hl = (struct hardlink *)n;
2459 /* The first entry must be a hardlink target. */
2460 target = hl->file_list.first;
2461 archive_entry_set_nlink(target->entry, hl->nlink);
2463 /* It means this file is a hardlink
2465 target->hardlink_target = target;
2466 for (nf = target->hlnext;
2467 nf != NULL; nf = nf->hlnext) {
2468 nf->hardlink_target = target;
2469 archive_entry_set_nlink(nf->entry, hl->nlink);
2475 file_hd_cmp_node(const struct archive_rb_node *n1,
2476 const struct archive_rb_node *n2)
2478 const struct hardlink *h1 = (const struct hardlink *)n1;
2479 const struct hardlink *h2 = (const struct hardlink *)n2;
2481 return (strcmp(archive_entry_pathname(h1->file_list.first->entry),
2482 archive_entry_pathname(h2->file_list.first->entry)));
2486 file_hd_cmp_key(const struct archive_rb_node *n, const void *key)
2488 const struct hardlink *h = (const struct hardlink *)n;
2490 return (strcmp(archive_entry_pathname(h->file_list.first->entry),
2491 (const char *)key));
2496 file_init_hardlinks(struct xar *xar)
2498 static const struct archive_rb_tree_ops rb_ops = {
2499 file_hd_cmp_node, file_hd_cmp_key,
2502 __archive_rb_tree_init(&(xar->hardlink_rbtree), &rb_ops);
2506 file_free_hardlinks(struct xar *xar)
2508 struct archive_rb_node *n, *next;
2510 for (n = ARCHIVE_RB_TREE_MIN(&(xar->hardlink_rbtree)); n;) {
2511 next = __archive_rb_tree_iterate(&(xar->hardlink_rbtree),
2512 n, ARCHIVE_RB_DIR_RIGHT);
2519 checksum_init(struct chksumwork *sumwrk, enum sumalg sum_alg)
2521 sumwrk->alg = sum_alg;
2526 archive_sha1_init(&(sumwrk->sha1ctx));
2529 archive_md5_init(&(sumwrk->md5ctx));
2535 checksum_update(struct chksumwork *sumwrk, const void *buff, size_t size)
2538 switch (sumwrk->alg) {
2542 archive_sha1_update(&(sumwrk->sha1ctx), buff, size);
2545 archive_md5_update(&(sumwrk->md5ctx), buff, size);
2551 checksum_final(struct chksumwork *sumwrk, struct chksumval *sumval)
2554 switch (sumwrk->alg) {
2559 archive_sha1_final(&(sumwrk->sha1ctx), sumval->val);
2560 sumval->len = SHA1_SIZE;
2563 archive_md5_final(&(sumwrk->md5ctx), sumval->val);
2564 sumval->len = MD5_SIZE;
2567 sumval->alg = sumwrk->alg;
2570 #if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
2572 compression_unsupported_encoder(struct archive *a,
2573 struct la_zstream *lastrm, const char *name)
2576 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2577 "%s compression not supported on this platform", name);
2579 lastrm->real_stream = NULL;
2580 return (ARCHIVE_FAILED);
2585 compression_init_encoder_gzip(struct archive *a,
2586 struct la_zstream *lastrm, int level, int withheader)
2591 compression_end(a, lastrm);
2592 strm = calloc(1, sizeof(*strm));
2594 archive_set_error(a, ENOMEM,
2595 "Can't allocate memory for gzip stream");
2596 return (ARCHIVE_FATAL);
2598 /* zlib.h is not const-correct, so we need this one bit
2599 * of ugly hackery to convert a const * pointer to
2600 * a non-const pointer. */
2601 strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
2602 strm->avail_in = lastrm->avail_in;
2603 strm->total_in = lastrm->total_in;
2604 strm->next_out = lastrm->next_out;
2605 strm->avail_out = lastrm->avail_out;
2606 strm->total_out = lastrm->total_out;
2607 if (deflateInit2(strm, level, Z_DEFLATED,
2608 (withheader)?15:-15,
2609 8, Z_DEFAULT_STRATEGY) != Z_OK) {
2611 lastrm->real_stream = NULL;
2612 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2613 "Internal error initializing compression library");
2614 return (ARCHIVE_FATAL);
2616 lastrm->real_stream = strm;
2618 lastrm->code = compression_code_gzip;
2619 lastrm->end = compression_end_gzip;
2620 return (ARCHIVE_OK);
2624 compression_code_gzip(struct archive *a,
2625 struct la_zstream *lastrm, enum la_zaction action)
2630 strm = (z_stream *)lastrm->real_stream;
2631 /* zlib.h is not const-correct, so we need this one bit
2632 * of ugly hackery to convert a const * pointer to
2633 * a non-const pointer. */
2634 strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
2635 strm->avail_in = lastrm->avail_in;
2636 strm->total_in = lastrm->total_in;
2637 strm->next_out = lastrm->next_out;
2638 strm->avail_out = lastrm->avail_out;
2639 strm->total_out = lastrm->total_out;
2641 (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH);
2642 lastrm->next_in = strm->next_in;
2643 lastrm->avail_in = strm->avail_in;
2644 lastrm->total_in = strm->total_in;
2645 lastrm->next_out = strm->next_out;
2646 lastrm->avail_out = strm->avail_out;
2647 lastrm->total_out = strm->total_out;
2650 return (ARCHIVE_OK);
2652 return (ARCHIVE_EOF);
2654 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2655 "GZip compression failed:"
2656 " deflate() call returned status %d", r);
2657 return (ARCHIVE_FATAL);
2662 compression_end_gzip(struct archive *a, struct la_zstream *lastrm)
2667 strm = (z_stream *)lastrm->real_stream;
2668 r = deflateEnd(strm);
2670 lastrm->real_stream = NULL;
2673 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2674 "Failed to clean up compressor");
2675 return (ARCHIVE_FATAL);
2677 return (ARCHIVE_OK);
2680 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
2682 compression_init_encoder_bzip2(struct archive *a,
2683 struct la_zstream *lastrm, int level)
2688 compression_end(a, lastrm);
2689 strm = calloc(1, sizeof(*strm));
2691 archive_set_error(a, ENOMEM,
2692 "Can't allocate memory for bzip2 stream");
2693 return (ARCHIVE_FATAL);
2695 /* bzlib.h is not const-correct, so we need this one bit
2696 * of ugly hackery to convert a const * pointer to
2697 * a non-const pointer. */
2698 strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
2699 strm->avail_in = lastrm->avail_in;
2700 strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
2701 strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
2702 strm->next_out = (char *)lastrm->next_out;
2703 strm->avail_out = lastrm->avail_out;
2704 strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
2705 strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
2706 if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) {
2708 lastrm->real_stream = NULL;
2709 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2710 "Internal error initializing compression library");
2711 return (ARCHIVE_FATAL);
2713 lastrm->real_stream = strm;
2715 lastrm->code = compression_code_bzip2;
2716 lastrm->end = compression_end_bzip2;
2717 return (ARCHIVE_OK);
2721 compression_code_bzip2(struct archive *a,
2722 struct la_zstream *lastrm, enum la_zaction action)
2727 strm = (bz_stream *)lastrm->real_stream;
2728 /* bzlib.h is not const-correct, so we need this one bit
2729 * of ugly hackery to convert a const * pointer to
2730 * a non-const pointer. */
2731 strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
2732 strm->avail_in = lastrm->avail_in;
2733 strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
2734 strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
2735 strm->next_out = (char *)lastrm->next_out;
2736 strm->avail_out = lastrm->avail_out;
2737 strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
2738 strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
2739 r = BZ2_bzCompress(strm,
2740 (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN);
2741 lastrm->next_in = (const unsigned char *)strm->next_in;
2742 lastrm->avail_in = strm->avail_in;
2744 (((uint64_t)(uint32_t)strm->total_in_hi32) << 32)
2745 + (uint64_t)(uint32_t)strm->total_in_lo32;
2746 lastrm->next_out = (unsigned char *)strm->next_out;
2747 lastrm->avail_out = strm->avail_out;
2749 (((uint64_t)(uint32_t)strm->total_out_hi32) << 32)
2750 + (uint64_t)(uint32_t)strm->total_out_lo32;
2752 case BZ_RUN_OK: /* Non-finishing */
2753 case BZ_FINISH_OK: /* Finishing: There's more work to do */
2754 return (ARCHIVE_OK);
2755 case BZ_STREAM_END: /* Finishing: all done */
2756 /* Only occurs in finishing case */
2757 return (ARCHIVE_EOF);
2759 /* Any other return value indicates an error */
2760 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2761 "Bzip2 compression failed:"
2762 " BZ2_bzCompress() call returned status %d", r);
2763 return (ARCHIVE_FATAL);
2768 compression_end_bzip2(struct archive *a, struct la_zstream *lastrm)
2773 strm = (bz_stream *)lastrm->real_stream;
2774 r = BZ2_bzCompressEnd(strm);
2776 lastrm->real_stream = NULL;
2779 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2780 "Failed to clean up compressor");
2781 return (ARCHIVE_FATAL);
2783 return (ARCHIVE_OK);
2788 compression_init_encoder_bzip2(struct archive *a,
2789 struct la_zstream *lastrm, int level)
2792 (void) level; /* UNUSED */
2794 compression_end(a, lastrm);
2795 return (compression_unsupported_encoder(a, lastrm, "bzip2"));
2799 #if defined(HAVE_LZMA_H)
2801 compression_init_encoder_lzma(struct archive *a,
2802 struct la_zstream *lastrm, int level)
2804 static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
2806 lzma_options_lzma lzma_opt;
2810 compression_end(a, lastrm);
2811 if (lzma_lzma_preset(&lzma_opt, level)) {
2812 lastrm->real_stream = NULL;
2813 archive_set_error(a, ENOMEM,
2814 "Internal error initializing compression library");
2815 return (ARCHIVE_FATAL);
2817 strm = calloc(1, sizeof(*strm));
2819 archive_set_error(a, ENOMEM,
2820 "Can't allocate memory for lzma stream");
2821 return (ARCHIVE_FATAL);
2823 *strm = lzma_init_data;
2824 r = lzma_alone_encoder(strm, &lzma_opt);
2827 lastrm->real_stream = strm;
2829 lastrm->code = compression_code_lzma;
2830 lastrm->end = compression_end_lzma;
2833 case LZMA_MEM_ERROR:
2835 lastrm->real_stream = NULL;
2836 archive_set_error(a, ENOMEM,
2837 "Internal error initializing compression library: "
2838 "Cannot allocate memory");
2843 lastrm->real_stream = NULL;
2844 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2845 "Internal error initializing compression library: "
2846 "It's a bug in liblzma");
2854 compression_init_encoder_xz(struct archive *a,
2855 struct la_zstream *lastrm, int level)
2857 static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
2859 lzma_filter *lzmafilters;
2860 lzma_options_lzma lzma_opt;
2864 compression_end(a, lastrm);
2865 strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2);
2867 archive_set_error(a, ENOMEM,
2868 "Can't allocate memory for xz stream");
2869 return (ARCHIVE_FATAL);
2871 lzmafilters = (lzma_filter *)(strm+1);
2874 if (lzma_lzma_preset(&lzma_opt, level)) {
2875 lastrm->real_stream = NULL;
2876 archive_set_error(a, ENOMEM,
2877 "Internal error initializing compression library");
2878 return (ARCHIVE_FATAL);
2880 lzmafilters[0].id = LZMA_FILTER_LZMA2;
2881 lzmafilters[0].options = &lzma_opt;
2882 lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
2884 *strm = lzma_init_data;
2885 r = lzma_stream_encoder(strm, lzmafilters, LZMA_CHECK_CRC64);
2888 lastrm->real_stream = strm;
2890 lastrm->code = compression_code_lzma;
2891 lastrm->end = compression_end_lzma;
2894 case LZMA_MEM_ERROR:
2896 lastrm->real_stream = NULL;
2897 archive_set_error(a, ENOMEM,
2898 "Internal error initializing compression library: "
2899 "Cannot allocate memory");
2904 lastrm->real_stream = NULL;
2905 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2906 "Internal error initializing compression library: "
2907 "It's a bug in liblzma");
2915 compression_code_lzma(struct archive *a,
2916 struct la_zstream *lastrm, enum la_zaction action)
2921 strm = (lzma_stream *)lastrm->real_stream;
2922 strm->next_in = lastrm->next_in;
2923 strm->avail_in = lastrm->avail_in;
2924 strm->total_in = lastrm->total_in;
2925 strm->next_out = lastrm->next_out;
2926 strm->avail_out = lastrm->avail_out;
2927 strm->total_out = lastrm->total_out;
2929 (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN);
2930 lastrm->next_in = strm->next_in;
2931 lastrm->avail_in = strm->avail_in;
2932 lastrm->total_in = strm->total_in;
2933 lastrm->next_out = strm->next_out;
2934 lastrm->avail_out = strm->avail_out;
2935 lastrm->total_out = strm->total_out;
2938 /* Non-finishing case */
2939 return (ARCHIVE_OK);
2940 case LZMA_STREAM_END:
2941 /* This return can only occur in finishing case. */
2942 return (ARCHIVE_EOF);
2943 case LZMA_MEMLIMIT_ERROR:
2944 archive_set_error(a, ENOMEM,
2945 "lzma compression error:"
2946 " %ju MiB would have been needed",
2947 (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1)
2949 return (ARCHIVE_FATAL);
2951 /* Any other return value indicates an error */
2952 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2953 "lzma compression failed:"
2954 " lzma_code() call returned status %d", r);
2955 return (ARCHIVE_FATAL);
2960 compression_end_lzma(struct archive *a, struct la_zstream *lastrm)
2964 (void)a; /* UNUSED */
2965 strm = (lzma_stream *)lastrm->real_stream;
2969 lastrm->real_stream = NULL;
2970 return (ARCHIVE_OK);
2974 compression_init_encoder_lzma(struct archive *a,
2975 struct la_zstream *lastrm, int level)
2978 (void) level; /* UNUSED */
2980 compression_end(a, lastrm);
2981 return (compression_unsupported_encoder(a, lastrm, "lzma"));
2984 compression_init_encoder_xz(struct archive *a,
2985 struct la_zstream *lastrm, int level)
2988 (void) level; /* UNUSED */
2990 compression_end(a, lastrm);
2991 return (compression_unsupported_encoder(a, lastrm, "xz"));
2996 xar_compression_init_encoder(struct archive_write *a)
3001 xar = (struct xar *)a->format_data;
3002 switch (xar->opt_compression) {
3004 r = compression_init_encoder_gzip(
3005 &(a->archive), &(xar->stream),
3006 xar->opt_compression_level, 1);
3009 r = compression_init_encoder_bzip2(
3010 &(a->archive), &(xar->stream),
3011 xar->opt_compression_level);
3014 r = compression_init_encoder_lzma(
3015 &(a->archive), &(xar->stream),
3016 xar->opt_compression_level);
3019 r = compression_init_encoder_xz(
3020 &(a->archive), &(xar->stream),
3021 xar->opt_compression_level);
3027 if (r == ARCHIVE_OK) {
3028 xar->stream.total_in = 0;
3029 xar->stream.next_out = xar->wbuff;
3030 xar->stream.avail_out = sizeof(xar->wbuff);
3031 xar->stream.total_out = 0;
3038 compression_code(struct archive *a, struct la_zstream *lastrm,
3039 enum la_zaction action)
3042 return (lastrm->code(a, lastrm, action));
3043 return (ARCHIVE_OK);
3047 compression_end(struct archive *a, struct la_zstream *lastrm)
3050 return (lastrm->end(a, lastrm));
3051 return (ARCHIVE_OK);
3056 save_xattrs(struct archive_write *a, struct file *file)
3061 struct heap_data *heap;
3065 xar = (struct xar *)a->format_data;
3066 count = archive_entry_xattr_reset(file->entry);
3068 return (ARCHIVE_OK);
3070 archive_entry_xattr_next(file->entry,
3071 &name, &value, &size);
3072 checksum_init(&(xar->a_sumwrk), xar->opt_sumalg);
3073 checksum_init(&(xar->e_sumwrk), xar->opt_sumalg);
3075 heap = calloc(1, sizeof(*heap));
3077 archive_set_error(&a->archive, ENOMEM,
3078 "Can't allocate memory for xattr");
3079 return (ARCHIVE_FATAL);
3081 heap->id = file->ea_idx++;
3082 heap->temp_offset = xar->temp_offset;
3083 heap->size = size;/* save a extracted size */
3084 heap->compression = xar->opt_compression;
3085 /* Get a extracted sumcheck value. */
3086 checksum_update(&(xar->e_sumwrk), value, size);
3087 checksum_final(&(xar->e_sumwrk), &(heap->e_sum));
3090 * Not compression to xattr is simple way.
3092 if (heap->compression == NONE) {
3093 checksum_update(&(xar->a_sumwrk), value, size);
3094 checksum_final(&(xar->a_sumwrk), &(heap->a_sum));
3095 if (write_to_temp(a, value, size)
3097 return (ARCHIVE_FATAL);
3098 heap->length = size;
3099 /* Add heap to the tail of file->xattr. */
3101 *file->xattr.last = heap;
3102 file->xattr.last = &(heap->next);
3108 * Init compression library.
3110 r = xar_compression_init_encoder(a);
3111 if (r != ARCHIVE_OK) {
3113 return (ARCHIVE_FATAL);
3116 xar->stream.next_in = (const unsigned char *)value;
3117 xar->stream.avail_in = size;
3119 r = compression_code(&(a->archive),
3120 &(xar->stream), ARCHIVE_Z_FINISH);
3121 if (r != ARCHIVE_OK && r != ARCHIVE_EOF) {
3123 return (ARCHIVE_FATAL);
3125 size = sizeof(xar->wbuff) - xar->stream.avail_out;
3126 checksum_update(&(xar->a_sumwrk),
3128 if (write_to_temp(a, xar->wbuff, size)
3130 return (ARCHIVE_FATAL);
3131 if (r == ARCHIVE_OK) {
3132 xar->stream.next_out = xar->wbuff;
3133 xar->stream.avail_out = sizeof(xar->wbuff);
3135 checksum_final(&(xar->a_sumwrk),
3137 heap->length = xar->stream.total_out;
3138 /* Add heap to the tail of file->xattr. */
3140 *file->xattr.last = heap;
3141 file->xattr.last = &(heap->next);
3145 /* Clean up compression library. */
3146 r = compression_end(&(a->archive), &(xar->stream));
3147 if (r != ARCHIVE_OK)
3148 return (ARCHIVE_FATAL);
3150 return (ARCHIVE_OK);
3154 getalgsize(enum sumalg sumalg)
3168 getalgname(enum sumalg sumalg)
3181 #endif /* Support xar format */