2 * Copyright (c) 2010-2011 Michihiro NAKAJIMA
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include "archive_platform.h"
27 __FBSDID("$FreeBSD$");
36 #if HAVE_LIBXML_XMLWRITER_H
37 #include <libxml/xmlwriter.h>
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 HEADER_MAGIC 0x78617221
101 #define HEADER_SIZE 28
102 #define HEADER_VERSION 1
112 #define MAX_SUM_SIZE 20
113 #define MD5_NAME "md5"
114 #define SHA1_NAME "sha1"
126 #ifdef ARCHIVE_HAS_MD5
127 archive_md5_ctx md5ctx;
129 #ifdef ARCHIVE_HAS_SHA1
130 archive_sha1_ctx sha1ctx;
143 const unsigned char *next_in;
147 unsigned char *next_out;
153 int (*code) (struct archive *a,
154 struct la_zstream *lastrm,
155 enum la_zaction action);
156 int (*end)(struct archive *a,
157 struct la_zstream *lastrm);
163 unsigned char val[MAX_SUM_SIZE];
168 struct heap_data *next;
169 uint64_t temp_offset;
170 uint64_t length; /* archived size. */
171 uint64_t size; /* extracted size. */
172 enum enctype compression;
173 struct chksumval a_sum; /* archived checksum. */
174 struct chksumval e_sum; /* extracted checksum. */
178 struct archive_rb_node rbnode;
181 struct archive_entry *entry;
183 struct archive_rb_tree rbtree;
187 /* For hardlinked files.
188 * Use only when archive_entry_nlink() > 1 */
189 struct file *hardlink_target;
190 struct file *parent; /* parent directory entry */
192 * To manage sub directory files.
193 * We use 'chnext' a menber of struct file to chain.
200 /* For making a directory tree. */
201 struct archive_string parentdir;
202 struct archive_string basename;
203 struct archive_string symlink;
207 struct heap_data *first;
208 struct heap_data **last;
210 struct heap_data data;
211 struct archive_string script;
218 struct archive_rb_node rbnode;
228 uint64_t temp_offset;
232 struct file *cur_dirent;
233 struct archive_string cur_dirstr;
234 struct file *cur_file;
235 uint64_t bytes_remaining;
236 struct archive_string tstr;
237 struct archive_string vstr;
239 enum sumalg opt_toc_sumalg;
240 enum sumalg opt_sumalg;
241 enum enctype opt_compression;
242 int opt_compression_level;
244 struct chksumwork a_sumwrk; /* archived checksum. */
245 struct chksumwork e_sumwrk; /* extracted checksum. */
246 struct la_zstream stream;
247 struct archive_string_conv *sconv;
249 * Compressed data buffer.
251 unsigned char wbuff[1024 * 64];
252 size_t wbuff_remaining;
254 struct heap_data toc;
256 * The list of all file entries is used to manage struct file
258 * We use 'next' a menber of struct file to chain.
265 * The list of hard-linked file entries.
266 * We use 'hlnext' a menber of struct file to chain.
268 struct archive_rb_tree hardlink_rbtree;
271 static int xar_options(struct archive_write *,
272 const char *, const char *);
273 static int xar_write_header(struct archive_write *,
274 struct archive_entry *);
275 static ssize_t xar_write_data(struct archive_write *,
276 const void *, size_t);
277 static int xar_finish_entry(struct archive_write *);
278 static int xar_close(struct archive_write *);
279 static int xar_free(struct archive_write *);
281 static struct file *file_new(struct archive_write *a, struct archive_entry *);
282 static void file_free(struct file *);
283 static struct file *file_create_virtual_dir(struct archive_write *a, struct xar *,
285 static int file_add_child_tail(struct file *, struct file *);
286 static struct file *file_find_child(struct file *, const char *);
287 static int file_gen_utility_names(struct archive_write *,
289 static int get_path_component(char *, int, const char *);
290 static int file_tree(struct archive_write *, struct file **);
291 static void file_register(struct xar *, struct file *);
292 static void file_init_register(struct xar *);
293 static void file_free_register(struct xar *);
294 static int file_register_hardlink(struct archive_write *,
296 static void file_connect_hardlink_files(struct xar *);
297 static void file_init_hardlinks(struct xar *);
298 static void file_free_hardlinks(struct xar *);
300 static void checksum_init(struct chksumwork *, enum sumalg);
301 static void checksum_update(struct chksumwork *, const void *, size_t);
302 static void checksum_final(struct chksumwork *, struct chksumval *);
303 static int compression_init_encoder_gzip(struct archive *,
304 struct la_zstream *, int, int);
305 static int compression_code_gzip(struct archive *,
306 struct la_zstream *, enum la_zaction);
307 static int compression_end_gzip(struct archive *, struct la_zstream *);
308 static int compression_init_encoder_bzip2(struct archive *,
309 struct la_zstream *, int);
310 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
311 static int compression_code_bzip2(struct archive *,
312 struct la_zstream *, enum la_zaction);
313 static int compression_end_bzip2(struct archive *, struct la_zstream *);
315 static int compression_init_encoder_lzma(struct archive *,
316 struct la_zstream *, int);
317 static int compression_init_encoder_xz(struct archive *,
318 struct la_zstream *, int);
319 #if defined(HAVE_LZMA_H)
320 static int compression_code_lzma(struct archive *,
321 struct la_zstream *, enum la_zaction);
322 static int compression_end_lzma(struct archive *, struct la_zstream *);
324 static int xar_compression_init_encoder(struct archive_write *);
325 static int compression_code(struct archive *,
326 struct la_zstream *, enum la_zaction);
327 static int compression_end(struct archive *,
328 struct la_zstream *);
329 static int save_xattrs(struct archive_write *, struct file *);
330 static int getalgsize(enum sumalg);
331 static const char *getalgname(enum sumalg);
334 archive_write_set_format_xar(struct archive *_a)
336 struct archive_write *a = (struct archive_write *)_a;
339 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
340 ARCHIVE_STATE_NEW, "archive_write_set_format_xar");
342 /* If another format was already registered, unregister it. */
343 if (a->format_free != NULL)
346 xar = calloc(1, sizeof(*xar));
348 archive_set_error(&a->archive, ENOMEM,
349 "Can't allocate xar data");
350 return (ARCHIVE_FATAL);
353 file_init_register(xar);
354 file_init_hardlinks(xar);
355 archive_string_init(&(xar->tstr));
356 archive_string_init(&(xar->vstr));
359 * Create the root directory.
361 xar->root = file_create_virtual_dir(a, xar, "");
362 if (xar->root == NULL) {
364 archive_set_error(&a->archive, ENOMEM,
365 "Can't allocate xar data");
366 return (ARCHIVE_FATAL);
368 xar->root->parent = xar->root;
369 file_register(xar, xar->root);
370 xar->cur_dirent = xar->root;
371 archive_string_init(&(xar->cur_dirstr));
372 archive_string_ensure(&(xar->cur_dirstr), 1);
373 xar->cur_dirstr.s[0] = 0;
378 /* Set default checksum type. */
379 xar->opt_toc_sumalg = CKSUM_SHA1;
380 xar->opt_sumalg = CKSUM_SHA1;
381 /* Set default compression type and level. */
382 xar->opt_compression = GZIP;
383 xar->opt_compression_level = 6;
385 a->format_data = xar;
387 a->format_name = "xar";
388 a->format_options = xar_options;
389 a->format_write_header = xar_write_header;
390 a->format_write_data = xar_write_data;
391 a->format_finish_entry = xar_finish_entry;
392 a->format_close = xar_close;
393 a->format_free = xar_free;
394 a->archive.archive_format = ARCHIVE_FORMAT_XAR;
395 a->archive.archive_format_name = "xar";
401 xar_options(struct archive_write *a, const char *key, const char *value)
405 xar = (struct xar *)a->format_data;
407 if (strcmp(key, "checksum") == 0) {
409 xar->opt_sumalg = CKSUM_NONE;
410 else if (strcmp(value, "sha1") == 0)
411 xar->opt_sumalg = CKSUM_SHA1;
412 else if (strcmp(value, "md5") == 0)
413 xar->opt_sumalg = CKSUM_MD5;
415 archive_set_error(&(a->archive),
417 "Unkonwn checksum name: `%s'",
419 return (ARCHIVE_FAILED);
423 if (strcmp(key, "compression") == 0) {
424 const char *name = NULL;
427 xar->opt_compression = NONE;
428 else if (strcmp(value, "gzip") == 0)
429 xar->opt_compression = GZIP;
430 else if (strcmp(value, "bzip2") == 0)
431 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
432 xar->opt_compression = BZIP2;
436 else if (strcmp(value, "lzma") == 0)
438 xar->opt_compression = LZMA;
442 else if (strcmp(value, "xz") == 0)
444 xar->opt_compression = XZ;
449 archive_set_error(&(a->archive),
451 "Unkonwn compression name: `%s'",
453 return (ARCHIVE_FAILED);
456 archive_set_error(&(a->archive),
458 "`%s' compression not supported "
461 return (ARCHIVE_FAILED);
465 if (strcmp(key, "compression-level") == 0) {
467 !(value[0] >= '0' && value[0] <= '9') ||
469 archive_set_error(&(a->archive),
471 "Illeagal value `%s'",
473 return (ARCHIVE_FAILED);
475 xar->opt_compression_level = value[0] - '0';
478 if (strcmp(key, "toc-checksum") == 0) {
480 xar->opt_toc_sumalg = CKSUM_NONE;
481 else if (strcmp(value, "sha1") == 0)
482 xar->opt_toc_sumalg = CKSUM_SHA1;
483 else if (strcmp(value, "md5") == 0)
484 xar->opt_toc_sumalg = CKSUM_MD5;
486 archive_set_error(&(a->archive),
488 "Unkonwn checksum name: `%s'",
490 return (ARCHIVE_FAILED);
495 return (ARCHIVE_FAILED);
499 xar_write_header(struct archive_write *a, struct archive_entry *entry)
503 struct archive_entry *file_entry;
506 xar = (struct xar *)a->format_data;
507 xar->cur_file = NULL;
508 xar->bytes_remaining = 0;
510 if (xar->sconv == NULL) {
511 xar->sconv = archive_string_conversion_to_charset(
512 &a->archive, "UTF-8", 1);
513 if (xar->sconv == NULL)
514 return (ARCHIVE_FATAL);
517 file = file_new(a, entry);
519 archive_set_error(&a->archive, ENOMEM,
520 "Can't allocate data");
521 return (ARCHIVE_FATAL);
523 r2 = file_gen_utility_names(a, file);
524 if (r2 < ARCHIVE_WARN)
528 * Ignore a path which looks like the top of directory name
529 * since we have already made the root directory of an Xar archive.
531 if (archive_strlen(&(file->parentdir)) == 0 &&
532 archive_strlen(&(file->basename)) == 0) {
537 /* Add entry into tree */
538 file_entry = file->entry;
539 r = file_tree(a, &file);
542 /* There is the same file in tree and
543 * the current file is older than the file in tree.
544 * So we don't need the current file data anymore. */
545 if (file->entry != file_entry)
548 file_register(xar, file);
550 /* A virtual file, which is a directory, does not have
551 * any contents and we won't store it into a archive
552 * file other than its name. */
557 * Prepare to save the contents of the file.
559 if (xar->temp_fd == -1) {
561 xar->temp_offset = 0;
562 xar->temp_fd = __archive_mktemp(NULL);
563 if (xar->temp_fd < 0) {
564 archive_set_error(&a->archive, errno,
565 "Couldn't create temporary file");
566 return (ARCHIVE_FATAL);
568 algsize = getalgsize(xar->opt_toc_sumalg);
570 if (lseek(xar->temp_fd, algsize, SEEK_SET) < 0) {
571 archive_set_error(&(a->archive), errno,
573 return (ARCHIVE_FATAL);
575 xar->temp_offset = algsize;
579 if (archive_entry_hardlink(file->entry) == NULL) {
580 r = save_xattrs(a, file);
582 return (ARCHIVE_FATAL);
585 /* Non regular files contents are unneeded to be saved to
586 * a temporary file. */
587 if (archive_entry_filetype(file->entry) != AE_IFREG)
591 * Set the current file to cur_file to read its contents.
593 xar->cur_file = file;
595 if (archive_entry_nlink(file->entry) > 1) {
596 r = file_register_hardlink(a, file);
599 if (archive_entry_hardlink(file->entry) != NULL) {
600 archive_entry_unset_size(file->entry);
605 /* Save a offset of current file in temporary file. */
606 file->data.temp_offset = xar->temp_offset;
607 file->data.size = archive_entry_size(file->entry);
608 file->data.compression = xar->opt_compression;
609 xar->bytes_remaining = archive_entry_size(file->entry);
610 checksum_init(&(xar->a_sumwrk), xar->opt_sumalg);
611 checksum_init(&(xar->e_sumwrk), xar->opt_sumalg);
612 r = xar_compression_init_encoder(a);
621 write_to_temp(struct archive_write *a, const void *buff, size_t s)
627 xar = (struct xar *)a->format_data;
628 p = (unsigned char *)buff;
630 ws = write(xar->temp_fd, p, s);
632 archive_set_error(&(a->archive), errno,
633 "fwrite function failed");
634 return (ARCHIVE_FATAL);
638 xar->temp_offset += ws;
644 xar_write_data(struct archive_write *a, const void *buff, size_t s)
651 xar = (struct xar *)a->format_data;
653 if (s > xar->bytes_remaining)
654 s = xar->bytes_remaining;
655 if (s == 0 || xar->cur_file == NULL)
657 if (xar->cur_file->data.compression == NONE) {
658 checksum_update(&(xar->e_sumwrk), buff, s);
659 checksum_update(&(xar->a_sumwrk), buff, s);
662 xar->stream.next_in = (const unsigned char *)buff;
663 xar->stream.avail_in = s;
664 if (xar->bytes_remaining > s)
667 run = ARCHIVE_Z_FINISH;
668 /* Compress file data. */
669 r = compression_code(&(a->archive), &(xar->stream), run);
670 if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
671 return (ARCHIVE_FATAL);
672 rsize = s - xar->stream.avail_in;
673 checksum_update(&(xar->e_sumwrk), buff, rsize);
674 size = sizeof(xar->wbuff) - xar->stream.avail_out;
675 checksum_update(&(xar->a_sumwrk), xar->wbuff, size);
677 #if !defined(_WIN32) || defined(__CYGWIN__)
678 if (xar->bytes_remaining ==
679 archive_entry_size(xar->cur_file->entry)) {
681 * Get the path of a shell script if so.
683 const unsigned char *b = (const unsigned char *)buff;
685 archive_string_empty(&(xar->cur_file->script));
686 if (rsize > 2 && b[0] == '#' && b[1] == '!') {
696 for (i = off; i < end && b[i] != '\0' &&
697 b[i] != '\n' && b[i] != '\r' &&
698 b[i] != ' ' && b[i] != '\t'; i++)
699 path[i - off] = b[i];
700 path[i - off] = '\0';
701 archive_strcpy(&(xar->cur_file->script), path);
706 if (xar->cur_file->data.compression == NONE) {
707 if (write_to_temp(a, buff, size) != ARCHIVE_OK)
708 return (ARCHIVE_FATAL);
710 if (write_to_temp(a, xar->wbuff, size) != ARCHIVE_OK)
711 return (ARCHIVE_FATAL);
713 xar->bytes_remaining -= rsize;
714 xar->cur_file->data.length += size;
720 xar_finish_entry(struct archive_write *a)
727 xar = (struct xar *)a->format_data;
728 if (xar->cur_file == NULL)
731 while (xar->bytes_remaining > 0) {
732 s = xar->bytes_remaining;
733 if (s > a->null_length)
735 w = xar_write_data(a, a->nulls, s);
737 xar->bytes_remaining -= w;
741 file = xar->cur_file;
742 checksum_final(&(xar->e_sumwrk), &(file->data.e_sum));
743 checksum_final(&(xar->a_sumwrk), &(file->data.a_sum));
744 xar->cur_file = NULL;
750 xmlwrite_string_attr(struct archive_write *a, xmlTextWriterPtr writer,
751 const char *key, const char *value,
752 const char *attrkey, const char *attrvalue)
756 r = xmlTextWriterStartElement(writer, BAD_CAST(key));
758 archive_set_error(&a->archive,
760 "xmlTextWriterStartElement() failed: %d", r);
761 return (ARCHIVE_FATAL);
763 if (attrkey != NULL && attrvalue != NULL) {
764 r = xmlTextWriterWriteAttribute(writer,
765 BAD_CAST(attrkey), BAD_CAST(attrvalue));
767 archive_set_error(&a->archive,
769 "xmlTextWriterWriteAttribute() failed: %d", r);
770 return (ARCHIVE_FATAL);
774 r = xmlTextWriterWriteString(writer, BAD_CAST(value));
776 archive_set_error(&a->archive,
778 "xmlTextWriterWriteString() failed: %d", r);
779 return (ARCHIVE_FATAL);
782 r = xmlTextWriterEndElement(writer);
784 archive_set_error(&a->archive,
786 "xmlTextWriterEndElement() failed: %d", r);
787 return (ARCHIVE_FATAL);
793 xmlwrite_string(struct archive_write *a, xmlTextWriterPtr writer,
794 const char *key, const char *value)
801 r = xmlTextWriterStartElement(writer, BAD_CAST(key));
803 archive_set_error(&a->archive,
805 "xmlTextWriterStartElement() failed: %d", r);
806 return (ARCHIVE_FATAL);
809 r = xmlTextWriterWriteString(writer, BAD_CAST(value));
811 archive_set_error(&a->archive,
813 "xmlTextWriterWriteString() failed: %d", r);
814 return (ARCHIVE_FATAL);
817 r = xmlTextWriterEndElement(writer);
819 archive_set_error(&a->archive,
821 "xmlTextWriterEndElement() failed: %d", r);
822 return (ARCHIVE_FATAL);
828 xmlwrite_fstring(struct archive_write *a, xmlTextWriterPtr writer,
829 const char *key, const char *fmt, ...)
834 xar = (struct xar *)a->format_data;
836 archive_string_empty(&xar->vstr);
837 archive_string_vsprintf(&xar->vstr, fmt, ap);
839 return (xmlwrite_string(a, writer, key, xar->vstr.s));
843 xmlwrite_time(struct archive_write *a, xmlTextWriterPtr writer,
844 const char *key, time_t t, int z)
849 #if defined(HAVE_GMTIME_R)
851 #elif defined(HAVE__GMTIME64_S)
852 _gmtime64_s(&tm, &t);
854 memcpy(&tm, gmtime(&t), sizeof(tm));
856 memset(×tr, 0, sizeof(timestr));
857 /* Do not use %F and %T for portability. */
858 strftime(timestr, sizeof(timestr), "%Y-%m-%dT%H:%M:%S", &tm);
860 strcat(timestr, "Z");
861 return (xmlwrite_string(a, writer, key, timestr));
865 xmlwrite_mode(struct archive_write *a, xmlTextWriterPtr writer,
866 const char *key, mode_t mode)
871 ms[1] = '0' + ((mode >> 6) & 07);
872 ms[2] = '0' + ((mode >> 3) & 07);
873 ms[3] = '0' + (mode & 07);
876 return (xmlwrite_string(a, writer, key, ms));
880 xmlwrite_sum(struct archive_write *a, xmlTextWriterPtr writer,
881 const char *key, struct chksumval *sum)
885 char buff[MAX_SUM_SIZE*2 + 1];
891 algname = getalgname(sum->alg);
892 algsize = getalgsize(sum->alg);
893 if (algname != NULL) {
894 const char *hex = "0123456789abcdef";
897 for (i = 0; i < algsize; i++) {
898 *p++ = hex[(*s >> 4)];
899 *p++ = hex[(*s & 0x0f)];
903 r = xmlwrite_string_attr(a, writer,
907 return (ARCHIVE_FATAL);
914 xmlwrite_heap(struct archive_write *a, xmlTextWriterPtr writer,
915 struct heap_data *heap)
920 r = xmlwrite_fstring(a, writer, "length", "%ju", heap->length);
922 return (ARCHIVE_FATAL);
923 r = xmlwrite_fstring(a, writer, "offset", "%ju", heap->temp_offset);
925 return (ARCHIVE_FATAL);
926 r = xmlwrite_fstring(a, writer, "size", "%ju", heap->size);
928 return (ARCHIVE_FATAL);
929 switch (heap->compression) {
931 encname = "application/x-gzip"; break;
933 encname = "application/x-bzip2"; break;
935 encname = "application/x-lzma"; break;
937 encname = "application/x-xz"; break;
939 encname = "application/octet-stream"; break;
941 r = xmlwrite_string_attr(a, writer, "encoding", NULL,
944 return (ARCHIVE_FATAL);
945 r = xmlwrite_sum(a, writer, "archived-checksum", &(heap->a_sum));
947 return (ARCHIVE_FATAL);
948 r = xmlwrite_sum(a, writer, "extracted-checksum", &(heap->e_sum));
950 return (ARCHIVE_FATAL);
955 * xar utility records fflags as following xml elements:
965 * If xar is running on BSD platform, records <flags>..</flags>;
966 * if xar is running on linux platform, records <ext2>..</ext2>;
967 * otherwise does not record.
969 * Our implements records both <flags> and <ext2> if it's necessary.
972 make_fflags_entry(struct archive_write *a, xmlTextWriterPtr writer,
973 const char *element, const char *fflags_text)
975 static const struct flagentry {
980 { "sappnd", "SystemAppend"},
981 { "sappend", "SystemAppend"},
982 { "arch", "SystemArchived"},
983 { "archived", "SystemArchived"},
984 { "schg", "SystemImmutable"},
985 { "schange", "SystemImmutable"},
986 { "simmutable", "SystemImmutable"},
987 { "nosunlnk", "SystemNoUnlink"},
988 { "nosunlink", "SystemNoUnlink"},
989 { "snapshot", "SystemSnapshot"},
990 { "uappnd", "UserAppend"},
991 { "uappend", "UserAppend"},
992 { "uchg", "UserImmutable"},
993 { "uchange", "UserImmutable"},
994 { "uimmutable", "UserImmutable"},
995 { "nodump", "UserNoDump"},
996 { "noopaque", "UserOpaque"},
997 { "nouunlnk", "UserNoUnlink"},
998 { "nouunlink", "UserNoUnlink"},
1002 { "sappnd", "AppendOnly"},
1003 { "sappend", "AppendOnly"},
1004 { "schg", "Immutable"},
1005 { "schange", "Immutable"},
1006 { "simmutable", "Immutable"},
1007 { "nodump", "NoDump"},
1008 { "nouunlnk", "Undelete"},
1009 { "nouunlink", "Undelete"},
1010 { "btree", "BTree"},
1011 { "comperr", "CompError"},
1012 { "compress", "Compress"},
1013 { "noatime", "NoAtime"},
1014 { "compdirty", "CompDirty"},
1015 { "comprblk", "CompBlock"},
1016 { "dirsync", "DirSync"},
1017 { "hashidx", "HashIndexed"},
1018 { "imagic", "iMagic"},
1019 { "journal", "Journaled"},
1020 { "securedeletion", "SecureDeletion"},
1021 { "sync", "Synchronous"},
1022 { "notail", "NoTail"},
1023 { "topdir", "TopDir"},
1024 { "reserved", "Reserved"},
1027 const struct flagentry *fe, *flagentry;
1028 #define FLAGENTRY_MAXSIZE ((sizeof(flagbsd)+sizeof(flagext2))/sizeof(flagbsd))
1029 const struct flagentry *avail[FLAGENTRY_MAXSIZE];
1033 if (strcmp(element, "ext2") == 0)
1034 flagentry = flagext2;
1036 flagentry = flagbsd;
1042 cp = strchr(p, ',');
1046 for (fe = flagentry; fe->name != NULL; fe++) {
1047 if (fe->name[cp - p] != '\0'
1048 || p[0] != fe->name[0])
1050 if (strncmp(p, fe->name, cp - p) == 0) {
1059 } while (p != NULL);
1062 r = xmlTextWriterStartElement(writer, BAD_CAST(element));
1064 archive_set_error(&a->archive,
1066 "xmlTextWriterStartElement() failed: %d", r);
1067 return (ARCHIVE_FATAL);
1069 for (i = 0; i < n; i++) {
1070 r = xmlwrite_string(a, writer,
1071 avail[i]->xarname, NULL);
1072 if (r != ARCHIVE_OK)
1076 r = xmlTextWriterEndElement(writer);
1078 archive_set_error(&a->archive,
1080 "xmlTextWriterEndElement() failed: %d", r);
1081 return (ARCHIVE_FATAL);
1084 return (ARCHIVE_OK);
1088 make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
1092 const char *filetype, *filelink, *fflags;
1093 struct archive_string linkto;
1094 struct heap_data *heap;
1100 xar = (struct xar *)a->format_data;
1104 * Make a file name entry, "<name>".
1106 l = ll = archive_strlen(&(file->basename));
1109 archive_set_error(&a->archive, ENOMEM,
1110 "Can't allocate memory");
1111 return (ARCHIVE_FATAL);
1113 r = UTF8Toisolat1(tmp, &l, BAD_CAST(file->basename.s), &ll);
1116 r = xmlTextWriterStartElement(writer, BAD_CAST("name"));
1118 archive_set_error(&a->archive,
1120 "xmlTextWriterStartElement() failed: %d", r);
1121 return (ARCHIVE_FATAL);
1123 r = xmlTextWriterWriteAttribute(writer,
1124 BAD_CAST("enctype"), BAD_CAST("base64"));
1126 archive_set_error(&a->archive,
1128 "xmlTextWriterWriteAttribute() failed: %d", r);
1129 return (ARCHIVE_FATAL);
1131 r = xmlTextWriterWriteBase64(writer, file->basename.s,
1132 0, archive_strlen(&(file->basename)));
1134 archive_set_error(&a->archive,
1136 "xmlTextWriterWriteBase64() failed: %d", r);
1137 return (ARCHIVE_FATAL);
1139 r = xmlTextWriterEndElement(writer);
1141 archive_set_error(&a->archive,
1143 "xmlTextWriterEndElement() failed: %d", r);
1144 return (ARCHIVE_FATAL);
1147 r = xmlwrite_string(a, writer, "name", file->basename.s);
1149 return (ARCHIVE_FATAL);
1153 * Make a file type entry, "<type>".
1156 archive_string_init(&linkto);
1157 switch (archive_entry_filetype(file->entry)) {
1159 filetype = "directory"; break;
1161 filetype = "symlink"; break;
1163 filetype = "character special"; break;
1165 filetype = "block special"; break;
1167 filetype = "socket"; break;
1169 filetype = "fifo"; break;
1172 if (file->hardlink_target != NULL) {
1173 filetype = "hardlink";
1175 if (file->hardlink_target == file)
1176 archive_strcpy(&linkto, "original");
1178 archive_string_sprintf(&linkto, "%d",
1179 file->hardlink_target->id);
1184 r = xmlwrite_string_attr(a, writer, "type", filetype,
1185 filelink, linkto.s);
1186 archive_string_free(&linkto);
1188 return (ARCHIVE_FATAL);
1191 * On a virtual directory, we record "name" and "type" only.
1194 return (ARCHIVE_OK);
1196 switch (archive_entry_filetype(file->entry)) {
1199 * xar utility has checked a file type, which
1200 * a symblic-link file has referenced.
1202 * <link type="directory">../ref/</link>
1203 * The symlink target file is "../ref/" and its
1204 * file type is a directory.
1206 * <link type="file">../f</link>
1207 * The symlink target file is "../f" and its
1208 * file type is a regular file.
1210 * But our implemention cannot do it, and then we
1211 * always record that a attribute "type" is "borken",
1213 * <link type="broken">foo/bar</link>
1214 * It means "foo/bar" is not reachable.
1216 r = xmlwrite_string_attr(a, writer, "link",
1220 return (ARCHIVE_FATAL);
1224 r = xmlTextWriterStartElement(writer, BAD_CAST("device"));
1226 archive_set_error(&a->archive,
1228 "xmlTextWriterStartElement() failed: %d", r);
1229 return (ARCHIVE_FATAL);
1231 r = xmlwrite_fstring(a, writer, "major",
1232 "%d", archive_entry_rdevmajor(file->entry));
1234 return (ARCHIVE_FATAL);
1235 r = xmlwrite_fstring(a, writer, "minor",
1236 "%d", archive_entry_rdevminor(file->entry));
1238 return (ARCHIVE_FATAL);
1239 r = xmlTextWriterEndElement(writer);
1241 archive_set_error(&a->archive,
1243 "xmlTextWriterEndElement() failed: %d", r);
1244 return (ARCHIVE_FATAL);
1252 * Make a inode entry, "<inode>".
1254 r = xmlwrite_fstring(a, writer, "inode",
1255 "%jd", archive_entry_ino64(file->entry));
1257 return (ARCHIVE_FATAL);
1258 if (archive_entry_dev(file->entry) != 0) {
1259 r = xmlwrite_fstring(a, writer, "deviceno",
1260 "%d", archive_entry_dev(file->entry));
1262 return (ARCHIVE_FATAL);
1266 * Make a file mode entry, "<mode>".
1268 r = xmlwrite_mode(a, writer, "mode",
1269 archive_entry_mode(file->entry));
1271 return (ARCHIVE_FATAL);
1274 * Make a user entry, "<uid>" and "<user>.
1276 r = xmlwrite_fstring(a, writer, "uid",
1277 "%d", archive_entry_uid(file->entry));
1279 return (ARCHIVE_FATAL);
1280 r = archive_entry_uname_l(file->entry, &p, &len, xar->sconv);
1282 if (errno == ENOMEM) {
1283 archive_set_error(&a->archive, ENOMEM,
1284 "Can't allocate memory for Uname");
1285 return (ARCHIVE_FATAL);
1287 archive_set_error(&a->archive,
1288 ARCHIVE_ERRNO_FILE_FORMAT,
1289 "Can't translate uname '%s' to UTF-8",
1290 archive_entry_uname(file->entry));
1294 r = xmlwrite_string(a, writer, "user", p);
1296 return (ARCHIVE_FATAL);
1300 * Make a group entry, "<gid>" and "<group>.
1302 r = xmlwrite_fstring(a, writer, "gid",
1303 "%d", archive_entry_gid(file->entry));
1305 return (ARCHIVE_FATAL);
1306 r = archive_entry_gname_l(file->entry, &p, &len, xar->sconv);
1308 if (errno == ENOMEM) {
1309 archive_set_error(&a->archive, ENOMEM,
1310 "Can't allocate memory for Gname");
1311 return (ARCHIVE_FATAL);
1313 archive_set_error(&a->archive,
1314 ARCHIVE_ERRNO_FILE_FORMAT,
1315 "Can't translate gname '%s' to UTF-8",
1316 archive_entry_gname(file->entry));
1320 r = xmlwrite_string(a, writer, "group", p);
1322 return (ARCHIVE_FATAL);
1326 * Make a ctime entry, "<ctime>".
1328 if (archive_entry_ctime_is_set(file->entry)) {
1329 r = xmlwrite_time(a, writer, "ctime",
1330 archive_entry_ctime(file->entry), 1);
1332 return (ARCHIVE_FATAL);
1336 * Make a mtime entry, "<mtime>".
1338 if (archive_entry_mtime_is_set(file->entry)) {
1339 r = xmlwrite_time(a, writer, "mtime",
1340 archive_entry_mtime(file->entry), 1);
1342 return (ARCHIVE_FATAL);
1346 * Make a atime entry, "<atime>".
1348 if (archive_entry_atime_is_set(file->entry)) {
1349 r = xmlwrite_time(a, writer, "atime",
1350 archive_entry_atime(file->entry), 1);
1352 return (ARCHIVE_FATAL);
1356 * Make fflags entries, "<flags>" and "<ext2>".
1358 fflags = archive_entry_fflags_text(file->entry);
1359 if (fflags != NULL) {
1360 r = make_fflags_entry(a, writer, "flags", fflags);
1363 r = make_fflags_entry(a, writer, "ext2", fflags);
1369 * Make extended attribute entries, "<ea>".
1371 archive_entry_xattr_reset(file->entry);
1372 for (heap = file->xattr.first; heap != NULL; heap = heap->next) {
1377 archive_entry_xattr_next(file->entry,
1378 &name, &value, &size);
1379 r = xmlTextWriterStartElement(writer, BAD_CAST("ea"));
1381 archive_set_error(&a->archive,
1383 "xmlTextWriterStartElement() failed: %d", r);
1384 return (ARCHIVE_FATAL);
1386 r = xmlTextWriterWriteFormatAttribute(writer,
1387 BAD_CAST("id"), "%d", heap->id);
1389 archive_set_error(&a->archive,
1391 "xmlTextWriterWriteAttribute() failed: %d", r);
1392 return (ARCHIVE_FATAL);
1394 r = xmlwrite_heap(a, writer, heap);
1396 return (ARCHIVE_FATAL);
1397 r = xmlwrite_string(a, writer, "name", name);
1399 return (ARCHIVE_FATAL);
1401 r = xmlTextWriterEndElement(writer);
1403 archive_set_error(&a->archive,
1405 "xmlTextWriterEndElement() failed: %d", r);
1406 return (ARCHIVE_FATAL);
1411 * Make a file data entry, "<data>".
1413 if (file->data.length > 0) {
1414 r = xmlTextWriterStartElement(writer, BAD_CAST("data"));
1416 archive_set_error(&a->archive,
1418 "xmlTextWriterStartElement() failed: %d", r);
1419 return (ARCHIVE_FATAL);
1422 r = xmlwrite_heap(a, writer, &(file->data));
1424 return (ARCHIVE_FATAL);
1426 r = xmlTextWriterEndElement(writer);
1428 archive_set_error(&a->archive,
1430 "xmlTextWriterEndElement() failed: %d", r);
1431 return (ARCHIVE_FATAL);
1435 if (archive_strlen(&file->script) > 0) {
1436 r = xmlTextWriterStartElement(writer, BAD_CAST("content"));
1438 archive_set_error(&a->archive,
1440 "xmlTextWriterStartElement() failed: %d", r);
1441 return (ARCHIVE_FATAL);
1444 r = xmlwrite_string(a, writer,
1445 "interpreter", file->script.s);
1447 return (ARCHIVE_FATAL);
1449 r = xmlwrite_string(a, writer, "type", "script");
1451 return (ARCHIVE_FATAL);
1453 r = xmlTextWriterEndElement(writer);
1455 archive_set_error(&a->archive,
1457 "xmlTextWriterEndElement() failed: %d", r);
1458 return (ARCHIVE_FATAL);
1469 make_toc(struct archive_write *a)
1474 xmlTextWriterPtr writer;
1478 xar = (struct xar *)a->format_data;
1480 ret = ARCHIVE_FATAL;
1483 * Initialize xml writer.
1486 bp = xmlBufferCreate();
1488 archive_set_error(&a->archive, ENOMEM,
1489 "xmlBufferCreate() "
1490 "couldn't create xml buffer");
1493 writer = xmlNewTextWriterMemory(bp, 0);
1494 if (writer == NULL) {
1495 archive_set_error(&a->archive,
1497 "xmlNewTextWriterMemory() "
1498 "couldn't create xml writer");
1501 r = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL);
1503 archive_set_error(&a->archive,
1505 "xmlTextWriterStartDocument() failed: %d", r);
1508 r = xmlTextWriterSetIndent(writer, 4);
1510 archive_set_error(&a->archive,
1512 "xmlTextWriterSetIndent() failed: %d", r);
1517 * Start recoding TOC
1519 r = xmlTextWriterStartElement(writer, BAD_CAST("xar"));
1521 archive_set_error(&a->archive,
1523 "xmlTextWriterStartElement() failed: %d", r);
1526 r = xmlTextWriterStartElement(writer, BAD_CAST("toc"));
1528 archive_set_error(&a->archive,
1530 "xmlTextWriterStartDocument() failed: %d", r);
1535 * Record the creation time of the archive file.
1537 r = xmlwrite_time(a, writer, "creation-time", time(NULL), 0);
1542 * Record the checksum value of TOC
1544 algsize = getalgsize(xar->opt_toc_sumalg);
1547 * Record TOC checksum
1549 r = xmlTextWriterStartElement(writer, BAD_CAST("checksum"));
1551 archive_set_error(&a->archive,
1553 "xmlTextWriterStartElement() failed: %d", r);
1556 r = xmlTextWriterWriteAttribute(writer, BAD_CAST("style"),
1557 BAD_CAST(getalgname(xar->opt_toc_sumalg)));
1559 archive_set_error(&a->archive,
1561 "xmlTextWriterWriteAttribute() failed: %d", r);
1566 * Record the offset of the value of checksum of TOC
1568 r = xmlwrite_string(a, writer, "offset", "0");
1573 * Record the size of the value of checksum of TOC
1575 r = xmlwrite_fstring(a, writer, "size", "%d", algsize);
1579 r = xmlTextWriterEndElement(writer);
1581 archive_set_error(&a->archive,
1583 "xmlTextWriterEndElement() failed: %d", r);
1590 if (np != np->parent) {
1591 r = make_file_entry(a, writer, np);
1592 if (r != ARCHIVE_OK)
1596 if (np->dir && np->children.first != NULL) {
1597 /* Enter to sub directories. */
1598 np = np->children.first;
1599 r = xmlTextWriterStartElement(writer,
1602 archive_set_error(&a->archive,
1604 "xmlTextWriterStartElement() "
1608 r = xmlTextWriterWriteFormatAttribute(
1609 writer, BAD_CAST("id"), "%d", np->id);
1611 archive_set_error(&a->archive,
1613 "xmlTextWriterWriteAttribute() "
1619 while (np != np->parent) {
1620 r = xmlTextWriterEndElement(writer);
1622 archive_set_error(&a->archive,
1624 "xmlTextWriterEndElement() "
1628 if (np->chnext == NULL) {
1629 /* Return to the parent directory. */
1633 r = xmlTextWriterStartElement(writer,
1636 archive_set_error(&a->archive,
1638 "xmlTextWriterStartElement() "
1642 r = xmlTextWriterWriteFormatAttribute(
1643 writer, BAD_CAST("id"), "%d", np->id);
1645 archive_set_error(&a->archive,
1647 "xmlTextWriterWriteAttribute() "
1654 } while (np != np->parent);
1656 r = xmlTextWriterEndDocument(writer);
1658 archive_set_error(&a->archive,
1660 "xmlTextWriterEndDocument() failed: %d", r);
1664 fprintf(stderr, "\n---TOC-- %d bytes --\n%s\n",
1665 strlen((const char *)bp->content), bp->content);
1669 * Compress the TOC and calculate the sum of the TOC.
1671 xar->toc.temp_offset = xar->temp_offset;
1672 xar->toc.size = bp->use;
1673 checksum_init(&(xar->a_sumwrk), xar->opt_toc_sumalg);
1675 r = compression_init_encoder_gzip(&(a->archive),
1676 &(xar->stream), 6, 1);
1677 if (r != ARCHIVE_OK)
1679 xar->stream.next_in = bp->content;
1680 xar->stream.avail_in = bp->use;
1681 xar->stream.total_in = 0;
1682 xar->stream.next_out = xar->wbuff;
1683 xar->stream.avail_out = sizeof(xar->wbuff);
1684 xar->stream.total_out = 0;
1688 r = compression_code(&(a->archive),
1689 &(xar->stream), ARCHIVE_Z_FINISH);
1690 if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
1692 size = sizeof(xar->wbuff) - xar->stream.avail_out;
1693 checksum_update(&(xar->a_sumwrk), xar->wbuff, size);
1694 if (write_to_temp(a, xar->wbuff, size) != ARCHIVE_OK)
1696 if (r == ARCHIVE_EOF)
1698 xar->stream.next_out = xar->wbuff;
1699 xar->stream.avail_out = sizeof(xar->wbuff);
1701 r = compression_end(&(a->archive), &(xar->stream));
1702 if (r != ARCHIVE_OK)
1704 xar->toc.length = xar->stream.total_out;
1705 xar->toc.compression = GZIP;
1706 checksum_final(&(xar->a_sumwrk), &(xar->toc.a_sum));
1711 xmlFreeTextWriter(writer);
1719 flush_wbuff(struct archive_write *a)
1725 xar = (struct xar *)a->format_data;
1726 s = sizeof(xar->wbuff) - xar->wbuff_remaining;
1727 r = __archive_write_output(a, xar->wbuff, s);
1728 if (r != ARCHIVE_OK)
1730 xar->wbuff_remaining = sizeof(xar->wbuff);
1735 copy_out(struct archive_write *a, uint64_t offset, uint64_t length)
1740 xar = (struct xar *)a->format_data;
1741 if (lseek(xar->temp_fd, offset, SEEK_SET) < 0) {
1742 archive_set_error(&(a->archive), errno, "lseek failed");
1743 return (ARCHIVE_FATAL);
1750 if (length > xar->wbuff_remaining)
1751 rsize = xar->wbuff_remaining;
1753 rsize = (size_t)length;
1754 wb = xar->wbuff + (sizeof(xar->wbuff) - xar->wbuff_remaining);
1755 rs = read(xar->temp_fd, wb, rsize);
1757 archive_set_error(&(a->archive), errno,
1758 "Can't read temporary file(%jd)",
1760 return (ARCHIVE_FATAL);
1763 archive_set_error(&(a->archive), 0,
1764 "Truncated xar archive");
1765 return (ARCHIVE_FATAL);
1767 xar->wbuff_remaining -= rs;
1769 if (xar->wbuff_remaining == 0) {
1771 if (r != ARCHIVE_OK)
1775 return (ARCHIVE_OK);
1779 xar_close(struct archive_write *a)
1786 xar = (struct xar *)a->format_data;
1789 if (xar->root->children.first == NULL)
1790 return (ARCHIVE_OK);
1792 /* Save the length of all file extended attributes and contents. */
1793 length = xar->temp_offset;
1795 /* Connect hardlinked files */
1796 file_connect_hardlink_files(xar);
1800 if (r != ARCHIVE_OK)
1803 * Make the xar header on wbuff(write buffer).
1806 xar->wbuff_remaining = sizeof(xar->wbuff);
1807 archive_be32enc(&wb[0], HEADER_MAGIC);
1808 archive_be16enc(&wb[4], HEADER_SIZE);
1809 archive_be16enc(&wb[6], HEADER_VERSION);
1810 archive_be64enc(&wb[8], xar->toc.length);
1811 archive_be64enc(&wb[16], xar->toc.size);
1812 archive_be32enc(&wb[24], xar->toc.a_sum.alg);
1813 xar->wbuff_remaining -= HEADER_SIZE;
1818 r = copy_out(a, xar->toc.temp_offset, xar->toc.length);
1819 if (r != ARCHIVE_OK)
1822 /* Write the checksum value of the TOC. */
1823 if (xar->toc.a_sum.len) {
1824 if (xar->wbuff_remaining < xar->toc.a_sum.len) {
1826 if (r != ARCHIVE_OK)
1829 wb = xar->wbuff + (sizeof(xar->wbuff) - xar->wbuff_remaining);
1830 memcpy(wb, xar->toc.a_sum.val, xar->toc.a_sum.len);
1831 xar->wbuff_remaining -= xar->toc.a_sum.len;
1835 * Write all file extended attributes and contents.
1837 r = copy_out(a, xar->toc.a_sum.len, length);
1838 if (r != ARCHIVE_OK)
1845 xar_free(struct archive_write *a)
1849 xar = (struct xar *)a->format_data;
1850 archive_string_free(&(xar->cur_dirstr));
1851 archive_string_free(&(xar->tstr));
1852 archive_string_free(&(xar->vstr));
1853 file_free_hardlinks(xar);
1854 file_free_register(xar);
1855 compression_end(&(a->archive), &(xar->stream));
1858 return (ARCHIVE_OK);
1862 file_cmp_node(const struct archive_rb_node *n1,
1863 const struct archive_rb_node *n2)
1865 struct file *f1 = (struct file *)n1;
1866 struct file *f2 = (struct file *)n2;
1868 return (strcmp(f1->basename.s, f2->basename.s));
1872 file_cmp_key(const struct archive_rb_node *n, const void *key)
1874 struct file *f = (struct file *)n;
1876 return (strcmp(f->basename.s, (const char *)key));
1879 static struct file *
1880 file_new(struct archive_write *a, struct archive_entry *entry)
1883 static const struct archive_rb_tree_ops rb_ops = {
1884 file_cmp_node, file_cmp_key
1887 file = calloc(1, sizeof(*file));
1892 file->entry = archive_entry_clone(entry);
1894 file->entry = archive_entry_new2(&a->archive);
1895 if (file->entry == NULL) {
1899 __archive_rb_tree_init(&(file->rbtree), &rb_ops);
1900 file->children.first = NULL;
1901 file->children.last = &(file->children.first);
1902 file->xattr.first = NULL;
1903 file->xattr.last = &(file->xattr.first);
1904 archive_string_init(&(file->parentdir));
1905 archive_string_init(&(file->basename));
1906 archive_string_init(&(file->symlink));
1907 archive_string_init(&(file->script));
1908 if (entry != NULL && archive_entry_filetype(entry) == AE_IFDIR)
1915 file_free(struct file *file)
1917 struct heap_data *heap, *next_heap;
1919 heap = file->xattr.first;
1920 while (heap != NULL) {
1921 next_heap = heap->next;
1925 archive_string_free(&(file->parentdir));
1926 archive_string_free(&(file->basename));
1927 archive_string_free(&(file->symlink));
1928 archive_string_free(&(file->script));
1932 static struct file *
1933 file_create_virtual_dir(struct archive_write *a, struct xar *xar,
1934 const char *pathname)
1938 file = file_new(a, NULL);
1941 archive_entry_set_pathname(file->entry, pathname);
1942 archive_entry_set_mode(file->entry, 0555 | AE_IFDIR);
1951 file_add_child_tail(struct file *parent, struct file *child)
1953 if (!__archive_rb_tree_insert_node(
1954 &(parent->rbtree), (struct archive_rb_node *)child))
1956 child->chnext = NULL;
1957 *parent->children.last = child;
1958 parent->children.last = &(child->chnext);
1959 child->parent = parent;
1964 * Find a entry from `parent'
1966 static struct file *
1967 file_find_child(struct file *parent, const char *child_name)
1971 np = (struct file *)__archive_rb_tree_find_node(
1972 &(parent->rbtree), child_name);
1976 #if defined(_WIN32) || defined(__CYGWIN__)
1978 cleanup_backslash(char *utf8, size_t len)
1981 /* Convert a path-separator from '\' to '/' */
1982 while (*utf8 != '\0' && len) {
1990 #define cleanup_backslash(p, len) /* nop */
1994 * Generate a parent directory name and a base name from a pathname.
1997 file_gen_utility_names(struct archive_write *a, struct file *file)
2001 char *p, *dirname, *slash;
2005 xar = (struct xar *)a->format_data;
2006 archive_string_empty(&(file->parentdir));
2007 archive_string_empty(&(file->basename));
2008 archive_string_empty(&(file->symlink));
2010 if (file->parent == file)/* virtual root */
2011 return (ARCHIVE_OK);
2013 if (archive_entry_pathname_l(file->entry, &pp, &len, xar->sconv)
2015 if (errno == ENOMEM) {
2016 archive_set_error(&a->archive, ENOMEM,
2017 "Can't allocate memory for Pathname");
2018 return (ARCHIVE_FATAL);
2020 archive_set_error(&a->archive,
2021 ARCHIVE_ERRNO_FILE_FORMAT,
2022 "Can't translate pathname '%s' to UTF-8",
2023 archive_entry_pathname(file->entry));
2026 archive_strncpy(&(file->parentdir), pp, len);
2027 len = file->parentdir.length;
2028 p = dirname = file->parentdir.s;
2030 * Convert a path-separator from '\' to '/'
2032 cleanup_backslash(p, len);
2035 * Remove leading '/', '../' and './' elements
2041 } else if (p[0] != '.')
2043 else if (p[1] == '.' && p[2] == '/') {
2046 } else if (p[1] == '/' || (p[1] == '.' && p[2] == '\0')) {
2049 } else if (p[1] == '\0') {
2056 memmove(dirname, p, len+1);
2060 * Remove "/","/." and "/.." elements from tail.
2065 if (len > 0 && p[len-1] == '/') {
2069 if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
2073 if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
2084 /* Convert '//' --> '/' */
2086 else if (p[1] == '.' && p[2] == '/')
2087 /* Convert '/./' --> '/' */
2089 else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
2090 /* Convert 'dir/dir1/../dir2/'
2094 while (rp >= dirname) {
2103 strcpy(dirname, p+4);
2114 if (archive_entry_filetype(file->entry) == AE_IFLNK) {
2116 /* Convert symlink name too. */
2117 if (archive_entry_symlink_l(file->entry, &pp, &len2,
2119 if (errno == ENOMEM) {
2120 archive_set_error(&a->archive, ENOMEM,
2121 "Can't allocate memory for Linkname");
2122 return (ARCHIVE_FATAL);
2124 archive_set_error(&a->archive,
2125 ARCHIVE_ERRNO_FILE_FORMAT,
2126 "Can't translate symlink '%s' to UTF-8",
2127 archive_entry_symlink(file->entry));
2130 archive_strncpy(&(file->symlink), pp, len2);
2131 cleanup_backslash(file->symlink.s, file->symlink.length);
2134 * - Count up directory elements.
2135 * - Find out the position which points the last position of
2136 * path separator('/').
2139 for (; *p != '\0'; p++)
2142 if (slash == NULL) {
2143 /* The pathname doesn't have a parent directory. */
2144 file->parentdir.length = len;
2145 archive_string_copy(&(file->basename), &(file->parentdir));
2146 archive_string_empty(&(file->parentdir));
2147 file->parentdir.s = '\0';
2151 /* Make a basename from dirname and slash */
2153 file->parentdir.length = slash - dirname;
2154 archive_strcpy(&(file->basename), slash + 1);
2159 get_path_component(char *name, int n, const char *fn)
2164 p = strchr(fn, '/');
2166 if ((l = strlen(fn)) == 0)
2172 memcpy(name, fn, l);
2179 * Add a new entry into the tree.
2182 file_tree(struct archive_write *a, struct file **filepp)
2184 #if defined(_WIN32) && !defined(__CYGWIN__)
2185 char name[_MAX_FNAME];/* Included null terminator size. */
2186 #elif defined(NAME_MAX) && NAME_MAX >= 255
2187 char name[NAME_MAX+1];
2191 struct xar *xar = (struct xar *)a->format_data;
2192 struct file *dent, *file, *np;
2193 struct archive_entry *ent;
2199 if (file->parentdir.length > 0)
2200 fn = p = file->parentdir.s;
2205 * If the path of the parent directory of `file' entry is
2206 * the same as the path of `cur_dirent', add isoent to
2209 if (archive_strlen(&(xar->cur_dirstr))
2210 == archive_strlen(&(file->parentdir)) &&
2211 strcmp(xar->cur_dirstr.s, fn) == 0) {
2212 if (!file_add_child_tail(xar->cur_dirent, file)) {
2213 np = (struct file *)__archive_rb_tree_find_node(
2214 &(xar->cur_dirent->rbtree),
2218 return (ARCHIVE_OK);
2222 l = get_path_component(name, sizeof(name), fn);
2228 archive_set_error(&a->archive,
2230 "A name buffer is too small");
2233 return (ARCHIVE_FATAL);
2236 np = file_find_child(dent, name);
2237 if (np == NULL || fn[0] == '\0')
2240 /* Find next subdirectory. */
2242 /* NOT Directory! */
2243 archive_set_error(&a->archive,
2245 "`%s' is not directory, we cannot insert `%s' ",
2246 archive_entry_pathname(np->entry),
2247 archive_entry_pathname(file->entry));
2250 return (ARCHIVE_FAILED);
2259 * Create virtual parent directories.
2261 while (fn[0] != '\0') {
2263 struct archive_string as;
2265 archive_string_init(&as);
2266 archive_strncat(&as, p, fn - p + l);
2267 if (as.s[as.length-1] == '/') {
2268 as.s[as.length-1] = '\0';
2271 vp = file_create_virtual_dir(a, xar, as.s);
2273 archive_string_free(&as);
2274 archive_set_error(&a->archive, ENOMEM,
2275 "Can't allocate memory");
2278 return (ARCHIVE_FATAL);
2280 archive_string_free(&as);
2281 if (file_gen_utility_names(a, vp) <= ARCHIVE_FAILED)
2282 return (ARCHIVE_FATAL);
2283 file_add_child_tail(dent, vp);
2284 file_register(xar, vp);
2290 l = get_path_component(name, sizeof(name), fn);
2292 archive_string_free(&as);
2293 archive_set_error(&a->archive,
2295 "A name buffer is too small");
2298 return (ARCHIVE_FATAL);
2303 /* Found out the parent directory where isoent can be
2305 xar->cur_dirent = dent;
2306 archive_string_empty(&(xar->cur_dirstr));
2307 archive_string_ensure(&(xar->cur_dirstr),
2308 archive_strlen(&(dent->parentdir)) +
2309 archive_strlen(&(dent->basename)) + 2);
2310 if (archive_strlen(&(dent->parentdir)) +
2311 archive_strlen(&(dent->basename)) == 0)
2312 xar->cur_dirstr.s[0] = 0;
2314 if (archive_strlen(&(dent->parentdir)) > 0) {
2315 archive_string_copy(&(xar->cur_dirstr),
2316 &(dent->parentdir));
2317 archive_strappend_char(&(xar->cur_dirstr), '/');
2319 archive_string_concat(&(xar->cur_dirstr),
2323 if (!file_add_child_tail(dent, file)) {
2324 np = (struct file *)__archive_rb_tree_find_node(
2325 &(dent->rbtree), file->basename.s);
2328 return (ARCHIVE_OK);
2333 * We have already has the entry the filename of which is
2336 if (archive_entry_filetype(np->entry) !=
2337 archive_entry_filetype(file->entry)) {
2338 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2339 "Found duplicate entries `%s' and its file type is "
2341 archive_entry_pathname(np->entry));
2344 return (ARCHIVE_FAILED);
2349 np->entry = file->entry;
2355 return (ARCHIVE_OK);
2359 file_register(struct xar *xar, struct file *file)
2361 file->id = xar->file_idx++;
2363 *xar->file_list.last = file;
2364 xar->file_list.last = &(file->next);
2368 file_init_register(struct xar *xar)
2370 xar->file_list.first = NULL;
2371 xar->file_list.last = &(xar->file_list.first);
2375 file_free_register(struct xar *xar)
2377 struct file *file, *file_next;
2379 file = xar->file_list.first;
2380 while (file != NULL) {
2381 file_next = file->next;
2388 * Register entry to get a hardlink target.
2391 file_register_hardlink(struct archive_write *a, struct file *file)
2393 struct xar *xar = (struct xar *)a->format_data;
2394 struct hardlink *hl;
2395 const char *pathname;
2397 archive_entry_set_nlink(file->entry, 1);
2398 pathname = archive_entry_hardlink(file->entry);
2399 if (pathname == NULL) {
2400 /* This `file` is a hardlink target. */
2401 hl = malloc(sizeof(*hl));
2403 archive_set_error(&a->archive, ENOMEM,
2404 "Can't allocate memory");
2405 return (ARCHIVE_FATAL);
2408 /* A hardlink target must be the first position. */
2409 file->hlnext = NULL;
2410 hl->file_list.first = file;
2411 hl->file_list.last = &(file->hlnext);
2412 __archive_rb_tree_insert_node(&(xar->hardlink_rbtree),
2413 (struct archive_rb_node *)hl);
2415 hl = (struct hardlink *)__archive_rb_tree_find_node(
2416 &(xar->hardlink_rbtree), pathname);
2418 /* Insert `file` entry into the tail. */
2419 file->hlnext = NULL;
2420 *hl->file_list.last = file;
2421 hl->file_list.last = &(file->hlnext);
2424 archive_entry_unset_size(file->entry);
2427 return (ARCHIVE_OK);
2431 * Hardlinked files have to have the same location of extent.
2432 * We have to find out hardlink target entries for entries which
2433 * have a hardlink target name.
2436 file_connect_hardlink_files(struct xar *xar)
2438 struct archive_rb_node *n;
2439 struct hardlink *hl;
2440 struct file *target, *nf;
2442 ARCHIVE_RB_TREE_FOREACH(n, &(xar->hardlink_rbtree)) {
2443 hl = (struct hardlink *)n;
2445 /* The first entry must be a hardlink target. */
2446 target = hl->file_list.first;
2447 archive_entry_set_nlink(target->entry, hl->nlink);
2449 /* It means this file is a hardlink
2451 target->hardlink_target = target;
2452 for (nf = target->hlnext;
2453 nf != NULL; nf = nf->hlnext) {
2454 nf->hardlink_target = target;
2455 archive_entry_set_nlink(nf->entry, hl->nlink);
2461 file_hd_cmp_node(const struct archive_rb_node *n1,
2462 const struct archive_rb_node *n2)
2464 struct hardlink *h1 = (struct hardlink *)n1;
2465 struct hardlink *h2 = (struct hardlink *)n2;
2467 return (strcmp(archive_entry_pathname(h1->file_list.first->entry),
2468 archive_entry_pathname(h2->file_list.first->entry)));
2472 file_hd_cmp_key(const struct archive_rb_node *n, const void *key)
2474 struct hardlink *h = (struct hardlink *)n;
2476 return (strcmp(archive_entry_pathname(h->file_list.first->entry),
2477 (const char *)key));
2482 file_init_hardlinks(struct xar *xar)
2484 static const struct archive_rb_tree_ops rb_ops = {
2485 file_hd_cmp_node, file_hd_cmp_key,
2488 __archive_rb_tree_init(&(xar->hardlink_rbtree), &rb_ops);
2492 file_free_hardlinks(struct xar *xar)
2494 struct archive_rb_node *n, *next;
2496 for (n = ARCHIVE_RB_TREE_MIN(&(xar->hardlink_rbtree)); n;) {
2497 next = __archive_rb_tree_iterate(&(xar->hardlink_rbtree),
2498 n, ARCHIVE_RB_DIR_RIGHT);
2505 checksum_init(struct chksumwork *sumwrk, enum sumalg sum_alg)
2507 sumwrk->alg = sum_alg;
2512 archive_sha1_init(&(sumwrk->sha1ctx));
2515 archive_md5_init(&(sumwrk->md5ctx));
2521 checksum_update(struct chksumwork *sumwrk, const void *buff, size_t size)
2524 switch (sumwrk->alg) {
2528 archive_sha1_update(&(sumwrk->sha1ctx), buff, size);
2531 archive_md5_update(&(sumwrk->md5ctx), buff, size);
2537 checksum_final(struct chksumwork *sumwrk, struct chksumval *sumval)
2540 switch (sumwrk->alg) {
2545 archive_sha1_final(&(sumwrk->sha1ctx), sumval->val);
2546 sumval->len = SHA1_SIZE;
2549 archive_md5_final(&(sumwrk->md5ctx), sumval->val);
2550 sumval->len = MD5_SIZE;
2553 sumval->alg = sumwrk->alg;
2556 #if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
2558 compression_unsupported_encoder(struct archive *a,
2559 struct la_zstream *lastrm, const char *name)
2562 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2563 "%s compression not supported on this platform", name);
2565 lastrm->real_stream = NULL;
2566 return (ARCHIVE_FAILED);
2571 compression_init_encoder_gzip(struct archive *a,
2572 struct la_zstream *lastrm, int level, int withheader)
2577 compression_end(a, lastrm);
2578 strm = calloc(1, sizeof(*strm));
2580 archive_set_error(a, ENOMEM,
2581 "Can't allocate memory for gzip stream");
2582 return (ARCHIVE_FATAL);
2584 /* zlib.h is not const-correct, so we need this one bit
2585 * of ugly hackery to convert a const * pointer to
2586 * a non-const pointer. */
2587 strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
2588 strm->avail_in = lastrm->avail_in;
2589 strm->total_in = lastrm->total_in;
2590 strm->next_out = lastrm->next_out;
2591 strm->avail_out = lastrm->avail_out;
2592 strm->total_out = lastrm->total_out;
2593 if (deflateInit2(strm, level, Z_DEFLATED,
2594 (withheader)?15:-15,
2595 8, Z_DEFAULT_STRATEGY) != Z_OK) {
2597 lastrm->real_stream = NULL;
2598 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2599 "Internal error initializing compression library");
2600 return (ARCHIVE_FATAL);
2602 lastrm->real_stream = strm;
2604 lastrm->code = compression_code_gzip;
2605 lastrm->end = compression_end_gzip;
2606 return (ARCHIVE_OK);
2610 compression_code_gzip(struct archive *a,
2611 struct la_zstream *lastrm, enum la_zaction action)
2616 strm = (z_stream *)lastrm->real_stream;
2617 /* zlib.h is not const-correct, so we need this one bit
2618 * of ugly hackery to convert a const * pointer to
2619 * a non-const pointer. */
2620 strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
2621 strm->avail_in = lastrm->avail_in;
2622 strm->total_in = lastrm->total_in;
2623 strm->next_out = lastrm->next_out;
2624 strm->avail_out = lastrm->avail_out;
2625 strm->total_out = lastrm->total_out;
2627 (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH);
2628 lastrm->next_in = strm->next_in;
2629 lastrm->avail_in = strm->avail_in;
2630 lastrm->total_in = strm->total_in;
2631 lastrm->next_out = strm->next_out;
2632 lastrm->avail_out = strm->avail_out;
2633 lastrm->total_out = strm->total_out;
2636 return (ARCHIVE_OK);
2638 return (ARCHIVE_EOF);
2640 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2641 "GZip compression failed:"
2642 " deflate() call returned status %d", r);
2643 return (ARCHIVE_FATAL);
2648 compression_end_gzip(struct archive *a, struct la_zstream *lastrm)
2653 strm = (z_stream *)lastrm->real_stream;
2654 r = deflateEnd(strm);
2656 lastrm->real_stream = NULL;
2659 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2660 "Failed to clean up compressor");
2661 return (ARCHIVE_FATAL);
2663 return (ARCHIVE_OK);
2666 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
2668 compression_init_encoder_bzip2(struct archive *a,
2669 struct la_zstream *lastrm, int level)
2674 compression_end(a, lastrm);
2675 strm = calloc(1, sizeof(*strm));
2677 archive_set_error(a, ENOMEM,
2678 "Can't allocate memory for bzip2 stream");
2679 return (ARCHIVE_FATAL);
2681 /* bzlib.h is not const-correct, so we need this one bit
2682 * of ugly hackery to convert a const * pointer to
2683 * a non-const pointer. */
2684 strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
2685 strm->avail_in = lastrm->avail_in;
2686 strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
2687 strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
2688 strm->next_out = (char *)lastrm->next_out;
2689 strm->avail_out = lastrm->avail_out;
2690 strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
2691 strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
2692 if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) {
2694 lastrm->real_stream = NULL;
2695 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2696 "Internal error initializing compression library");
2697 return (ARCHIVE_FATAL);
2699 lastrm->real_stream = strm;
2701 lastrm->code = compression_code_bzip2;
2702 lastrm->end = compression_end_bzip2;
2703 return (ARCHIVE_OK);
2707 compression_code_bzip2(struct archive *a,
2708 struct la_zstream *lastrm, enum la_zaction action)
2713 strm = (bz_stream *)lastrm->real_stream;
2714 /* bzlib.h is not const-correct, so we need this one bit
2715 * of ugly hackery to convert a const * pointer to
2716 * a non-const pointer. */
2717 strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
2718 strm->avail_in = lastrm->avail_in;
2719 strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
2720 strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
2721 strm->next_out = (char *)lastrm->next_out;
2722 strm->avail_out = lastrm->avail_out;
2723 strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
2724 strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
2725 r = BZ2_bzCompress(strm,
2726 (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN);
2727 lastrm->next_in = (const unsigned char *)strm->next_in;
2728 lastrm->avail_in = strm->avail_in;
2730 (((uint64_t)(uint32_t)strm->total_in_hi32) << 32)
2731 + (uint64_t)(uint32_t)strm->total_in_lo32;
2732 lastrm->next_out = (unsigned char *)strm->next_out;
2733 lastrm->avail_out = strm->avail_out;
2735 (((uint64_t)(uint32_t)strm->total_out_hi32) << 32)
2736 + (uint64_t)(uint32_t)strm->total_out_lo32;
2738 case BZ_RUN_OK: /* Non-finishing */
2739 case BZ_FINISH_OK: /* Finishing: There's more work to do */
2740 return (ARCHIVE_OK);
2741 case BZ_STREAM_END: /* Finishing: all done */
2742 /* Only occurs in finishing case */
2743 return (ARCHIVE_EOF);
2745 /* Any other return value indicates an error */
2746 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2747 "Bzip2 compression failed:"
2748 " BZ2_bzCompress() call returned status %d", r);
2749 return (ARCHIVE_FATAL);
2754 compression_end_bzip2(struct archive *a, struct la_zstream *lastrm)
2759 strm = (bz_stream *)lastrm->real_stream;
2760 r = BZ2_bzCompressEnd(strm);
2762 lastrm->real_stream = NULL;
2765 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2766 "Failed to clean up compressor");
2767 return (ARCHIVE_FATAL);
2769 return (ARCHIVE_OK);
2774 compression_init_encoder_bzip2(struct archive *a,
2775 struct la_zstream *lastrm, int level)
2778 (void) level; /* UNUSED */
2780 compression_end(a, lastrm);
2781 return (compression_unsupported_encoder(a, lastrm, "bzip2"));
2785 #if defined(HAVE_LZMA_H)
2787 compression_init_encoder_lzma(struct archive *a,
2788 struct la_zstream *lastrm, int level)
2790 static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
2792 lzma_options_lzma lzma_opt;
2796 compression_end(a, lastrm);
2797 if (lzma_lzma_preset(&lzma_opt, level)) {
2798 lastrm->real_stream = NULL;
2799 archive_set_error(a, ENOMEM,
2800 "Internal error initializing compression library");
2801 return (ARCHIVE_FATAL);
2803 strm = calloc(1, sizeof(*strm));
2805 archive_set_error(a, ENOMEM,
2806 "Can't allocate memory for lzma stream");
2807 return (ARCHIVE_FATAL);
2809 *strm = lzma_init_data;
2810 r = lzma_alone_encoder(strm, &lzma_opt);
2813 lastrm->real_stream = strm;
2815 lastrm->code = compression_code_lzma;
2816 lastrm->end = compression_end_lzma;
2819 case LZMA_MEM_ERROR:
2821 lastrm->real_stream = NULL;
2822 archive_set_error(a, ENOMEM,
2823 "Internal error initializing compression library: "
2824 "Cannot allocate memory");
2829 lastrm->real_stream = NULL;
2830 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2831 "Internal error initializing compression library: "
2832 "It's a bug in liblzma");
2840 compression_init_encoder_xz(struct archive *a,
2841 struct la_zstream *lastrm, int level)
2843 static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
2845 lzma_filter *lzmafilters;
2846 lzma_options_lzma lzma_opt;
2850 compression_end(a, lastrm);
2851 strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2);
2853 archive_set_error(a, ENOMEM,
2854 "Can't allocate memory for xz stream");
2855 return (ARCHIVE_FATAL);
2857 lzmafilters = (lzma_filter *)(strm+1);
2860 if (lzma_lzma_preset(&lzma_opt, level)) {
2861 lastrm->real_stream = NULL;
2862 archive_set_error(a, ENOMEM,
2863 "Internal error initializing compression library");
2864 return (ARCHIVE_FATAL);
2866 lzmafilters[0].id = LZMA_FILTER_LZMA2;
2867 lzmafilters[0].options = &lzma_opt;
2868 lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
2870 *strm = lzma_init_data;
2871 r = lzma_stream_encoder(strm, lzmafilters, LZMA_CHECK_CRC64);
2874 lastrm->real_stream = strm;
2876 lastrm->code = compression_code_lzma;
2877 lastrm->end = compression_end_lzma;
2880 case LZMA_MEM_ERROR:
2882 lastrm->real_stream = NULL;
2883 archive_set_error(a, ENOMEM,
2884 "Internal error initializing compression library: "
2885 "Cannot allocate memory");
2890 lastrm->real_stream = NULL;
2891 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2892 "Internal error initializing compression library: "
2893 "It's a bug in liblzma");
2901 compression_code_lzma(struct archive *a,
2902 struct la_zstream *lastrm, enum la_zaction action)
2907 strm = (lzma_stream *)lastrm->real_stream;
2908 strm->next_in = lastrm->next_in;
2909 strm->avail_in = lastrm->avail_in;
2910 strm->total_in = lastrm->total_in;
2911 strm->next_out = lastrm->next_out;
2912 strm->avail_out = lastrm->avail_out;
2913 strm->total_out = lastrm->total_out;
2915 (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN);
2916 lastrm->next_in = strm->next_in;
2917 lastrm->avail_in = strm->avail_in;
2918 lastrm->total_in = strm->total_in;
2919 lastrm->next_out = strm->next_out;
2920 lastrm->avail_out = strm->avail_out;
2921 lastrm->total_out = strm->total_out;
2924 /* Non-finishing case */
2925 return (ARCHIVE_OK);
2926 case LZMA_STREAM_END:
2927 /* This return can only occur in finishing case. */
2928 return (ARCHIVE_EOF);
2929 case LZMA_MEMLIMIT_ERROR:
2930 archive_set_error(a, ENOMEM,
2931 "lzma compression error:"
2932 " %ju MiB would have been needed",
2933 (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1)
2935 return (ARCHIVE_FATAL);
2937 /* Any other return value indicates an error */
2938 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2939 "lzma compression failed:"
2940 " lzma_code() call returned status %d", r);
2941 return (ARCHIVE_FATAL);
2946 compression_end_lzma(struct archive *a, struct la_zstream *lastrm)
2950 (void)a; /* UNUSED */
2951 strm = (lzma_stream *)lastrm->real_stream;
2955 lastrm->real_stream = NULL;
2956 return (ARCHIVE_OK);
2960 compression_init_encoder_lzma(struct archive *a,
2961 struct la_zstream *lastrm, int level)
2964 (void) level; /* UNUSED */
2966 compression_end(a, lastrm);
2967 return (compression_unsupported_encoder(a, lastrm, "lzma"));
2970 compression_init_encoder_xz(struct archive *a,
2971 struct la_zstream *lastrm, int level)
2974 (void) level; /* UNUSED */
2976 compression_end(a, lastrm);
2977 return (compression_unsupported_encoder(a, lastrm, "xz"));
2982 xar_compression_init_encoder(struct archive_write *a)
2987 xar = (struct xar *)a->format_data;
2988 switch (xar->opt_compression) {
2990 r = compression_init_encoder_gzip(
2991 &(a->archive), &(xar->stream),
2992 xar->opt_compression_level, 1);
2995 r = compression_init_encoder_bzip2(
2996 &(a->archive), &(xar->stream),
2997 xar->opt_compression_level);
3000 r = compression_init_encoder_lzma(
3001 &(a->archive), &(xar->stream),
3002 xar->opt_compression_level);
3005 r = compression_init_encoder_xz(
3006 &(a->archive), &(xar->stream),
3007 xar->opt_compression_level);
3013 if (r == ARCHIVE_OK) {
3014 xar->stream.total_in = 0;
3015 xar->stream.next_out = xar->wbuff;
3016 xar->stream.avail_out = sizeof(xar->wbuff);
3017 xar->stream.total_out = 0;
3024 compression_code(struct archive *a, struct la_zstream *lastrm,
3025 enum la_zaction action)
3028 return (lastrm->code(a, lastrm, action));
3029 return (ARCHIVE_OK);
3033 compression_end(struct archive *a, struct la_zstream *lastrm)
3036 return (lastrm->end(a, lastrm));
3037 return (ARCHIVE_OK);
3042 save_xattrs(struct archive_write *a, struct file *file)
3047 struct heap_data *heap;
3051 xar = (struct xar *)a->format_data;
3052 count = archive_entry_xattr_reset(file->entry);
3054 return (ARCHIVE_OK);
3056 archive_entry_xattr_next(file->entry,
3057 &name, &value, &size);
3058 checksum_init(&(xar->a_sumwrk), xar->opt_sumalg);
3059 checksum_init(&(xar->e_sumwrk), xar->opt_sumalg);
3061 heap = calloc(1, sizeof(*heap));
3063 archive_set_error(&a->archive, ENOMEM,
3064 "Can't allocate memory for xattr");
3065 return (ARCHIVE_FATAL);
3067 heap->id = file->ea_idx++;
3068 heap->temp_offset = xar->temp_offset;
3069 heap->size = size;/* save a extracted size */
3070 heap->compression = xar->opt_compression;
3071 /* Get a extracted sumcheck value. */
3072 checksum_update(&(xar->e_sumwrk), value, size);
3073 checksum_final(&(xar->e_sumwrk), &(heap->e_sum));
3076 * Not compression to xattr is simple way.
3078 if (heap->compression == NONE) {
3079 checksum_update(&(xar->a_sumwrk), value, size);
3080 checksum_final(&(xar->a_sumwrk), &(heap->a_sum));
3081 if (write_to_temp(a, value, size)
3083 return (ARCHIVE_FATAL);
3084 heap->length = size;
3085 /* Add heap to the tail of file->xattr. */
3087 *file->xattr.last = heap;
3088 file->xattr.last = &(heap->next);
3094 * Init compression library.
3096 r = xar_compression_init_encoder(a);
3097 if (r != ARCHIVE_OK) {
3099 return (ARCHIVE_FATAL);
3102 xar->stream.next_in = (const unsigned char *)value;
3103 xar->stream.avail_in = size;
3105 r = compression_code(&(a->archive),
3106 &(xar->stream), ARCHIVE_Z_FINISH);
3107 if (r != ARCHIVE_OK && r != ARCHIVE_EOF) {
3109 return (ARCHIVE_FATAL);
3111 size = sizeof(xar->wbuff) - xar->stream.avail_out;
3112 checksum_update(&(xar->a_sumwrk),
3114 if (write_to_temp(a, xar->wbuff, size)
3116 return (ARCHIVE_FATAL);
3117 if (r == ARCHIVE_OK) {
3118 xar->stream.next_out = xar->wbuff;
3119 xar->stream.avail_out = sizeof(xar->wbuff);
3121 checksum_final(&(xar->a_sumwrk),
3123 heap->length = xar->stream.total_out;
3124 /* Add heap to the tail of file->xattr. */
3126 *file->xattr.last = heap;
3127 file->xattr.last = &(heap->next);
3131 /* Clean up compression library. */
3132 r = compression_end(&(a->archive), &(xar->stream));
3133 if (r != ARCHIVE_OK)
3134 return (ARCHIVE_FATAL);
3136 return (ARCHIVE_OK);
3140 getalgsize(enum sumalg sumalg)
3154 getalgname(enum sumalg sumalg)
3167 #endif /* Support xar format */