2 * Copyright (c) 2009-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"
28 #ifdef HAVE_SYS_TYPES_H
29 #include <sys/types.h>
31 #ifdef HAVE_SYS_UTSNAME_H
32 #include <sys/utsname.h>
54 #include "archive_endian.h"
55 #include "archive_entry.h"
56 #include "archive_entry_locale.h"
57 #include "archive_private.h"
58 #include "archive_rb.h"
59 #include "archive_write_private.h"
61 #if defined(_WIN32) && !defined(__CYGWIN__)
68 /* To compare to the ISO image file made by mkisofs. */
69 #define COMPAT_MKISOFS 1
72 #define LOGICAL_BLOCK_BITS 11
73 #define LOGICAL_BLOCK_SIZE 2048
74 #define PATH_TABLE_BLOCK_SIZE 4096
76 #define SYSTEM_AREA_BLOCK 16
77 #define PRIMARY_VOLUME_DESCRIPTOR_BLOCK 1
78 #define SUPPLEMENTARY_VOLUME_DESCRIPTOR_BLOCK 1
79 #define BOOT_RECORD_DESCRIPTOR_BLOCK 1
80 #define VOLUME_DESCRIPTOR_SET_TERMINATOR_BLOCK 1
81 #define NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK 1
82 #define RRIP_ER_BLOCK 1
83 #define PADDING_BLOCK 150
85 #define FD_1_2M_SIZE (1024 * 1200)
86 #define FD_1_44M_SIZE (1024 * 1440)
87 #define FD_2_88M_SIZE (1024 * 2880)
88 #define MULTI_EXTENT_SIZE (ARCHIVE_LITERAL_LL(1) << 32) /* 4Gi bytes. */
90 #define RR_CE_SIZE 28 /* SUSP "CE" extension size */
92 #define FILE_FLAG_EXISTENCE 0x01
93 #define FILE_FLAG_DIRECTORY 0x02
94 #define FILE_FLAG_ASSOCIATED 0x04
95 #define FILE_FLAG_RECORD 0x08
96 #define FILE_FLAG_PROTECTION 0x10
97 #define FILE_FLAG_MULTI_EXTENT 0x80
99 static const char rrip_identifier[] =
101 static const char rrip_descriptor[] =
102 "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR "
103 "POSIX FILE SYSTEM SEMANTICS";
104 static const char rrip_source[] =
105 "PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. "
106 "SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR "
107 "CONTACT INFORMATION.";
108 #define RRIP_ER_ID_SIZE (sizeof(rrip_identifier)-1)
109 #define RRIP_ER_DSC_SIZE (sizeof(rrip_descriptor)-1)
110 #define RRIP_ER_SRC_SIZE (sizeof(rrip_source)-1)
111 #define RRIP_ER_SIZE (8 + RRIP_ER_ID_SIZE + \
112 RRIP_ER_DSC_SIZE + RRIP_ER_SRC_SIZE)
114 static const unsigned char zisofs_magic[8] = {
115 0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07
118 #define ZF_HEADER_SIZE 16 /* zisofs header size. */
119 #define ZF_LOG2_BS 15 /* log2 block size; 32K bytes. */
120 #define ZF_BLOCK_SIZE (1UL << ZF_LOG2_BS)
123 * Manage extra records.
128 unsigned char buf[LOGICAL_BLOCK_SIZE];
129 struct extr_rec *next;
132 struct ctl_extr_rec {
135 struct isoent *isoent;
136 unsigned char *ce_ptr;
143 #define DR_SAFETY RR_CE_SIZE
144 #define DR_LIMIT (254 - DR_SAFETY)
147 * The relation of struct isofile and isoent and archive_entry.
149 * Primary volume tree --> struct isoent
152 * struct isofile --> archive_entry
155 * Joliet volume tree --> struct isoent
157 * struct isoent has specific information for volume.
161 /* Used for managing struct isofile list. */
162 struct isofile *allnext;
163 struct isofile *datanext;
164 /* Used for managing a hardlined struct isofile list. */
165 struct isofile *hlnext;
166 struct isofile *hardlink_target;
168 struct archive_entry *entry;
171 * Used for making a directory tree.
173 struct archive_string parentdir;
174 struct archive_string basename;
175 struct archive_string basename_utf16;
176 struct archive_string symlink;
177 int dircnt; /* The number of elements of
178 * its parent directory */
181 * Used for a Directory Record.
184 int64_t offset_of_temp;
189 * One extent equals one content.
190 * If this entry has multi extent, `next' variable points
193 struct content *next; /* next content */
194 } content, *cur_content;
207 unsigned char header_size;
208 unsigned char log2_bs;
209 uint32_t uncompressed_size;
214 /* Keep `rbnode' at the first member of struct isoent. */
215 struct archive_rb_node rbnode;
217 struct isofile *file;
219 struct isoent *parent;
220 /* A list of children.(use chnext) */
222 struct isoent *first;
223 struct isoent **last;
226 struct archive_rb_tree rbtree;
228 /* A list of sub directories.(use drnext) */
230 struct isoent *first;
231 struct isoent **last;
234 /* A sorted list of sub directories. */
235 struct isoent **children_sorted;
236 /* Used for managing struct isoent list. */
237 struct isoent *chnext;
238 struct isoent *drnext;
239 struct isoent *ptnext;
242 * Used for making a Directory Record.
251 uint32_t dir_location;
256 * on primary, ISO9660 file/directory name.
257 * on joliet, UCS2 file/directory name.
258 * ext_off : offset of identifier extension.
259 * ext_len : length of identifier extension.
260 * id_len : byte size of identifier.
261 * on primary, this is ext_off + ext_len + version length.
262 * on joliet, this is ext_off + ext_len.
263 * mb_len : length of multibyte-character of identifier.
264 * on primary, mb_len and id_len are always the same.
265 * on joliet, mb_len and id_len are different.
274 * Used for making a Rockridge extension.
275 * This is a part of Directory Records.
277 struct isoent *rr_parent;
278 struct isoent *rr_child;
280 /* Extra Record.(which we call in this source file)
281 * A maximum size of the Directory Record is 254.
282 * so, if generated RRIP data of a file cannot into a Directory
283 * Record because of its size, that surplus data relocate this
287 struct extr_rec *first;
288 struct extr_rec **last;
289 struct extr_rec *current;
293 /* If set to one, this file type is a directory.
294 * A convenience flag to be used as
295 * "archive_entry_filetype(isoent->file->entry) == AE_IFDIR".
301 struct archive_rb_node rbnode;
304 struct isofile *first;
305 struct isofile **last;
314 * Usage : abstract-file=<value>
315 * Type : string, max 37 bytes
316 * Default: Not specified
317 * COMPAT : mkisofs -abstract <value>
319 * Specifies Abstract Filename.
320 * This file shall be described in the Root Directory
321 * and containing a abstract statement.
323 unsigned int abstract_file:1;
324 #define OPT_ABSTRACT_FILE_DEFAULT 0 /* Not specified */
325 #define ABSTRACT_FILE_SIZE 37
328 * Usage : application-id=<value>
329 * Type : string, max 128 bytes
330 * Default: Not specified
331 * COMPAT : mkisofs -A/-appid <value>.
333 * Specifies Application Identifier.
334 * If the first byte is set to '_'(5F), the remaining
335 * bytes of this option shall specify an identifier
336 * for a file containing the identification of the
338 * This file shall be described in the Root Directory.
340 unsigned int application_id:1;
341 #define OPT_APPLICATION_ID_DEFAULT 0 /* Use default identifier */
342 #define APPLICATION_IDENTIFIER_SIZE 128
345 * Usage : !allow-vernum
348 * : Violates the ISO9660 standard if disable.
351 * Allow filenames to use version numbers.
353 unsigned int allow_vernum:1;
354 #define OPT_ALLOW_VERNUM_DEFAULT 1 /* Enabled */
357 * Usage : biblio-file=<value>
358 * Type : string, max 37 bytes
359 * Default: Not specified
360 * COMPAT : mkisofs -biblio <value>
362 * Specifies Bibliographic Filename.
363 * This file shall be described in the Root Directory
364 * and containing bibliographic records.
366 unsigned int biblio_file:1;
367 #define OPT_BIBLIO_FILE_DEFAULT 0 /* Not specified */
368 #define BIBLIO_FILE_SIZE 37
371 * Usage : boot=<value>
373 * Default: Not specified
374 * COMPAT : mkisofs -b/-eltorito-boot <value>
376 * Specifies "El Torito" boot image file to make
380 #define OPT_BOOT_DEFAULT 0 /* Not specified */
383 * Usage : boot-catalog=<value>
385 * Default: "boot.catalog"
386 * COMPAT : mkisofs -c/-eltorito-catalog <value>
388 * Specifies a fullpath of El Torito boot catalog.
390 unsigned int boot_catalog:1;
391 #define OPT_BOOT_CATALOG_DEFAULT 0 /* Not specified */
394 * Usage : boot-info-table
397 * COMPAT : mkisofs -boot-info-table
399 * Modify the boot image file specified by `boot'
400 * option; ISO writer stores boot file information
401 * into the boot file in ISO image at offset 8
404 unsigned int boot_info_table:1;
405 #define OPT_BOOT_INFO_TABLE_DEFAULT 0 /* Disabled */
408 * Usage : boot-load-seg=<value>
410 * Default: Not specified
411 * COMPAT : mkisofs -boot-load-seg <value>
413 * Specifies a load segment for boot image.
414 * This is used with no-emulation mode.
416 unsigned int boot_load_seg:1;
417 #define OPT_BOOT_LOAD_SEG_DEFAULT 0 /* Not specified */
420 * Usage : boot-load-size=<value>
422 * Default: Not specified
423 * COMPAT : mkisofs -boot-load-size <value>
425 * Specifies a sector count for boot image.
426 * This is used with no-emulation mode.
428 unsigned int boot_load_size:1;
429 #define OPT_BOOT_LOAD_SIZE_DEFAULT 0 /* Not specified */
432 * Usage : boot-type=<boot-media-type>
433 * : 'no-emulation' : 'no emulation' image
434 * : 'fd' : floppy disk image
435 * : 'hard-disk' : hard disk image
437 * Default: Auto detect
438 * : We check a size of boot image;
439 * : If ths size is just 1.22M/1.44M/2.88M,
440 * : we assume boot_type is 'fd';
441 * : otherwise boot_type is 'no-emulation'.
444 * mkisofs -no-emul-boot
446 * This is a default on the mkisofs.
448 * mkisofs -hard-disk-boot
450 * Specifies a type of "El Torito" boot image.
452 unsigned int boot_type:2;
453 #define OPT_BOOT_TYPE_AUTO 0 /* auto detect */
454 #define OPT_BOOT_TYPE_NO_EMU 1 /* ``no emulation'' image */
455 #define OPT_BOOT_TYPE_FD 2 /* floppy disk image */
456 #define OPT_BOOT_TYPE_HARD_DISK 3 /* hard disk image */
457 #define OPT_BOOT_TYPE_DEFAULT OPT_BOOT_TYPE_AUTO
460 * Usage : compression-level=<value>
462 * Default: Not specified
465 * Specifies compression level for option zisofs=direct.
467 unsigned int compression_level:1;
468 #define OPT_COMPRESSION_LEVEL_DEFAULT 0 /* Not specified */
471 * Usage : copyright-file=<value>
472 * Type : string, max 37 bytes
473 * Default: Not specified
474 * COMPAT : mkisofs -copyright <value>
476 * Specifies Copyright Filename.
477 * This file shall be described in the Root Directory
478 * and containing a copyright statement.
480 unsigned int copyright_file:1;
481 #define OPT_COPYRIGHT_FILE_DEFAULT 0 /* Not specified */
482 #define COPYRIGHT_FILE_SIZE 37
485 * Usage : gid=<value>
487 * Default: Not specified
488 * COMPAT : mkisofs -gid <value>
490 * Specifies a group id to rewrite the group id of all files.
493 #define OPT_GID_DEFAULT 0 /* Not specified */
496 * Usage : iso-level=[1234]
499 * COMPAT : mkisofs -iso-level <value>
501 * Specifies ISO9600 Level.
503 * - limits each file size less than 4Gi bytes;
504 * - a File Name shall not contain more than eight
505 * d-characters or eight d1-characters;
506 * - a File Name Extension shall not contain more than
507 * three d-characters or three d1-characters;
508 * - a Directory Identifier shall not contain more
509 * than eight d-characters or eight d1-characters.
511 * - limits each file size less than 4Giga bytes;
512 * - a File Name shall not contain more than thirty
513 * d-characters or thirty d1-characters;
514 * - a File Name Extension shall not contain more than
515 * thirty d-characters or thirty d1-characters;
516 * - a Directory Identifier shall not contain more
517 * than thirty-one d-characters or thirty-one
520 * - no limit of file size; use multi extent.
522 * - this level 4 simulates mkisofs option
524 * - crate a enhanced volume as mkisofs doing;
525 * - allow a File Name to have leading dot;
526 * - allow a File Name to have all ASCII letters;
527 * - allow a File Name to have multiple dots;
528 * - allow more then 8 depths of directory trees;
529 * - disable a version number to a File Name;
530 * - disable a forced period to the tail of a File Name;
531 * - the maxinum length of files and directories is raised to 193.
532 * if rockridge option is disabled, raised to 207.
534 unsigned int iso_level:3;
535 #define OPT_ISO_LEVEL_DEFAULT 1 /* ISO Level 1 */
538 * Usage : joliet[=long]
540 * : Do not generate Joliet Volume and Records.
542 * : Generates Joliet Volume and Directory Records.
543 * : [COMPAT: mkisofs -J/-joliet]
545 * : The joliet filenames are up to 103 Unicode
547 * : This option breaks the Joliet specification.
548 * : [COMPAT: mkisofs -J -joliet-long]
549 * Type : boolean/string
551 * COMPAT : mkisofs -J / -joliet-long
553 * Generates Joliet Volume and Directory Records.
555 unsigned int joliet:2;
556 #define OPT_JOLIET_DISABLE 0 /* Not generate Joliet Records. */
557 #define OPT_JOLIET_ENABLE 1 /* Generate Joliet Records. */
558 #define OPT_JOLIET_LONGNAME 2 /* Use long joliet filenames.*/
559 #define OPT_JOLIET_DEFAULT OPT_JOLIET_ENABLE
562 * Usage : !limit-depth
565 * : Violates the ISO9660 standard if disable.
566 * COMPAT : mkisofs -D/-disable-deep-relocation
568 * The number of levels in hierarchy cannot exceed eight.
570 unsigned int limit_depth:1;
571 #define OPT_LIMIT_DEPTH_DEFAULT 1 /* Enabled */
574 * Usage : !limit-dirs
577 * : Violates the ISO9660 standard if disable.
578 * COMPAT : mkisofs -no-limit-pathtables
580 * Limits the number of directories less than 65536 due
581 * to the size of the Parent Directory Number of Path
584 unsigned int limit_dirs:1;
585 #define OPT_LIMIT_DIRS_DEFAULT 1 /* Enabled */
591 * COMPAT : -pad/-no-pad
593 * Pads the end of the ISO image by null of 300Ki bytes.
596 #define OPT_PAD_DEFAULT 1 /* Enabled */
599 * Usage : publisher=<value>
600 * Type : string, max 128 bytes
601 * Default: Not specified
602 * COMPAT : mkisofs -publisher <value>
604 * Specifies Publisher Identifier.
605 * If the first byte is set to '_'(5F), the remaining
606 * bytes of this option shall specify an identifier
607 * for a file containing the identification of the user.
608 * This file shall be described in the Root Directory.
610 unsigned int publisher:1;
611 #define OPT_PUBLISHER_DEFAULT 0 /* Not specified */
612 #define PUBLISHER_IDENTIFIER_SIZE 128
617 * : disable to generate SUSP and RR records.
619 * : the same as 'rockridge=useful'.
621 * : generate SUSP and RR records.
622 * : [COMPAT: mkisofs -R]
623 * : rockridge=useful [DEFAULT]
624 * : generate SUSP and RR records.
625 * : [COMPAT: mkisofs -r]
626 * : NOTE Our rockridge=useful option does not set a zero
627 * : to uid and gid, you should use application
628 * : option such as --gid,--gname,--uid and --uname
629 * : badtar options instead.
630 * Type : boolean/string
631 * Default: Enabled as rockridge=useful
632 * COMPAT : mkisofs -r / -R
634 * Generates SUSP and RR records.
637 #define OPT_RR_DISABLED 0
638 #define OPT_RR_STRICT 1
639 #define OPT_RR_USEFUL 2
640 #define OPT_RR_DEFAULT OPT_RR_USEFUL
643 * Usage : volume-id=<value>
644 * Type : string, max 32 bytes
645 * Default: Not specified
646 * COMPAT : mkisofs -V <value>
648 * Specifies Volume Identifier.
650 unsigned int volume_id:1;
651 #define OPT_VOLUME_ID_DEFAULT 0 /* Use default identifier */
652 #define VOLUME_IDENTIFIER_SIZE 32
655 * Usage : !zisofs [DEFAULT]
656 * : Disable to generate RRIP 'ZF' extension.
658 * : Make files zisofs file and generate RRIP 'ZF'
659 * : extension. So you do not need mkzftree utility
660 * : for making zisofs.
661 * : When the file size is less than one Logical Block
662 * : size, that file will not zisofs'ed since it does
663 * : reduece an ISO-image size.
665 * : When you specify option 'boot=<boot-image>', that
666 * : 'boot-image' file won't be converted to zisofs file.
670 * Generates RRIP 'ZF' System Use Entry.
672 unsigned int zisofs:1;
673 #define OPT_ZISOFS_DISABLED 0
674 #define OPT_ZISOFS_DIRECT 1
675 #define OPT_ZISOFS_DEFAULT OPT_ZISOFS_DISABLED
680 /* The creation time of ISO image. */
682 /* A file stream of a temporary file, which file contents
683 * save to until ISO iamge can be created. */
686 struct isofile *cur_file;
687 struct isoent *cur_dirent;
688 struct archive_string cur_dirstr;
689 uint64_t bytes_remaining;
690 int need_multi_extent;
692 /* Temporary string buffer for Joliet extension. */
693 struct archive_string utf16be;
694 struct archive_string mbs;
696 struct archive_string_conv *sconv_to_utf16be;
697 struct archive_string_conv *sconv_from_utf16be;
699 /* A list of all of struct isofile entries. */
701 struct isofile *first;
702 struct isofile **last;
705 /* A list of struct isofile entries which have its
706 * contents and are not a directory, a hardlined file
707 * and a symlink file. */
709 struct isofile *first;
710 struct isofile **last;
713 /* Used for managing to find hardlinking files. */
714 struct archive_rb_tree hardlink_rbtree;
716 /* Used for making the Path Table Record. */
718 /* the root of entry tree. */
719 struct isoent *rootent;
727 struct isoent *first;
728 struct isoent **last;
729 struct isoent **sorted;
734 int path_table_block;
736 int location_type_L_path_table;
737 int location_type_M_path_table;
741 /* Used for making a Volume Descriptor. */
742 int volume_space_size;
743 int volume_sequence_number;
744 int total_file_block;
745 struct archive_string volume_identifier;
746 struct archive_string publisher_identifier;
747 struct archive_string data_preparer_identifier;
748 struct archive_string application_identifier;
749 struct archive_string copyright_file_identifier;
750 struct archive_string abstract_file_identifier;
751 struct archive_string bibliographic_file_identifier;
753 /* Used for making rockridge extensions. */
754 int location_rrip_er;
756 /* Used for making zisofs. */
761 unsigned char magic_buffer[64];
766 * Copy a compressed file to iso9660.zisofs.temp_fd
767 * and also copy a uncompressed file(original file) to
768 * iso9660.temp_fd . If the number of logical block
769 * of the compressed file is less than the number of
770 * logical block of the uncompressed file, use it and
771 * remove the copy of the uncompressed file.
772 * but if not, we use uncompressed file and remove
773 * the copy of the compressed file.
775 uint32_t *block_pointers;
776 size_t block_pointers_allocated;
777 int block_pointers_cnt;
778 int block_pointers_idx;
780 int64_t block_offset;
785 int compression_level;
789 struct isoent *directories_too_deep;
793 #define wb_buffmax() (LOGICAL_BLOCK_SIZE * 32)
794 #define wb_remaining(a) (((struct iso9660 *)(a)->format_data)->wbuff_remaining)
795 #define wb_offset(a) (((struct iso9660 *)(a)->format_data)->wbuff_offset \
796 + wb_buffmax() - wb_remaining(a))
797 unsigned char wbuff[LOGICAL_BLOCK_SIZE * 32];
798 size_t wbuff_remaining;
803 int64_t wbuff_offset;
804 int64_t wbuff_written;
807 /* 'El Torito' boot data. */
809 /* boot catalog file */
810 struct archive_string catalog_filename;
811 struct isoent *catalog;
812 /* boot image file */
813 struct archive_string boot_filename;
816 unsigned char platform_id;
817 #define BOOT_PLATFORM_X86 0
818 #define BOOT_PLATFORM_PPC 1
819 #define BOOT_PLATFORM_MAC 2
820 struct archive_string id;
821 unsigned char media_type;
822 #define BOOT_MEDIA_NO_EMULATION 0
823 #define BOOT_MEDIA_1_2M_DISKETTE 1
824 #define BOOT_MEDIA_1_44M_DISKETTE 2
825 #define BOOT_MEDIA_2_88M_DISKETTE 3
826 #define BOOT_MEDIA_HARD_DISK 4
827 unsigned char system_type;
828 uint16_t boot_load_seg;
829 uint16_t boot_load_size;
830 #define BOOT_LOAD_SIZE 4
833 struct iso_option opt;
837 * Types of Volume Descriptor
840 VDT_BOOT_RECORD=0, /* Boot Record Volume Descriptor */
841 VDT_PRIMARY=1, /* Primary Volume Descriptor */
842 VDT_SUPPLEMENTARY=2, /* Supplementary Volume Descriptor */
843 VDT_TERMINATOR=255 /* Volume Descriptor Set Terminator */
847 * Types of Directory Record
850 DIR_REC_VD, /* Stored in Volume Descriptor. */
851 DIR_REC_SELF, /* Stored as Current Directory. */
852 DIR_REC_PARENT, /* Stored as Parent Directory. */
853 DIR_REC_NORMAL, /* Stored as Child. */
857 * Kinds of Volume Descriptor Character
867 * IDentifier Resolver.
868 * Used for resolving duplicated filenames.
872 struct archive_rb_node rbnode;
873 /* Used in wait_list. */
874 struct idrent *wnext;
875 struct idrent *avail;
877 struct isoent *isoent;
883 struct archive_rb_tree rbtree;
886 struct idrent *first;
887 struct idrent **last;
904 static int iso9660_options(struct archive_write *,
905 const char *, const char *);
906 static int iso9660_write_header(struct archive_write *,
907 struct archive_entry *);
908 static ssize_t iso9660_write_data(struct archive_write *,
909 const void *, size_t);
910 static int iso9660_finish_entry(struct archive_write *);
911 static int iso9660_close(struct archive_write *);
912 static int iso9660_free(struct archive_write *);
914 static void get_system_identitier(char *, size_t);
915 static void set_str(unsigned char *, const char *, size_t, char,
917 static inline int joliet_allowed_char(unsigned char, unsigned char);
918 static int set_str_utf16be(struct archive_write *, unsigned char *,
919 const char *, size_t, uint16_t, enum vdc);
920 static int set_str_a_characters_bp(struct archive_write *,
921 unsigned char *, int, int, const char *, enum vdc);
922 static int set_str_d_characters_bp(struct archive_write *,
923 unsigned char *, int, int, const char *, enum vdc);
924 static void set_VD_bp(unsigned char *, enum VD_type, unsigned char);
925 static inline void set_unused_field_bp(unsigned char *, int, int);
927 static unsigned char *extra_open_record(unsigned char *, int,
928 struct isoent *, struct ctl_extr_rec *);
929 static void extra_close_record(struct ctl_extr_rec *, int);
930 static unsigned char * extra_next_record(struct ctl_extr_rec *, int);
931 static unsigned char *extra_get_record(struct isoent *, int *, int *, int *);
932 static void extra_tell_used_size(struct ctl_extr_rec *, int);
933 static int extra_setup_location(struct isoent *, int);
934 static int set_directory_record_rr(unsigned char *, int,
935 struct isoent *, struct iso9660 *, enum dir_rec_type);
936 static int set_directory_record(unsigned char *, size_t,
937 struct isoent *, struct iso9660 *, enum dir_rec_type,
939 static inline int get_dir_rec_size(struct iso9660 *, struct isoent *,
940 enum dir_rec_type, enum vdd_type);
941 static inline unsigned char *wb_buffptr(struct archive_write *);
942 static int wb_write_out(struct archive_write *);
943 static int wb_consume(struct archive_write *, size_t);
945 static int wb_set_offset(struct archive_write *, int64_t);
947 static int write_null(struct archive_write *, size_t);
948 static int write_VD_terminator(struct archive_write *);
949 static int set_file_identifier(unsigned char *, int, int, enum vdc,
950 struct archive_write *, struct vdd *,
951 struct archive_string *, const char *, int,
953 static int write_VD(struct archive_write *, struct vdd *);
954 static int write_VD_boot_record(struct archive_write *);
955 static int write_information_block(struct archive_write *);
956 static int write_path_table(struct archive_write *, int,
958 static int write_directory_descriptors(struct archive_write *,
960 static int write_file_descriptors(struct archive_write *);
961 static int write_rr_ER(struct archive_write *);
962 static void calculate_path_table_size(struct vdd *);
964 static void isofile_init_entry_list(struct iso9660 *);
965 static void isofile_add_entry(struct iso9660 *, struct isofile *);
966 static void isofile_free_all_entries(struct iso9660 *);
967 static void isofile_init_entry_data_file_list(struct iso9660 *);
968 static void isofile_add_data_file(struct iso9660 *, struct isofile *);
969 static struct isofile * isofile_new(struct archive_write *,
970 struct archive_entry *);
971 static void isofile_free(struct isofile *);
972 static int isofile_gen_utility_names(struct archive_write *,
974 static int isofile_register_hardlink(struct archive_write *,
976 static void isofile_connect_hardlink_files(struct iso9660 *);
977 static void isofile_init_hardlinks(struct iso9660 *);
978 static void isofile_free_hardlinks(struct iso9660 *);
980 static struct isoent *isoent_new(struct isofile *);
981 static int isoent_clone_tree(struct archive_write *,
982 struct isoent **, struct isoent *);
983 static void _isoent_free(struct isoent *isoent);
984 static void isoent_free_all(struct isoent *);
985 static struct isoent * isoent_create_virtual_dir(struct archive_write *,
986 struct iso9660 *, const char *);
987 static int isoent_cmp_node(const struct archive_rb_node *,
988 const struct archive_rb_node *);
989 static int isoent_cmp_key(const struct archive_rb_node *,
991 static int isoent_add_child_head(struct isoent *, struct isoent *);
992 static int isoent_add_child_tail(struct isoent *, struct isoent *);
993 static void isoent_remove_child(struct isoent *, struct isoent *);
994 static void isoent_setup_directory_location(struct iso9660 *,
996 static void isoent_setup_file_location(struct iso9660 *, int);
997 static int get_path_component(char *, int, const char *);
998 static int isoent_tree(struct archive_write *, struct isoent **);
999 static struct isoent *isoent_find_child(struct isoent *, const char *);
1000 static struct isoent *isoent_find_entry(struct isoent *, const char *);
1001 static void idr_relaxed_filenames(char *);
1002 static void idr_init(struct iso9660 *, struct vdd *, struct idr *);
1003 static void idr_cleanup(struct idr *);
1004 static int idr_ensure_poolsize(struct archive_write *, struct idr *,
1006 static int idr_start(struct archive_write *, struct idr *,
1007 int, int, int, int, const struct archive_rb_tree_ops *);
1008 static void idr_register(struct idr *, struct isoent *, int,
1010 static void idr_extend_identifier(struct idrent *, int, int);
1011 static void idr_resolve(struct idr *, void (*)(unsigned char *, int));
1012 static void idr_set_num(unsigned char *, int);
1013 static void idr_set_num_beutf16(unsigned char *, int);
1014 static int isoent_gen_iso9660_identifier(struct archive_write *,
1015 struct isoent *, struct idr *);
1016 static int isoent_gen_joliet_identifier(struct archive_write *,
1017 struct isoent *, struct idr *);
1018 static int isoent_cmp_iso9660_identifier(const struct isoent *,
1019 const struct isoent *);
1020 static int isoent_cmp_node_iso9660(const struct archive_rb_node *,
1021 const struct archive_rb_node *);
1022 static int isoent_cmp_key_iso9660(const struct archive_rb_node *,
1024 static int isoent_cmp_joliet_identifier(const struct isoent *,
1025 const struct isoent *);
1026 static int isoent_cmp_node_joliet(const struct archive_rb_node *,
1027 const struct archive_rb_node *);
1028 static int isoent_cmp_key_joliet(const struct archive_rb_node *,
1030 static inline void path_table_add_entry(struct path_table *, struct isoent *);
1031 static inline struct isoent * path_table_last_entry(struct path_table *);
1032 static int isoent_make_path_table(struct archive_write *);
1033 static int isoent_find_out_boot_file(struct archive_write *,
1035 static int isoent_create_boot_catalog(struct archive_write *,
1037 static size_t fd_boot_image_size(int);
1038 static int make_boot_catalog(struct archive_write *);
1039 static int setup_boot_information(struct archive_write *);
1041 static int zisofs_init(struct archive_write *, struct isofile *);
1042 static void zisofs_detect_magic(struct archive_write *,
1043 const void *, size_t);
1044 static int zisofs_write_to_temp(struct archive_write *,
1045 const void *, size_t);
1046 static int zisofs_finish_entry(struct archive_write *);
1047 static int zisofs_rewind_boot_file(struct archive_write *);
1048 static int zisofs_free(struct archive_write *);
1051 archive_write_set_format_iso9660(struct archive *_a)
1053 struct archive_write *a = (struct archive_write *)_a;
1054 struct iso9660 *iso9660;
1056 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
1057 ARCHIVE_STATE_NEW, "archive_write_set_format_iso9660");
1059 /* If another format was already registered, unregister it. */
1060 if (a->format_free != NULL)
1061 (a->format_free)(a);
1063 iso9660 = calloc(1, sizeof(*iso9660));
1064 if (iso9660 == NULL) {
1065 archive_set_error(&a->archive, ENOMEM,
1066 "Can't allocate iso9660 data");
1067 return (ARCHIVE_FATAL);
1069 iso9660->birth_time = 0;
1070 iso9660->temp_fd = -1;
1071 iso9660->cur_file = NULL;
1072 iso9660->primary.max_depth = 0;
1073 iso9660->primary.vdd_type = VDD_PRIMARY;
1074 iso9660->primary.pathtbl = NULL;
1075 iso9660->joliet.rootent = NULL;
1076 iso9660->joliet.max_depth = 0;
1077 iso9660->joliet.vdd_type = VDD_JOLIET;
1078 iso9660->joliet.pathtbl = NULL;
1079 isofile_init_entry_list(iso9660);
1080 isofile_init_entry_data_file_list(iso9660);
1081 isofile_init_hardlinks(iso9660);
1082 iso9660->directories_too_deep = NULL;
1083 iso9660->dircnt_max = 1;
1084 iso9660->wbuff_remaining = wb_buffmax();
1085 iso9660->wbuff_type = WB_TO_TEMP;
1086 iso9660->wbuff_offset = 0;
1087 iso9660->wbuff_written = 0;
1088 iso9660->wbuff_tail = 0;
1089 archive_string_init(&(iso9660->utf16be));
1090 archive_string_init(&(iso9660->mbs));
1093 * Init Identifiers used for PVD and SVD.
1095 archive_string_init(&(iso9660->volume_identifier));
1096 archive_strcpy(&(iso9660->volume_identifier), "CDROM");
1097 archive_string_init(&(iso9660->publisher_identifier));
1098 archive_string_init(&(iso9660->data_preparer_identifier));
1099 archive_string_init(&(iso9660->application_identifier));
1100 archive_strcpy(&(iso9660->application_identifier),
1101 archive_version_string());
1102 archive_string_init(&(iso9660->copyright_file_identifier));
1103 archive_string_init(&(iso9660->abstract_file_identifier));
1104 archive_string_init(&(iso9660->bibliographic_file_identifier));
1107 * Init El Torito bootable CD variables.
1109 archive_string_init(&(iso9660->el_torito.catalog_filename));
1110 iso9660->el_torito.catalog = NULL;
1111 /* Set default file name of boot catalog */
1112 archive_strcpy(&(iso9660->el_torito.catalog_filename),
1114 archive_string_init(&(iso9660->el_torito.boot_filename));
1115 iso9660->el_torito.boot = NULL;
1116 iso9660->el_torito.platform_id = BOOT_PLATFORM_X86;
1117 archive_string_init(&(iso9660->el_torito.id));
1118 iso9660->el_torito.boot_load_seg = 0;
1119 iso9660->el_torito.boot_load_size = BOOT_LOAD_SIZE;
1122 * Init zisofs variables.
1125 iso9660->zisofs.block_pointers = NULL;
1126 iso9660->zisofs.block_pointers_allocated = 0;
1127 iso9660->zisofs.stream_valid = 0;
1128 iso9660->zisofs.compression_level = 9;
1129 memset(&(iso9660->zisofs.stream), 0,
1130 sizeof(iso9660->zisofs.stream));
1134 * Set default value of iso9660 options.
1136 iso9660->opt.abstract_file = OPT_ABSTRACT_FILE_DEFAULT;
1137 iso9660->opt.application_id = OPT_APPLICATION_ID_DEFAULT;
1138 iso9660->opt.allow_vernum = OPT_ALLOW_VERNUM_DEFAULT;
1139 iso9660->opt.biblio_file = OPT_BIBLIO_FILE_DEFAULT;
1140 iso9660->opt.boot = OPT_BOOT_DEFAULT;
1141 iso9660->opt.boot_catalog = OPT_BOOT_CATALOG_DEFAULT;
1142 iso9660->opt.boot_info_table = OPT_BOOT_INFO_TABLE_DEFAULT;
1143 iso9660->opt.boot_load_seg = OPT_BOOT_LOAD_SEG_DEFAULT;
1144 iso9660->opt.boot_load_size = OPT_BOOT_LOAD_SIZE_DEFAULT;
1145 iso9660->opt.boot_type = OPT_BOOT_TYPE_DEFAULT;
1146 iso9660->opt.compression_level = OPT_COMPRESSION_LEVEL_DEFAULT;
1147 iso9660->opt.copyright_file = OPT_COPYRIGHT_FILE_DEFAULT;
1148 iso9660->opt.iso_level = OPT_ISO_LEVEL_DEFAULT;
1149 iso9660->opt.joliet = OPT_JOLIET_DEFAULT;
1150 iso9660->opt.limit_depth = OPT_LIMIT_DEPTH_DEFAULT;
1151 iso9660->opt.limit_dirs = OPT_LIMIT_DIRS_DEFAULT;
1152 iso9660->opt.pad = OPT_PAD_DEFAULT;
1153 iso9660->opt.publisher = OPT_PUBLISHER_DEFAULT;
1154 iso9660->opt.rr = OPT_RR_DEFAULT;
1155 iso9660->opt.volume_id = OPT_VOLUME_ID_DEFAULT;
1156 iso9660->opt.zisofs = OPT_ZISOFS_DEFAULT;
1158 /* Create the root directory. */
1159 iso9660->primary.rootent =
1160 isoent_create_virtual_dir(a, iso9660, "");
1161 if (iso9660->primary.rootent == NULL) {
1163 archive_set_error(&a->archive, ENOMEM,
1164 "Can't allocate memory");
1165 return (ARCHIVE_FATAL);
1167 iso9660->primary.rootent->parent = iso9660->primary.rootent;
1168 iso9660->cur_dirent = iso9660->primary.rootent;
1169 archive_string_init(&(iso9660->cur_dirstr));
1170 archive_string_ensure(&(iso9660->cur_dirstr), 1);
1171 iso9660->cur_dirstr.s[0] = 0;
1172 iso9660->sconv_to_utf16be = NULL;
1173 iso9660->sconv_from_utf16be = NULL;
1175 a->format_data = iso9660;
1176 a->format_name = "iso9660";
1177 a->format_options = iso9660_options;
1178 a->format_write_header = iso9660_write_header;
1179 a->format_write_data = iso9660_write_data;
1180 a->format_finish_entry = iso9660_finish_entry;
1181 a->format_close = iso9660_close;
1182 a->format_free = iso9660_free;
1183 a->archive.archive_format = ARCHIVE_FORMAT_ISO9660;
1184 a->archive.archive_format_name = "ISO9660";
1186 return (ARCHIVE_OK);
1190 get_str_opt(struct archive_write *a, struct archive_string *s,
1191 size_t maxsize, const char *key, const char *value)
1194 if (strlen(value) > maxsize) {
1195 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1196 "Value is longer than %zu characters "
1197 "for option ``%s''", maxsize, key);
1198 return (ARCHIVE_FATAL);
1200 archive_strcpy(s, value);
1201 return (ARCHIVE_OK);
1205 get_num_opt(struct archive_write *a, int *num, int high, int low,
1206 const char *key, const char *value)
1208 const char *p = value;
1213 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1214 "Invalid value(empty) for option ``%s''", key);
1215 return (ARCHIVE_FATAL);
1222 if (*p >= '0' && *p <= '9')
1223 data = data * 10 + *p - '0';
1225 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1226 "Invalid value for option ``%s''", key);
1227 return (ARCHIVE_FATAL);
1230 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1231 "Invalid value(over %d) for "
1232 "option ``%s''", high, key);
1233 return (ARCHIVE_FATAL);
1236 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1237 "Invalid value(under %d) for "
1238 "option ``%s''", low, key);
1239 return (ARCHIVE_FATAL);
1247 return (ARCHIVE_OK);
1251 iso9660_options(struct archive_write *a, const char *key, const char *value)
1253 struct iso9660 *iso9660 = a->format_data;
1259 if (strcmp(key, "abstract-file") == 0) {
1261 &(iso9660->abstract_file_identifier),
1262 ABSTRACT_FILE_SIZE, key, value);
1263 iso9660->opt.abstract_file = r == ARCHIVE_OK;
1266 if (strcmp(key, "application-id") == 0) {
1268 &(iso9660->application_identifier),
1269 APPLICATION_IDENTIFIER_SIZE, key, value);
1270 iso9660->opt.application_id = r == ARCHIVE_OK;
1273 if (strcmp(key, "allow-vernum") == 0) {
1274 iso9660->opt.allow_vernum = value != NULL;
1275 return (ARCHIVE_OK);
1279 if (strcmp(key, "biblio-file") == 0) {
1281 &(iso9660->bibliographic_file_identifier),
1282 BIBLIO_FILE_SIZE, key, value);
1283 iso9660->opt.biblio_file = r == ARCHIVE_OK;
1286 if (strcmp(key, "boot") == 0) {
1288 iso9660->opt.boot = 0;
1290 iso9660->opt.boot = 1;
1292 &(iso9660->el_torito.boot_filename),
1295 return (ARCHIVE_OK);
1297 if (strcmp(key, "boot-catalog") == 0) {
1299 &(iso9660->el_torito.catalog_filename),
1301 iso9660->opt.boot_catalog = r == ARCHIVE_OK;
1304 if (strcmp(key, "boot-info-table") == 0) {
1305 iso9660->opt.boot_info_table = value != NULL;
1306 return (ARCHIVE_OK);
1308 if (strcmp(key, "boot-load-seg") == 0) {
1311 iso9660->opt.boot_load_seg = 0;
1316 if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
1321 if (*p >= 'A' && *p <= 'F')
1322 seg += *p - 'A' + 0x0a;
1323 else if (*p >= 'a' && *p <= 'f')
1324 seg += *p - 'a' + 0x0a;
1325 else if (*p >= '0' && *p <= '9')
1330 archive_set_error(&a->archive,
1332 "Invalid value(over 0xffff) for "
1333 "option ``%s''", key);
1334 return (ARCHIVE_FATAL);
1338 iso9660->el_torito.boot_load_seg = (uint16_t)seg;
1339 iso9660->opt.boot_load_seg = 1;
1340 return (ARCHIVE_OK);
1342 if (strcmp(key, "boot-load-size") == 0) {
1344 r = get_num_opt(a, &num, 0xffff, 1, key, value);
1345 iso9660->opt.boot_load_size = r == ARCHIVE_OK;
1346 if (r != ARCHIVE_OK)
1347 return (ARCHIVE_FATAL);
1348 iso9660->el_torito.boot_load_size = (uint16_t)num;
1349 return (ARCHIVE_OK);
1351 if (strcmp(key, "boot-type") == 0) {
1354 if (strcmp(value, "no-emulation") == 0)
1355 iso9660->opt.boot_type = OPT_BOOT_TYPE_NO_EMU;
1356 else if (strcmp(value, "fd") == 0)
1357 iso9660->opt.boot_type = OPT_BOOT_TYPE_FD;
1358 else if (strcmp(value, "hard-disk") == 0)
1359 iso9660->opt.boot_type = OPT_BOOT_TYPE_HARD_DISK;
1362 return (ARCHIVE_OK);
1366 if (strcmp(key, "compression-level") == 0) {
1368 if (value == NULL ||
1369 !(value[0] >= '0' && value[0] <= '9') ||
1372 iso9660->zisofs.compression_level = value[0] - '0';
1373 iso9660->opt.compression_level = 1;
1374 return (ARCHIVE_OK);
1376 archive_set_error(&a->archive,
1379 "is not supported on this platform.", key);
1380 return (ARCHIVE_FATAL);
1383 if (strcmp(key, "copyright-file") == 0) {
1385 &(iso9660->copyright_file_identifier),
1386 COPYRIGHT_FILE_SIZE, key, value);
1387 iso9660->opt.copyright_file = r == ARCHIVE_OK;
1391 /* Specifies Volume creation date and time;
1392 * year(4),month(2),day(2),hour(2),minute(2),second(2).
1393 * e.g. "20090929033757"
1395 if (strcmp(key, "creation") == 0) {
1400 if (p == NULL || strlen(p) < 14)
1402 memset(&tm, 0, sizeof(tm));
1403 memcpy(buf, p, 4); buf[4] = '\0'; p += 4;
1404 tm.tm_year = strtol(buf, NULL, 10) - 1900;
1405 memcpy(buf, p, 2); buf[2] = '\0'; p += 2;
1406 tm.tm_mon = strtol(buf, NULL, 10) - 1;
1407 memcpy(buf, p, 2); buf[2] = '\0'; p += 2;
1408 tm.tm_mday = strtol(buf, NULL, 10);
1409 memcpy(buf, p, 2); buf[2] = '\0'; p += 2;
1410 tm.tm_hour = strtol(buf, NULL, 10);
1411 memcpy(buf, p, 2); buf[2] = '\0'; p += 2;
1412 tm.tm_min = strtol(buf, NULL, 10);
1413 memcpy(buf, p, 2); buf[2] = '\0';
1414 tm.tm_sec = strtol(buf, NULL, 10);
1415 iso9660->birth_time = mktime(&tm);
1416 return (ARCHIVE_OK);
1421 if (strcmp(key, "iso-level") == 0) {
1422 if (value != NULL && value[1] == '\0' &&
1423 (value[0] >= '1' && value[0] <= '4')) {
1424 iso9660->opt.iso_level = value[0]-'0';
1425 return (ARCHIVE_OK);
1431 if (strcmp(key, "joliet") == 0) {
1433 iso9660->opt.joliet = OPT_JOLIET_DISABLE;
1434 else if (strcmp(value, "1") == 0)
1435 iso9660->opt.joliet = OPT_JOLIET_ENABLE;
1436 else if (strcmp(value, "long") == 0)
1437 iso9660->opt.joliet = OPT_JOLIET_LONGNAME;
1440 return (ARCHIVE_OK);
1444 if (strcmp(key, "limit-depth") == 0) {
1445 iso9660->opt.limit_depth = value != NULL;
1446 return (ARCHIVE_OK);
1448 if (strcmp(key, "limit-dirs") == 0) {
1449 iso9660->opt.limit_dirs = value != NULL;
1450 return (ARCHIVE_OK);
1454 if (strcmp(key, "pad") == 0) {
1455 iso9660->opt.pad = value != NULL;
1456 return (ARCHIVE_OK);
1458 if (strcmp(key, "publisher") == 0) {
1460 &(iso9660->publisher_identifier),
1461 PUBLISHER_IDENTIFIER_SIZE, key, value);
1462 iso9660->opt.publisher = r == ARCHIVE_OK;
1467 if (strcmp(key, "rockridge") == 0 ||
1468 strcmp(key, "Rockridge") == 0) {
1470 iso9660->opt.rr = OPT_RR_DISABLED;
1471 else if (strcmp(value, "1") == 0)
1472 iso9660->opt.rr = OPT_RR_USEFUL;
1473 else if (strcmp(value, "strict") == 0)
1474 iso9660->opt.rr = OPT_RR_STRICT;
1475 else if (strcmp(value, "useful") == 0)
1476 iso9660->opt.rr = OPT_RR_USEFUL;
1479 return (ARCHIVE_OK);
1483 if (strcmp(key, "volume-id") == 0) {
1484 r = get_str_opt(a, &(iso9660->volume_identifier),
1485 VOLUME_IDENTIFIER_SIZE, key, value);
1486 iso9660->opt.volume_id = r == ARCHIVE_OK;
1491 if (strcmp(key, "zisofs") == 0) {
1493 iso9660->opt.zisofs = OPT_ZISOFS_DISABLED;
1496 iso9660->opt.zisofs = OPT_ZISOFS_DIRECT;
1498 archive_set_error(&a->archive,
1501 "is not supported on this platform.");
1502 return (ARCHIVE_FATAL);
1505 return (ARCHIVE_OK);
1510 /* Note: The "warn" return is just to inform the options
1511 * supervisor that we didn't handle it. It will generate
1512 * a suitable error if no one used this option. */
1513 return (ARCHIVE_WARN);
1516 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1517 "Invalid value for option ``%s''", key);
1518 return (ARCHIVE_FAILED);
1522 iso9660_write_header(struct archive_write *a, struct archive_entry *entry)
1524 struct iso9660 *iso9660;
1525 struct isofile *file;
1526 struct isoent *isoent;
1527 int r, ret = ARCHIVE_OK;
1529 iso9660 = a->format_data;
1531 iso9660->cur_file = NULL;
1532 iso9660->bytes_remaining = 0;
1533 iso9660->need_multi_extent = 0;
1534 if (archive_entry_filetype(entry) == AE_IFLNK
1535 && iso9660->opt.rr == OPT_RR_DISABLED) {
1536 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1537 "Ignore symlink file.");
1538 iso9660->cur_file = NULL;
1539 return (ARCHIVE_WARN);
1541 if (archive_entry_filetype(entry) == AE_IFREG &&
1542 archive_entry_size(entry) >= MULTI_EXTENT_SIZE) {
1543 if (iso9660->opt.iso_level < 3) {
1544 archive_set_error(&a->archive,
1546 "Ignore over %lld bytes file. "
1547 "This file too large.",
1549 iso9660->cur_file = NULL;
1550 return (ARCHIVE_WARN);
1552 iso9660->need_multi_extent = 1;
1555 file = isofile_new(a, entry);
1557 archive_set_error(&a->archive, ENOMEM,
1558 "Can't allocate data");
1559 return (ARCHIVE_FATAL);
1561 r = isofile_gen_utility_names(a, file);
1562 if (r < ARCHIVE_WARN) {
1570 * Ignore a path which looks like the top of directory name
1571 * since we have already made the root directory of an ISO image.
1573 if (archive_strlen(&(file->parentdir)) == 0 &&
1574 archive_strlen(&(file->basename)) == 0) {
1579 isofile_add_entry(iso9660, file);
1580 isoent = isoent_new(file);
1581 if (isoent == NULL) {
1582 archive_set_error(&a->archive, ENOMEM,
1583 "Can't allocate data");
1584 return (ARCHIVE_FATAL);
1586 if (isoent->file->dircnt > iso9660->dircnt_max)
1587 iso9660->dircnt_max = isoent->file->dircnt;
1589 /* Add the current file into tree */
1590 r = isoent_tree(a, &isoent);
1591 if (r != ARCHIVE_OK)
1594 /* If there is the same file in tree and
1595 * the current file is older than the file in tree.
1596 * So we don't need the current file data anymore. */
1597 if (isoent->file != file)
1598 return (ARCHIVE_OK);
1600 /* Non regular files contents are unneeded to be saved to
1601 * temporary files. */
1602 if (archive_entry_filetype(file->entry) != AE_IFREG)
1606 * Set the current file to cur_file to read its contents.
1608 iso9660->cur_file = file;
1610 if (archive_entry_nlink(file->entry) > 1) {
1611 r = isofile_register_hardlink(a, file);
1612 if (r != ARCHIVE_OK)
1613 return (ARCHIVE_FATAL);
1617 * Prepare to save the contents of the file.
1619 if (iso9660->temp_fd < 0) {
1620 iso9660->temp_fd = __archive_mktemp(NULL);
1621 if (iso9660->temp_fd < 0) {
1622 archive_set_error(&a->archive, errno,
1623 "Couldn't create temporary file");
1624 return (ARCHIVE_FATAL);
1628 /* Save an offset of current file in temporary file. */
1629 file->content.offset_of_temp = wb_offset(a);
1630 file->cur_content = &(file->content);
1631 r = zisofs_init(a, file);
1634 iso9660->bytes_remaining = archive_entry_size(file->entry);
1640 write_to_temp(struct archive_write *a, const void *buff, size_t s)
1642 struct iso9660 *iso9660 = a->format_data;
1644 const unsigned char *b;
1646 b = (const unsigned char *)buff;
1648 written = write(iso9660->temp_fd, b, s);
1650 archive_set_error(&a->archive, errno,
1651 "Can't write to temporary file");
1652 return (ARCHIVE_FATAL);
1657 return (ARCHIVE_OK);
1661 wb_write_to_temp(struct archive_write *a, const void *buff, size_t s)
1663 const char *xp = buff;
1667 * If a written data size is big enough to use system-call
1668 * and there is no waiting data, this calls write_to_temp() in
1669 * order to reduce a extra memory copy.
1671 if (wb_remaining(a) == wb_buffmax() && s > (1024 * 16)) {
1672 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
1673 xs = s % LOGICAL_BLOCK_SIZE;
1674 iso9660->wbuff_offset += s - xs;
1675 if (write_to_temp(a, buff, s - xs) != ARCHIVE_OK)
1676 return (ARCHIVE_FATAL);
1678 return (ARCHIVE_OK);
1684 if (size > wb_remaining(a))
1685 size = wb_remaining(a);
1686 memcpy(wb_buffptr(a), xp, size);
1687 if (wb_consume(a, size) != ARCHIVE_OK)
1688 return (ARCHIVE_FATAL);
1692 return (ARCHIVE_OK);
1696 wb_write_padding_to_temp(struct archive_write *a, int64_t csize)
1701 ns = csize % LOGICAL_BLOCK_SIZE;
1703 ret = write_null(a, LOGICAL_BLOCK_SIZE - ns);
1710 write_iso9660_data(struct archive_write *a, const void *buff, size_t s)
1712 struct iso9660 *iso9660 = a->format_data;
1715 if (iso9660->temp_fd < 0) {
1716 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1717 "Couldn't create temporary file");
1718 return (ARCHIVE_FATAL);
1722 if (iso9660->need_multi_extent &&
1723 (iso9660->cur_file->cur_content->size + ws) >=
1724 (MULTI_EXTENT_SIZE - LOGICAL_BLOCK_SIZE)) {
1725 struct content *con;
1728 ts = MULTI_EXTENT_SIZE - LOGICAL_BLOCK_SIZE -
1729 iso9660->cur_file->cur_content->size;
1731 if (iso9660->zisofs.detect_magic)
1732 zisofs_detect_magic(a, buff, ts);
1734 if (iso9660->zisofs.making) {
1735 if (zisofs_write_to_temp(a, buff, ts) != ARCHIVE_OK)
1736 return (ARCHIVE_FATAL);
1738 if (wb_write_to_temp(a, buff, ts) != ARCHIVE_OK)
1739 return (ARCHIVE_FATAL);
1740 iso9660->cur_file->cur_content->size += ts;
1743 /* Write padding. */
1744 if (wb_write_padding_to_temp(a,
1745 iso9660->cur_file->cur_content->size) != ARCHIVE_OK)
1746 return (ARCHIVE_FATAL);
1748 /* Compute the logical block number. */
1749 iso9660->cur_file->cur_content->blocks =
1750 (iso9660->cur_file->cur_content->size
1751 + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS;
1757 buff = (const void *)(((const unsigned char *)buff) + ts);
1758 /* Make a content for next extent. */
1759 con = calloc(1, sizeof(*con));
1761 archive_set_error(&a->archive, ENOMEM,
1762 "Can't allocate content data");
1763 return (ARCHIVE_FATAL);
1765 con->offset_of_temp = wb_offset(a);
1766 iso9660->cur_file->cur_content->next = con;
1767 iso9660->cur_file->cur_content = con;
1769 iso9660->zisofs.block_offset = 0;
1773 if (iso9660->zisofs.detect_magic)
1774 zisofs_detect_magic(a, buff, ws);
1776 if (iso9660->zisofs.making) {
1777 if (zisofs_write_to_temp(a, buff, ws) != ARCHIVE_OK)
1778 return (ARCHIVE_FATAL);
1780 if (wb_write_to_temp(a, buff, ws) != ARCHIVE_OK)
1781 return (ARCHIVE_FATAL);
1782 iso9660->cur_file->cur_content->size += ws;
1789 iso9660_write_data(struct archive_write *a, const void *buff, size_t s)
1791 struct iso9660 *iso9660 = a->format_data;
1794 if (iso9660->cur_file == NULL)
1796 if (archive_entry_filetype(iso9660->cur_file->entry) != AE_IFREG)
1798 if (s > iso9660->bytes_remaining)
1799 s = iso9660->bytes_remaining;
1803 r = write_iso9660_data(a, buff, s);
1805 iso9660->bytes_remaining -= r;
1810 iso9660_finish_entry(struct archive_write *a)
1812 struct iso9660 *iso9660 = a->format_data;
1814 if (iso9660->cur_file == NULL)
1815 return (ARCHIVE_OK);
1816 if (archive_entry_filetype(iso9660->cur_file->entry) != AE_IFREG)
1817 return (ARCHIVE_OK);
1818 if (iso9660->cur_file->content.size == 0)
1819 return (ARCHIVE_OK);
1821 /* If there are unwritten data, write null data instead. */
1822 while (iso9660->bytes_remaining > 0) {
1825 s = (iso9660->bytes_remaining > a->null_length)?
1826 a->null_length: (size_t)iso9660->bytes_remaining;
1827 if (write_iso9660_data(a, a->nulls, s) < 0)
1828 return (ARCHIVE_FATAL);
1829 iso9660->bytes_remaining -= s;
1832 if (iso9660->zisofs.making && zisofs_finish_entry(a) != ARCHIVE_OK)
1833 return (ARCHIVE_FATAL);
1835 /* Write padding. */
1836 if (wb_write_padding_to_temp(a, iso9660->cur_file->cur_content->size)
1838 return (ARCHIVE_FATAL);
1840 /* Compute the logical block number. */
1841 iso9660->cur_file->cur_content->blocks =
1842 (iso9660->cur_file->cur_content->size
1843 + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS;
1845 /* Add the current file to data file list. */
1846 isofile_add_data_file(iso9660, iso9660->cur_file);
1848 return (ARCHIVE_OK);
1852 iso9660_close(struct archive_write *a)
1854 struct iso9660 *iso9660;
1857 iso9660 = a->format_data;
1860 * Write remaining data out to the temporary file.
1862 if (wb_remaining(a) > 0) {
1863 ret = wb_write_out(a);
1872 if (iso9660->birth_time == 0)
1874 time(&(iso9660->birth_time));
1877 * Prepare a bootable ISO image.
1879 if (iso9660->opt.boot) {
1880 /* Find out the boot file entry. */
1881 ret = isoent_find_out_boot_file(a, iso9660->primary.rootent);
1884 /* Reconvert the boot file from zisofs'ed form to
1886 ret = zisofs_rewind_boot_file(a);
1889 /* Write remaining data out to the temporary file. */
1890 if (wb_remaining(a) > 0) {
1891 ret = wb_write_out(a);
1895 /* Create the boot catalog. */
1896 ret = isoent_create_boot_catalog(a, iso9660->primary.rootent);
1902 * Prepare joliet extensions.
1904 if (iso9660->opt.joliet) {
1905 /* Make a new tree for joliet. */
1906 ret = isoent_clone_tree(a, &(iso9660->joliet.rootent),
1907 iso9660->primary.rootent);
1910 /* Make sure we have UTF-16BE convertors.
1911 * if there is no file entry, convertors are still
1913 if (iso9660->sconv_to_utf16be == NULL) {
1914 iso9660->sconv_to_utf16be =
1915 archive_string_conversion_to_charset(
1916 &(a->archive), "UTF-16BE", 1);
1917 if (iso9660->sconv_to_utf16be == NULL)
1918 /* Couldn't allocate memory */
1919 return (ARCHIVE_FATAL);
1920 iso9660->sconv_from_utf16be =
1921 archive_string_conversion_from_charset(
1922 &(a->archive), "UTF-16BE", 1);
1923 if (iso9660->sconv_from_utf16be == NULL)
1924 /* Couldn't allocate memory */
1925 return (ARCHIVE_FATAL);
1932 ret = isoent_make_path_table(a);
1937 * Calculate a total volume size and setup all locations of
1938 * contents of an iso9660 image.
1940 blocks = SYSTEM_AREA_BLOCK
1941 + PRIMARY_VOLUME_DESCRIPTOR_BLOCK
1942 + VOLUME_DESCRIPTOR_SET_TERMINATOR_BLOCK
1943 + NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK;
1944 if (iso9660->opt.boot)
1945 blocks += BOOT_RECORD_DESCRIPTOR_BLOCK;
1946 if (iso9660->opt.joliet)
1947 blocks += SUPPLEMENTARY_VOLUME_DESCRIPTOR_BLOCK;
1948 if (iso9660->opt.iso_level == 4)
1949 blocks += SUPPLEMENTARY_VOLUME_DESCRIPTOR_BLOCK;
1951 /* Setup the locations of Path Table. */
1952 iso9660->primary.location_type_L_path_table = blocks;
1953 blocks += iso9660->primary.path_table_block;
1954 iso9660->primary.location_type_M_path_table = blocks;
1955 blocks += iso9660->primary.path_table_block;
1956 if (iso9660->opt.joliet) {
1957 iso9660->joliet.location_type_L_path_table = blocks;
1958 blocks += iso9660->joliet.path_table_block;
1959 iso9660->joliet.location_type_M_path_table = blocks;
1960 blocks += iso9660->joliet.path_table_block;
1963 /* Setup the locations of directories. */
1964 isoent_setup_directory_location(iso9660, blocks,
1965 &(iso9660->primary));
1966 blocks += iso9660->primary.total_dir_block;
1967 if (iso9660->opt.joliet) {
1968 isoent_setup_directory_location(iso9660, blocks,
1969 &(iso9660->joliet));
1970 blocks += iso9660->joliet.total_dir_block;
1973 if (iso9660->opt.rr) {
1974 iso9660->location_rrip_er = blocks;
1975 blocks += RRIP_ER_BLOCK;
1978 /* Setup the locations of all file contents. */
1979 isoent_setup_file_location(iso9660, blocks);
1980 blocks += iso9660->total_file_block;
1981 if (iso9660->opt.boot && iso9660->opt.boot_info_table) {
1982 ret = setup_boot_information(a);
1987 /* Now we have a total volume size. */
1988 iso9660->volume_space_size = blocks;
1989 if (iso9660->opt.pad)
1990 iso9660->volume_space_size += PADDING_BLOCK;
1991 iso9660->volume_sequence_number = 1;
1995 * Write an ISO 9660 image.
1998 /* Switc to start using wbuff as file buffer. */
1999 iso9660->wbuff_remaining = wb_buffmax();
2000 iso9660->wbuff_type = WB_TO_STREAM;
2001 iso9660->wbuff_offset = 0;
2002 iso9660->wbuff_written = 0;
2003 iso9660->wbuff_tail = 0;
2005 /* Write The System Area */
2006 ret = write_null(a, SYSTEM_AREA_BLOCK * LOGICAL_BLOCK_SIZE);
2007 if (ret != ARCHIVE_OK)
2008 return (ARCHIVE_FATAL);
2010 /* Write Primary Volume Descriptor */
2011 ret = write_VD(a, &(iso9660->primary));
2012 if (ret != ARCHIVE_OK)
2013 return (ARCHIVE_FATAL);
2015 if (iso9660->opt.boot) {
2016 /* Write Boot Record Volume Descriptor */
2017 ret = write_VD_boot_record(a);
2018 if (ret != ARCHIVE_OK)
2019 return (ARCHIVE_FATAL);
2022 if (iso9660->opt.iso_level == 4) {
2023 /* Write Enhanced Volume Descriptor */
2024 iso9660->primary.vdd_type = VDD_ENHANCED;
2025 ret = write_VD(a, &(iso9660->primary));
2026 iso9660->primary.vdd_type = VDD_PRIMARY;
2027 if (ret != ARCHIVE_OK)
2028 return (ARCHIVE_FATAL);
2031 if (iso9660->opt.joliet) {
2032 ret = write_VD(a, &(iso9660->joliet));
2033 if (ret != ARCHIVE_OK)
2034 return (ARCHIVE_FATAL);
2037 /* Write Volume Descriptor Set Terminator */
2038 ret = write_VD_terminator(a);
2039 if (ret != ARCHIVE_OK)
2040 return (ARCHIVE_FATAL);
2042 /* Write Non-ISO File System Information */
2043 ret = write_information_block(a);
2044 if (ret != ARCHIVE_OK)
2045 return (ARCHIVE_FATAL);
2047 /* Write Type L Path Table */
2048 ret = write_path_table(a, 0, &(iso9660->primary));
2049 if (ret != ARCHIVE_OK)
2050 return (ARCHIVE_FATAL);
2052 /* Write Type M Path Table */
2053 ret = write_path_table(a, 1, &(iso9660->primary));
2054 if (ret != ARCHIVE_OK)
2055 return (ARCHIVE_FATAL);
2057 if (iso9660->opt.joliet) {
2058 /* Write Type L Path Table */
2059 ret = write_path_table(a, 0, &(iso9660->joliet));
2060 if (ret != ARCHIVE_OK)
2061 return (ARCHIVE_FATAL);
2063 /* Write Type M Path Table */
2064 ret = write_path_table(a, 1, &(iso9660->joliet));
2065 if (ret != ARCHIVE_OK)
2066 return (ARCHIVE_FATAL);
2069 /* Write Directory Descriptors */
2070 ret = write_directory_descriptors(a, &(iso9660->primary));
2071 if (ret != ARCHIVE_OK)
2072 return (ARCHIVE_FATAL);
2074 if (iso9660->opt.joliet) {
2075 ret = write_directory_descriptors(a, &(iso9660->joliet));
2076 if (ret != ARCHIVE_OK)
2077 return (ARCHIVE_FATAL);
2080 if (iso9660->opt.rr) {
2081 /* Write Rockridge ER(Extensions Reference) */
2082 ret = write_rr_ER(a);
2083 if (ret != ARCHIVE_OK)
2084 return (ARCHIVE_FATAL);
2087 /* Write File Descriptors */
2088 ret = write_file_descriptors(a);
2089 if (ret != ARCHIVE_OK)
2090 return (ARCHIVE_FATAL);
2093 if (iso9660->opt.pad) {
2094 ret = write_null(a, PADDING_BLOCK * LOGICAL_BLOCK_SIZE);
2095 if (ret != ARCHIVE_OK)
2096 return (ARCHIVE_FATAL);
2099 if (iso9660->directories_too_deep != NULL) {
2100 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2101 "%s: Directories too deep.",
2102 archive_entry_pathname(
2103 iso9660->directories_too_deep->file->entry));
2104 return (ARCHIVE_WARN);
2107 /* Write remaining data out. */
2108 ret = wb_write_out(a);
2114 iso9660_free(struct archive_write *a)
2116 struct iso9660 *iso9660;
2119 iso9660 = a->format_data;
2121 /* Close the temporary file. */
2122 if (iso9660->temp_fd >= 0)
2123 close(iso9660->temp_fd);
2125 /* Free some stuff for zisofs operations. */
2126 ret = zisofs_free(a);
2128 /* Remove directory entries in tree which includes file entries. */
2129 isoent_free_all(iso9660->primary.rootent);
2130 for (i = 0; i < iso9660->primary.max_depth; i++)
2131 free(iso9660->primary.pathtbl[i].sorted);
2132 free(iso9660->primary.pathtbl);
2134 if (iso9660->opt.joliet) {
2135 isoent_free_all(iso9660->joliet.rootent);
2136 for (i = 0; i < iso9660->joliet.max_depth; i++)
2137 free(iso9660->joliet.pathtbl[i].sorted);
2138 free(iso9660->joliet.pathtbl);
2141 /* Remove isofile entries. */
2142 isofile_free_all_entries(iso9660);
2143 isofile_free_hardlinks(iso9660);
2145 archive_string_free(&(iso9660->cur_dirstr));
2146 archive_string_free(&(iso9660->volume_identifier));
2147 archive_string_free(&(iso9660->publisher_identifier));
2148 archive_string_free(&(iso9660->data_preparer_identifier));
2149 archive_string_free(&(iso9660->application_identifier));
2150 archive_string_free(&(iso9660->copyright_file_identifier));
2151 archive_string_free(&(iso9660->abstract_file_identifier));
2152 archive_string_free(&(iso9660->bibliographic_file_identifier));
2153 archive_string_free(&(iso9660->el_torito.catalog_filename));
2154 archive_string_free(&(iso9660->el_torito.boot_filename));
2155 archive_string_free(&(iso9660->el_torito.id));
2156 archive_string_free(&(iso9660->utf16be));
2157 archive_string_free(&(iso9660->mbs));
2160 a->format_data = NULL;
2166 * Get the System Identifier
2169 get_system_identitier(char *system_id, size_t size)
2171 #if defined(HAVE_SYS_UTSNAME_H)
2175 strncpy(system_id, u.sysname, size-1);
2176 system_id[size-1] = '\0';
2177 #elif defined(_WIN32) && !defined(__CYGWIN__)
2178 strncpy(system_id, "Windows", size-1);
2179 system_id[size-1] = '\0';
2181 #error no way to get the system identifier on your platform.
2186 set_str(unsigned char *p, const char *s, size_t l, char f, const char *map)
2192 while ((c = *s++) != 0 && l > 0) {
2193 if (c >= 0x80 || map[c] == 0)
2195 /* illegal character */
2196 if (c >= 'a' && c <= 'z') {
2197 /* convert c from a-z to A-Z */
2205 /* If l isn't zero, fill p buffer by the character
2206 * which indicated by f. */
2212 joliet_allowed_char(unsigned char high, unsigned char low)
2214 int utf16 = (high << 8) | low;
2216 if (utf16 <= 0x001F)
2220 case 0x002A: /* '*' */
2221 case 0x002F: /* '/' */
2222 case 0x003A: /* ':' */
2223 case 0x003B: /* ';' */
2224 case 0x003F: /* '?' */
2225 case 0x005C: /* '\' */
2226 return (0);/* Not allowed. */
2232 set_str_utf16be(struct archive_write *a, unsigned char *p, const char *s,
2233 size_t l, uint16_t uf, enum vdc vdc)
2245 if (vdc == VDC_UCS2) {
2246 struct iso9660 *iso9660 = a->format_data;
2247 if (archive_strncpy_in_locale(&iso9660->utf16be, s, strlen(s),
2248 iso9660->sconv_to_utf16be) != 0 && errno == ENOMEM) {
2249 archive_set_error(&a->archive, ENOMEM,
2250 "Can't allocate memory for UTF-16BE");
2251 return (ARCHIVE_FATAL);
2253 size = iso9660->utf16be.length;
2256 memcpy(p, iso9660->utf16be.s, size);
2258 const uint16_t *u16 = (const uint16_t *)s;
2267 for (i = 0; i < size; i += 2, p += 2) {
2268 if (!joliet_allowed_char(p[0], p[1]))
2269 archive_be16enc(p, 0x005F);/* '_' */
2273 archive_be16enc(p, uf);
2279 return (ARCHIVE_OK);
2282 static const char a_characters_map[0x80] = {
2283 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
2284 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
2285 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
2286 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20-2F */
2287 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30-3F */
2288 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
2289 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
2290 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 60-6F */
2291 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 70-7F */
2294 static const char a1_characters_map[0x80] = {
2295 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
2296 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
2297 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
2298 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20-2F */
2299 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30-3F */
2300 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
2301 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
2302 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60-6F */
2303 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,/* 70-7F */
2306 static const char d_characters_map[0x80] = {
2307 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
2308 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
2309 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
2310 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 20-2F */
2311 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,/* 30-3F */
2312 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
2313 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
2314 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 60-6F */
2315 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 70-7F */
2318 static const char d1_characters_map[0x80] = {
2319 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
2320 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
2321 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
2322 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 20-2F */
2323 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,/* 30-3F */
2324 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
2325 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
2326 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60-6F */
2327 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,/* 70-7F */
2331 set_str_a_characters_bp(struct archive_write *a, unsigned char *bp,
2332 int from, int to, const char *s, enum vdc vdc)
2338 set_str(bp+from, s, to - from + 1, 0x20,
2343 set_str(bp+from, s, to - from + 1, 0x20,
2348 case VDC_UCS2_DIRECT:
2349 r = set_str_utf16be(a, bp+from, s, to - from + 1,
2359 set_str_d_characters_bp(struct archive_write *a, unsigned char *bp,
2360 int from, int to, const char *s, enum vdc vdc)
2366 set_str(bp+from, s, to - from + 1, 0x20,
2371 set_str(bp+from, s, to - from + 1, 0x20,
2376 case VDC_UCS2_DIRECT:
2377 r = set_str_utf16be(a, bp+from, s, to - from + 1,
2387 set_VD_bp(unsigned char *bp, enum VD_type type, unsigned char ver)
2390 /* Volume Descriptor Type */
2391 bp[1] = (unsigned char)type;
2392 /* Standard Identifier */
2393 memcpy(bp + 2, "CD001", 5);
2394 /* Volume Descriptor Version */
2399 set_unused_field_bp(unsigned char *bp, int from, int to)
2401 memset(bp + from, 0, to - from + 1);
2405 * 8-bit unsigned numerical values.
2406 * ISO9660 Standard 7.1.1
2409 set_num_711(unsigned char *p, unsigned char value)
2415 * 8-bit signed numerical values.
2416 * ISO9660 Standard 7.1.2
2419 set_num_712(unsigned char *p, char value)
2421 *((char *)p) = value;
2425 * Least significant byte first.
2426 * ISO9660 Standard 7.2.1
2429 set_num_721(unsigned char *p, uint16_t value)
2431 archive_le16enc(p, value);
2435 * Most significant byte first.
2436 * ISO9660 Standard 7.2.2
2439 set_num_722(unsigned char *p, uint16_t value)
2441 archive_be16enc(p, value);
2446 * ISO9660 Standard 7.2.3
2449 set_num_723(unsigned char *p, uint16_t value)
2451 archive_le16enc(p, value);
2452 archive_be16enc(p+2, value);
2456 * Least significant byte first.
2457 * ISO9660 Standard 7.3.1
2460 set_num_731(unsigned char *p, uint32_t value)
2462 archive_le32enc(p, value);
2466 * Most significant byte first.
2467 * ISO9660 Standard 7.3.2
2470 set_num_732(unsigned char *p, uint32_t value)
2472 archive_be32enc(p, value);
2477 * ISO9660 Standard 7.3.3
2480 set_num_733(unsigned char *p, uint32_t value)
2482 archive_le32enc(p, value);
2483 archive_be32enc(p+4, value);
2487 set_digit(unsigned char *p, size_t s, int value)
2491 p[s] = '0' + (value % 10);
2496 #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
2497 #define get_gmoffset(tm) ((tm)->tm_gmtoff)
2498 #elif defined(HAVE_STRUCT_TM___TM_GMTOFF)
2499 #define get_gmoffset(tm) ((tm)->__tm_gmtoff)
2502 get_gmoffset(struct tm *tm)
2506 #if defined(HAVE__GET_TIMEZONE)
2507 _get_timezone(&offset);
2508 #elif defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
2521 get_tmfromtime(struct tm *tm, time_t *t)
2523 #if HAVE_LOCALTIME_R
2526 #elif HAVE__LOCALTIME64_S
2527 _localtime64_s(tm, t);
2529 memcpy(tm, localtime(t), sizeof(*tm));
2534 * Date and Time Format.
2535 * ISO9660 Standard 8.4.26.1
2538 set_date_time(unsigned char *p, time_t t)
2542 get_tmfromtime(&tm, &t);
2543 set_digit(p, 4, tm.tm_year + 1900);
2544 set_digit(p+4, 2, tm.tm_mon + 1);
2545 set_digit(p+6, 2, tm.tm_mday);
2546 set_digit(p+8, 2, tm.tm_hour);
2547 set_digit(p+10, 2, tm.tm_min);
2548 set_digit(p+12, 2, tm.tm_sec);
2549 set_digit(p+14, 2, 0);
2550 set_num_712(p+16, get_gmoffset(&tm)/(60*15));
2554 set_date_time_null(unsigned char *p)
2561 set_time_915(unsigned char *p, time_t t)
2565 get_tmfromtime(&tm, &t);
2566 set_num_711(p+0, tm.tm_year);
2567 set_num_711(p+1, tm.tm_mon+1);
2568 set_num_711(p+2, tm.tm_mday);
2569 set_num_711(p+3, tm.tm_hour);
2570 set_num_711(p+4, tm.tm_min);
2571 set_num_711(p+5, tm.tm_sec);
2572 set_num_712(p+6, get_gmoffset(&tm)/(60*15));
2577 * Write SUSP "CE" System Use Entry.
2580 set_SUSP_CE(unsigned char *p, int location, int offset, int size)
2582 unsigned char *bp = p -1;
2583 /* Extend the System Use Area
2586 * +----+----+----+----+-----------+-----------+
2587 * | 'C'| 'E'| 1C | 01 | LOCATION1 | LOCATION2 |
2588 * +----+----+----+----+-----------+-----------+
2594 * LOCATION1 : Location of Continuation of System Use Area.
2595 * LOCATION2 : Offset to Start of Continuation.
2596 * LOCATION3 : Length of the Continuation.
2601 bp[3] = RR_CE_SIZE; /* length */
2602 bp[4] = 1; /* version */
2603 set_num_733(bp+5, location);
2604 set_num_733(bp+13, offset);
2605 set_num_733(bp+21, size);
2606 return (RR_CE_SIZE);
2610 * The functions, which names are beginning with extra_, are used to
2611 * control extra records.
2612 * The maximum size of a Directory Record is 254. When a filename is
2613 * very long, all of RRIP data of a file won't stored to the Directory
2614 * Record and so remaining RRIP data store to an extra record instead.
2616 static unsigned char *
2617 extra_open_record(unsigned char *bp, int dr_len, struct isoent *isoent,
2618 struct ctl_extr_rec *ctl)
2624 ctl->isoent = isoent;
2626 ctl->cur_len = ctl->dr_len = dr_len;
2627 ctl->limit = DR_LIMIT;
2633 extra_close_record(struct ctl_extr_rec *ctl, int ce_size)
2638 extra_tell_used_size(ctl, ce_size);
2640 if (ctl->cur_len & 0x01) {
2642 if (ctl->bp != NULL)
2643 ctl->bp[ctl->cur_len] = 0;
2646 if (ctl->use_extr) {
2647 if (ctl->ce_ptr != NULL)
2648 set_SUSP_CE(ctl->ce_ptr, ctl->extr_loc,
2649 ctl->extr_off, ctl->cur_len - padding);
2651 ctl->dr_len = ctl->cur_len;
2654 #define extra_space(ctl) ((ctl)->limit - (ctl)->cur_len)
2656 static unsigned char *
2657 extra_next_record(struct ctl_extr_rec *ctl, int length)
2659 int cur_len = ctl->cur_len;/* save cur_len */
2661 /* Close the current extra record or Directory Record. */
2662 extra_close_record(ctl, RR_CE_SIZE);
2664 /* Get a next extra record. */
2666 if (ctl->bp != NULL) {
2667 /* Storing data into an extra record. */
2670 /* Save the pointer where a CE extension will be
2672 ctl->ce_ptr = &ctl->bp[cur_len+1];
2673 p = extra_get_record(ctl->isoent,
2674 &ctl->limit, &ctl->extr_off, &ctl->extr_loc);
2675 ctl->bp = p - 1;/* the base of bp offset is 1. */
2677 /* Calculating the size of an extra record. */
2678 (void)extra_get_record(ctl->isoent,
2679 &ctl->limit, NULL, NULL);
2681 /* Check if an extra record is almost full.
2682 * If so, get a next one. */
2683 if (extra_space(ctl) < length)
2684 (void)extra_next_record(ctl, length);
2689 static inline struct extr_rec *
2690 extra_last_record(struct isoent *isoent)
2692 if (isoent->extr_rec_list.first == NULL)
2694 return ((struct extr_rec *)(void *)
2695 ((char *)(isoent->extr_rec_list.last)
2696 - offsetof(struct extr_rec, next)));
2699 static unsigned char *
2700 extra_get_record(struct isoent *isoent, int *space, int *off, int *loc)
2702 struct extr_rec *rec;
2704 isoent = isoent->parent;
2706 /* Storing data into an extra record. */
2707 rec = isoent->extr_rec_list.current;
2708 if (DR_SAFETY > LOGICAL_BLOCK_SIZE - rec->offset)
2711 /* Calculating the size of an extra record. */
2712 rec = extra_last_record(isoent);
2714 DR_SAFETY > LOGICAL_BLOCK_SIZE - rec->offset) {
2715 rec = malloc(sizeof(*rec));
2720 /* Insert `rec` into the tail of isoent->extr_rec_list */
2722 *isoent->extr_rec_list.last = rec;
2723 isoent->extr_rec_list.last = &(rec->next);
2726 *space = LOGICAL_BLOCK_SIZE - rec->offset - DR_SAFETY;
2728 *space -= 1;/* Keep padding space. */
2732 *loc = rec->location;
2733 isoent->extr_rec_list.current = rec;
2735 return (&rec->buf[rec->offset]);
2739 extra_tell_used_size(struct ctl_extr_rec *ctl, int size)
2741 struct isoent *isoent;
2742 struct extr_rec *rec;
2744 if (ctl->use_extr) {
2745 isoent = ctl->isoent->parent;
2746 rec = isoent->extr_rec_list.current;
2748 rec->offset += size;
2750 ctl->cur_len += size;
2754 extra_setup_location(struct isoent *isoent, int location)
2756 struct extr_rec *rec;
2760 rec = isoent->extr_rec_list.first;
2761 isoent->extr_rec_list.current = rec;
2764 rec->location = location++;
2772 * Create the RRIP entries.
2775 set_directory_record_rr(unsigned char *bp, int dr_len,
2776 struct isoent *isoent, struct iso9660 *iso9660, enum dir_rec_type t)
2778 /* Flags(BP 5) of the Rockridge "RR" System Use Field */
2779 unsigned char rr_flag;
2780 #define RR_USE_PX 0x01
2781 #define RR_USE_PN 0x02
2782 #define RR_USE_SL 0x04
2783 #define RR_USE_NM 0x08
2784 #define RR_USE_CL 0x10
2785 #define RR_USE_PL 0x20
2786 #define RR_USE_RE 0x40
2787 #define RR_USE_TF 0x80
2789 struct ctl_extr_rec ctl;
2790 struct isoent *rr_parent, *pxent;
2791 struct isofile *file;
2793 bp = extra_open_record(bp, dr_len, isoent, &ctl);
2795 if (t == DIR_REC_PARENT) {
2796 rr_parent = isoent->rr_parent;
2797 pxent = isoent->parent;
2798 if (rr_parent != NULL)
2801 isoent = isoent->parent;
2806 file = isoent->file;
2808 if (t != DIR_REC_NORMAL) {
2809 rr_flag = RR_USE_PX | RR_USE_TF;
2810 if (rr_parent != NULL)
2811 rr_flag |= RR_USE_PL;
2813 rr_flag = RR_USE_PX | RR_USE_NM | RR_USE_TF;
2814 if (archive_entry_filetype(file->entry) == AE_IFLNK)
2815 rr_flag |= RR_USE_SL;
2816 if (isoent->rr_parent != NULL)
2817 rr_flag |= RR_USE_RE;
2818 if (isoent->rr_child != NULL)
2819 rr_flag |= RR_USE_CL;
2820 if (archive_entry_filetype(file->entry) == AE_IFCHR ||
2821 archive_entry_filetype(file->entry) == AE_IFBLK)
2822 rr_flag |= RR_USE_PN;
2823 #ifdef COMPAT_MKISOFS
2825 * mkisofs 2.01.01a63 records "RE" extension to
2826 * the entry of "rr_moved" directory.
2827 * I don't understand this behavior.
2829 if (isoent->virtual &&
2830 isoent->parent == iso9660->primary.rootent &&
2831 strcmp(isoent->file->basename.s, "rr_moved") == 0)
2832 rr_flag |= RR_USE_RE;
2836 /* Write "SP" System Use Entry. */
2837 if (t == DIR_REC_SELF && isoent == isoent->parent) {
2843 bp[4] = 1; /* version */
2844 bp[5] = 0xBE; /* Check Byte */
2845 bp[6] = 0xEF; /* Check Byte */
2849 extra_tell_used_size(&ctl, length);
2852 /* Write "RR" System Use Entry. */
2854 if (extra_space(&ctl) < length)
2855 bp = extra_next_record(&ctl, length);
2860 bp[4] = 1; /* version */
2864 extra_tell_used_size(&ctl, length);
2866 /* Write "NM" System Use Entry. */
2867 if (rr_flag & RR_USE_NM) {
2870 * e.g. a basename is 'foo'
2872 * +----+----+----+----+----+----+----+----+
2873 * | 'N'| 'M'| 08 | 01 | 00 | 'f'| 'o'| 'o'|
2874 * +----+----+----+----+----+----+----+----+
2875 * <----------------- len ----------------->
2877 size_t nmlen = file->basename.length;
2878 const char *nm = file->basename.s;
2881 if (extra_space(&ctl) < 6)
2882 bp = extra_next_record(&ctl, 6);
2886 bp[4] = 1; /* version */
2888 nmmax = extra_space(&ctl);
2891 while (nmlen + 5 > nmmax) {
2895 bp[5] = 0x01;/* Alternate Name continues
2896 * in next "NM" field */
2897 memcpy(bp+6, nm, length - 5);
2900 nmlen -= length - 5;
2902 extra_tell_used_size(&ctl, length);
2903 if (extra_space(&ctl) < 6) {
2904 bp = extra_next_record(&ctl, 6);
2905 nmmax = extra_space(&ctl);
2912 bp[4] = 1; /* version */
2919 memcpy(bp+6, nm, nmlen);
2922 extra_tell_used_size(&ctl, length);
2925 /* Write "PX" System Use Entry. */
2926 if (rr_flag & RR_USE_PX) {
2930 * +----+----+----+----+-----------+-----------+
2931 * | 'P'| 'X'| 2C | 01 | FILE MODE | LINKS |
2932 * +----+----+----+----+-----------+-----------+
2934 * +-----------+-----------+------------------+
2935 * | USER ID | GROUP ID |FILE SERIAL NUMBER|
2936 * +-----------+-----------+------------------+
2940 if (extra_space(&ctl) < length)
2941 bp = extra_next_record(&ctl, length);
2947 mode = archive_entry_mode(file->entry);
2948 uid = archive_entry_uid(file->entry);
2949 gid = archive_entry_gid(file->entry);
2950 if (iso9660->opt.rr == OPT_RR_USEFUL) {
2952 * This action is simular mkisofs -r option
2953 * but our rockridge=useful option does not
2954 * set a zero to uid and gid.
2956 /* set all read bit ON */
2958 #if !defined(_WIN32) && !defined(__CYGWIN__)
2961 /* set all exec bit ON */
2963 /* clear all write bits. */
2965 /* clear setuid,setgid,sticky bits. */
2972 bp[4] = 1; /* version */
2974 set_num_733(bp+5, mode);
2975 /* file links (stat.st_nlink) */
2977 archive_entry_nlink(file->entry));
2978 set_num_733(bp+21, uid);
2979 set_num_733(bp+29, gid);
2980 /* File Serial Number */
2982 set_num_733(bp+37, pxent->dir_location);
2983 else if (file->hardlink_target != NULL)
2985 file->hardlink_target->cur_content->location);
2988 file->cur_content->location);
2991 extra_tell_used_size(&ctl, length);
2994 /* Write "SL" System Use Entry. */
2995 if (rr_flag & RR_USE_SL) {
2998 * e.g. a symbolic name is 'foo/bar'
3000 * +----+----+----+----+----+------------+
3001 * | 'S'| 'L'| 0F | 01 | 00 | components |
3002 * +----+----+----+----+----+-----+------+
3003 * 0 1 2 3 4 5 ...|... 15
3004 * <----------------- len --------+------>
3007 * +----+----+----+----+----+ |
3008 * | 00 | 03 | 'f'| 'o'| 'o'| <---+
3009 * +----+----+----+----+----+ |
3012 * +----+----+----+----+----+ |
3013 * | 00 | 03 | 'b'| 'a'| 'r'| <---+
3014 * +----+----+----+----+----+
3017 * - cflg : flag of componet
3018 * - clen : length of componet
3023 if (extra_space(&ctl) < 7)
3024 bp = extra_next_record(&ctl, 7);
3025 sl = file->symlink.s;
3030 bp[4] = 1; /* version */
3033 unsigned char *nc, *cf, *cl, cldmy = 0;
3036 slmax = extra_space(&ctl);
3045 while (*sl && sllen + 11 < slmax) {
3046 if (sl_last == '\0' && sl[0] == '/') {
3050 * | 08 | 00 | ROOT component.
3053 * Root component has to appear
3054 * at the first component only.
3058 *cf = 0x08; /* ROOT */
3067 if (((sl_last == '\0' || sl_last == '/') &&
3068 sl[0] == '.' && sl[1] == '.' &&
3069 (sl[2] == '/' || sl[2] == '\0')) ||
3071 sl[1] == '.' && sl[2] == '.' &&
3072 (sl[3] == '/' || sl[3] == '\0'))) {
3076 * | 04 | 00 | PARENT component.
3077 * +----+----+ ("..")
3081 *cf = 0x04; /* PARENT */
3086 sl += 3;/* skip "/.." */
3088 sl += 2;/* skip ".." */
3093 if (((sl_last == '\0' || sl_last == '/') &&
3095 (sl[1] == '/' || sl[1] == '\0')) ||
3096 (sl[0] == '/' && sl[1] == '.' &&
3097 (sl[2] == '/' || sl[2] == '\0'))) {
3101 * | 02 | 00 | CURREENT component.
3106 *cf = 0x02; /* CURRENT */
3111 sl += 2;/* skip "/." */
3113 sl ++; /* skip "." */
3118 if (sl[0] == '/' || cl == NULL) {
3143 * Mark flg as CONTINUE component.
3148 * +----+----+----+----+----+-
3149 * | 'S'| 'L'| XX | 01 | 01 |
3150 * +----+----+----+----+----+-
3152 * continues in next "SL"
3155 bp[5] = 0x01;/* This Symbolic Link
3160 extra_tell_used_size(&ctl, length);
3161 if (extra_space(&ctl) < 11)
3162 bp = extra_next_record(&ctl, 11);
3167 bp[4] = 1; /* version */
3176 extra_tell_used_size(&ctl, length);
3182 /* Write "TF" System Use Entry. */
3183 if (rr_flag & RR_USE_TF) {
3187 * +----+----+----+----+-----+-------------+
3188 * | 'T'| 'F'| XX | 01 |FLAGS| TIME STAMPS |
3189 * +----+----+----+----+-----+-------------+
3191 * TIME STAMPS : ISO 9660 Standard 9.1.5.
3192 * If TF_LONG_FORM FLAGS is set,
3193 * use ISO9660 Standard 8.4.26.1.
3195 #define TF_CREATION 0x01 /* Creation time recorded */
3196 #define TF_MODIFY 0x02 /* Modification time recorded */
3197 #define TF_ACCESS 0x04 /* Last Access time recorded */
3198 #define TF_ATTRIBUTES 0x08 /* Last Attribute Change time recorded */
3199 #define TF_BACKUP 0x10 /* Last Backup time recorded */
3200 #define TF_EXPIRATION 0x20 /* Expiration time recorded */
3201 #define TF_EFFECTIVE 0x40 /* Effective time recorded */
3202 #define TF_LONG_FORM 0x80 /* ISO 9660 17-byte time format used */
3203 unsigned char tf_flags;
3207 #ifndef COMPAT_MKISOFS
3208 if (archive_entry_birthtime_is_set(file->entry) &&
3209 archive_entry_birthtime(file->entry) <=
3210 archive_entry_mtime(file->entry)) {
3212 tf_flags |= TF_CREATION;
3215 if (archive_entry_mtime_is_set(file->entry)) {
3217 tf_flags |= TF_MODIFY;
3219 if (archive_entry_atime_is_set(file->entry)) {
3221 tf_flags |= TF_ACCESS;
3223 if (archive_entry_ctime_is_set(file->entry)) {
3225 tf_flags |= TF_ATTRIBUTES;
3227 if (extra_space(&ctl) < length)
3228 bp = extra_next_record(&ctl, length);
3233 bp[4] = 1; /* version */
3237 if (tf_flags & TF_CREATION) {
3239 archive_entry_birthtime(file->entry));
3242 /* Modification time */
3243 if (tf_flags & TF_MODIFY) {
3245 archive_entry_mtime(file->entry));
3248 /* Last Access time */
3249 if (tf_flags & TF_ACCESS) {
3251 archive_entry_atime(file->entry));
3254 /* Last Attribute Change time */
3255 if (tf_flags & TF_ATTRIBUTES) {
3257 archive_entry_ctime(file->entry));
3261 extra_tell_used_size(&ctl, length);
3264 /* Write "RE" System Use Entry. */
3265 if (rr_flag & RR_USE_RE) {
3269 * +----+----+----+----+
3270 * | 'R'| 'E'| 04 | 01 |
3271 * +----+----+----+----+
3275 if (extra_space(&ctl) < length)
3276 bp = extra_next_record(&ctl, length);
3281 bp[4] = 1; /* version */
3284 extra_tell_used_size(&ctl, length);
3287 /* Write "PL" System Use Entry. */
3288 if (rr_flag & RR_USE_PL) {
3292 * +----+----+----+----+------------+
3293 * | 'P'| 'L'| 0C | 01 | *LOCATION |
3294 * +----+----+----+----+------------+
3296 * *LOCATION: location of parent directory
3299 if (extra_space(&ctl) < length)
3300 bp = extra_next_record(&ctl, length);
3305 bp[4] = 1; /* version */
3307 rr_parent->dir_location);
3310 extra_tell_used_size(&ctl, length);
3313 /* Write "CL" System Use Entry. */
3314 if (rr_flag & RR_USE_CL) {
3318 * +----+----+----+----+------------+
3319 * | 'C'| 'L'| 0C | 01 | *LOCATION |
3320 * +----+----+----+----+------------+
3322 * *LOCATION: location of child directory
3325 if (extra_space(&ctl) < length)
3326 bp = extra_next_record(&ctl, length);
3331 bp[4] = 1; /* version */
3333 isoent->rr_child->dir_location);
3336 extra_tell_used_size(&ctl, length);
3339 /* Write "PN" System Use Entry. */
3340 if (rr_flag & RR_USE_PN) {
3344 * +----+----+----+----+------------+------------+
3345 * | 'P'| 'N'| 14 | 01 | dev_t high | dev_t low |
3346 * +----+----+----+----+------------+------------+
3350 if (extra_space(&ctl) < length)
3351 bp = extra_next_record(&ctl, length);
3358 bp[4] = 1; /* version */
3359 dev = (uint64_t)archive_entry_rdev(file->entry);
3360 set_num_733(bp + 5, dev >> 32);
3361 set_num_733(bp + 13, dev & 0xFFFFFFFF);
3364 extra_tell_used_size(&ctl, length);
3367 /* Write "ZF" System Use Entry. */
3368 if (file->zisofs.header_size) {
3372 * +----+----+----+----+----+----+-------------+
3373 * | 'Z'| 'F'| 10 | 01 | 'p'| 'z'| Header Size |
3374 * +----+----+----+----+----+----+-------------+
3376 * +--------------------+-------------------+
3377 * | Log2 of block Size | Uncompressed Size |
3378 * +--------------------+-------------------+
3382 if (extra_space(&ctl) < length)
3383 bp = extra_next_record(&ctl, length);
3388 bp[4] = 1; /* version */
3391 bp[7] = file->zisofs.header_size;
3392 bp[8] = file->zisofs.log2_bs;
3393 set_num_733(bp + 9, file->zisofs.uncompressed_size);
3396 extra_tell_used_size(&ctl, length);
3399 /* Write "CE" System Use Entry. */
3400 if (t == DIR_REC_SELF && isoent == isoent->parent) {
3401 length = RR_CE_SIZE;
3403 set_SUSP_CE(bp+1, iso9660->location_rrip_er,
3405 extra_tell_used_size(&ctl, length);
3408 extra_close_record(&ctl, 0);
3410 return (ctl.dr_len);
3414 * Write data of a Directory Record or calculate writing bytes itself.
3415 * If parameter `p' is NULL, calculates the size of writing data, which
3416 * a Directory Record needs to write, then it saved and return
3417 * the calculated size.
3418 * Parameter `n' is a remaining size of buffer. when parameter `p' is
3419 * not NULL, check whether that `n' is not less than the saved size.
3420 * if that `n' is small, return zero.
3422 * This format of the Directory Record is according to
3423 * ISO9660 Standard 9.1
3426 set_directory_record(unsigned char *p, size_t n, struct isoent *isoent,
3427 struct iso9660 *iso9660, enum dir_rec_type t,
3428 enum vdd_type vdd_type)
3436 * Check whether a write buffer size is less than the
3437 * saved size which is needed to write this Directory
3442 dr_len = isoent->dr_len.vd; break;
3444 dr_len = isoent->dr_len.self; break;
3445 case DIR_REC_PARENT:
3446 dr_len = isoent->dr_len.parent; break;
3447 case DIR_REC_NORMAL:
3449 dr_len = isoent->dr_len.normal; break;
3452 return (0);/* Needs more buffer size. */
3455 if (t == DIR_REC_NORMAL && isoent->identifier != NULL)
3456 fi_len = isoent->id_len;
3461 struct isoent *xisoent;
3462 struct isofile *file;
3465 if (t == DIR_REC_PARENT)
3466 xisoent = isoent->parent;
3469 file = isoent->file;
3470 if (file->hardlink_target != NULL)
3471 file = file->hardlink_target;
3472 /* Make a file flag. */
3474 flag = FILE_FLAG_DIRECTORY;
3476 if (file->cur_content->next != NULL)
3477 flag = FILE_FLAG_MULTI_EXTENT;
3483 /* Extended Attribute Record Length */
3484 set_num_711(bp+2, 0);
3485 /* Location of Extent */
3487 set_num_733(bp+3, xisoent->dir_location);
3489 set_num_733(bp+3, file->cur_content->location);
3493 xisoent->dir_block * LOGICAL_BLOCK_SIZE);
3495 set_num_733(bp+11, file->cur_content->size);
3496 /* Recording Date and Time */
3498 * If a file type is symbolic link, you are seeing this
3499 * field value is different from a value mkisofs makes.
3500 * libarchive uses lstat to get this one, but it
3501 * seems mkisofs uses stat to get.
3504 archive_entry_mtime(xisoent->file->entry));
3507 /* File Unit Size */
3508 set_num_711(bp+27, 0);
3509 /* Interleave Gap Size */
3510 set_num_711(bp+28, 0);
3511 /* Volume Sequence Number */
3512 set_num_723(bp+29, iso9660->volume_sequence_number);
3513 /* Length of File Identifier */
3514 set_num_711(bp+33, fi_len);
3515 /* File Identifier */
3519 set_num_711(bp+34, 0);
3521 case DIR_REC_PARENT:
3522 set_num_711(bp+34, 1);
3524 case DIR_REC_NORMAL:
3525 if (isoent->identifier != NULL)
3526 memcpy(bp+34, isoent->identifier, fi_len);
3528 set_num_711(bp+34, 0);
3533 dr_len = 33 + fi_len;
3535 if (dr_len & 0x01) {
3541 /* Volume Descriptor does not record extension. */
3542 if (t == DIR_REC_VD) {
3544 /* Length of Directory Record */
3545 set_num_711(p, dr_len);
3547 isoent->dr_len.vd = dr_len;
3552 if (iso9660->opt.rr && vdd_type != VDD_JOLIET)
3553 dr_len = set_directory_record_rr(bp, dr_len,
3554 isoent, iso9660, t);
3557 /* Length of Directory Record */
3558 set_num_711(p, dr_len);
3561 * Save the size which is needed to write this
3566 /* This case does not come, but compiler
3567 * complains that DIR_REC_VD not handled
3571 isoent->dr_len.self = dr_len; break;
3572 case DIR_REC_PARENT:
3573 isoent->dr_len.parent = dr_len; break;
3574 case DIR_REC_NORMAL:
3575 isoent->dr_len.normal = dr_len; break;
3583 * Calculate the size of a directory record.
3586 get_dir_rec_size(struct iso9660 *iso9660, struct isoent *isoent,
3587 enum dir_rec_type t, enum vdd_type vdd_type)
3590 return (set_directory_record(NULL, SIZE_MAX,
3591 isoent, iso9660, t, vdd_type));
3595 * Manage to write ISO-image data with wbuff to reduce calling
3596 * __archive_write_output() for performance.
3600 static inline unsigned char *
3601 wb_buffptr(struct archive_write *a)
3603 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3605 return (&(iso9660->wbuff[sizeof(iso9660->wbuff)
3606 - iso9660->wbuff_remaining]));
3610 wb_write_out(struct archive_write *a)
3612 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3616 wsize = sizeof(iso9660->wbuff) - iso9660->wbuff_remaining;
3617 nw = wsize % LOGICAL_BLOCK_SIZE;
3618 if (iso9660->wbuff_type == WB_TO_STREAM)
3619 r = __archive_write_output(a, iso9660->wbuff, wsize - nw);
3621 r = write_to_temp(a, iso9660->wbuff, wsize - nw);
3622 /* Increase the offset. */
3623 iso9660->wbuff_offset += wsize - nw;
3624 if (iso9660->wbuff_offset > iso9660->wbuff_written)
3625 iso9660->wbuff_written = iso9660->wbuff_offset;
3626 iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
3628 iso9660->wbuff_remaining -= nw;
3629 memmove(iso9660->wbuff, iso9660->wbuff + wsize - nw, nw);
3635 wb_consume(struct archive_write *a, size_t size)
3637 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3639 if (size > iso9660->wbuff_remaining ||
3640 iso9660->wbuff_remaining == 0) {
3641 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
3642 "Internal Programing error: iso9660:wb_consume()"
3643 " size=%jd, wbuff_remaining=%jd",
3644 (intmax_t)size, (intmax_t)iso9660->wbuff_remaining);
3645 return (ARCHIVE_FATAL);
3647 iso9660->wbuff_remaining -= size;
3648 if (iso9660->wbuff_remaining < LOGICAL_BLOCK_SIZE)
3649 return (wb_write_out(a));
3650 return (ARCHIVE_OK);
3656 wb_set_offset(struct archive_write *a, int64_t off)
3658 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3659 int64_t used, ext_bytes;
3661 if (iso9660->wbuff_type != WB_TO_TEMP) {
3662 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
3663 "Internal Programing error: iso9660:wb_set_offset()");
3664 return (ARCHIVE_FATAL);
3667 used = sizeof(iso9660->wbuff) - iso9660->wbuff_remaining;
3668 if (iso9660->wbuff_offset + used > iso9660->wbuff_tail)
3669 iso9660->wbuff_tail = iso9660->wbuff_offset + used;
3670 if (iso9660->wbuff_offset < iso9660->wbuff_written) {
3672 write_to_temp(a, iso9660->wbuff, used) != ARCHIVE_OK)
3673 return (ARCHIVE_FATAL);
3674 iso9660->wbuff_offset = iso9660->wbuff_written;
3675 lseek(iso9660->temp_fd, iso9660->wbuff_offset, SEEK_SET);
3676 iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
3679 if (off < iso9660->wbuff_offset) {
3681 * Write out waiting data.
3684 if (wb_write_out(a) != ARCHIVE_OK)
3685 return (ARCHIVE_FATAL);
3687 lseek(iso9660->temp_fd, off, SEEK_SET);
3688 iso9660->wbuff_offset = off;
3689 iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
3690 } else if (off <= iso9660->wbuff_tail) {
3691 iso9660->wbuff_remaining =
3692 sizeof(iso9660->wbuff) - (off - iso9660->wbuff_offset);
3694 ext_bytes = off - iso9660->wbuff_tail;
3695 iso9660->wbuff_remaining = sizeof(iso9660->wbuff)
3696 - (iso9660->wbuff_tail - iso9660->wbuff_offset);
3697 while (ext_bytes >= (int64_t)iso9660->wbuff_remaining) {
3698 if (write_null(a, (size_t)iso9660->wbuff_remaining)
3700 return (ARCHIVE_FATAL);
3701 ext_bytes -= iso9660->wbuff_remaining;
3703 if (ext_bytes > 0) {
3704 if (write_null(a, (size_t)ext_bytes) != ARCHIVE_OK)
3705 return (ARCHIVE_FATAL);
3708 return (ARCHIVE_OK);
3711 #endif /* HAVE_ZLIB_H */
3714 write_null(struct archive_write *a, size_t size)
3717 unsigned char *p, *old;
3720 remaining = wb_remaining(a);
3722 if (size <= remaining) {
3724 return (wb_consume(a, size));
3726 memset(p, 0, remaining);
3727 r = wb_consume(a, remaining);
3728 if (r != ARCHIVE_OK)
3733 memset(p, 0, old - p);
3734 remaining = wb_remaining(a);
3736 size_t wsize = size;
3738 if (wsize > remaining)
3740 r = wb_consume(a, wsize);
3741 if (r != ARCHIVE_OK)
3745 return (ARCHIVE_OK);
3749 * Write Volume Descriptor Set Terminator
3752 write_VD_terminator(struct archive_write *a)
3756 bp = wb_buffptr(a) -1;
3757 set_VD_bp(bp, VDT_TERMINATOR, 1);
3758 set_unused_field_bp(bp, 8, LOGICAL_BLOCK_SIZE);
3760 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
3764 set_file_identifier(unsigned char *bp, int from, int to, enum vdc vdc,
3765 struct archive_write *a, struct vdd *vdd, struct archive_string *id,
3766 const char *label, int leading_under, enum char_type char_type)
3768 char identifier[256];
3769 struct isoent *isoent;
3774 if (id->length > 0 && leading_under && id->s[0] != '_') {
3775 if (char_type == A_CHAR)
3776 r = set_str_a_characters_bp(a, bp, from, to, id->s, vdc);
3778 r = set_str_d_characters_bp(a, bp, from, to, id->s, vdc);
3779 } else if (id->length > 0) {
3783 isoent = isoent_find_entry(vdd->rootent, ids);
3784 if (isoent == NULL) {
3785 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
3786 "Not Found %s `%s'.",
3788 return (ARCHIVE_FATAL);
3790 len = isoent->ext_off + isoent->ext_len;
3791 if (vdd->vdd_type == VDD_JOLIET) {
3792 if (len > sizeof(identifier)-2)
3793 len = sizeof(identifier)-2;
3795 if (len > sizeof(identifier)-1)
3796 len = sizeof(identifier)-1;
3798 memcpy(identifier, isoent->identifier, len);
3799 identifier[len] = '\0';
3800 if (vdd->vdd_type == VDD_JOLIET) {
3801 identifier[len+1] = 0;
3802 vdc = VDC_UCS2_DIRECT;
3804 if (char_type == A_CHAR)
3805 r = set_str_a_characters_bp(a, bp, from, to,
3808 r = set_str_d_characters_bp(a, bp, from, to,
3811 if (char_type == A_CHAR)
3812 r = set_str_a_characters_bp(a, bp, from, to, NULL, vdc);
3814 r = set_str_d_characters_bp(a, bp, from, to, NULL, vdc);
3820 * Write Primary/Supplementary Volume Descriptor
3823 write_VD(struct archive_write *a, struct vdd *vdd)
3825 struct iso9660 *iso9660;
3827 uint16_t volume_set_size = 1;
3828 char identifier[256];
3831 unsigned char vd_ver, fst_ver;
3834 iso9660 = a->format_data;
3835 switch (vdd->vdd_type) {
3837 vdt = VDT_SUPPLEMENTARY;
3838 vd_ver = fst_ver = 1;
3842 vdt = VDT_SUPPLEMENTARY;
3843 vd_ver = fst_ver = 2;
3844 vdc = VDC_LOWERCASE;
3849 vd_ver = fst_ver = 1;
3850 #ifdef COMPAT_MKISOFS
3851 vdc = VDC_LOWERCASE;
3858 bp = wb_buffptr(a) -1;
3859 /* Volume Descriptor Type */
3860 set_VD_bp(bp, vdt, vd_ver);
3862 set_unused_field_bp(bp, 8, 8);
3863 /* System Identifier */
3864 get_system_identitier(identifier, sizeof(identifier));
3865 r = set_str_a_characters_bp(a, bp, 9, 40, identifier, vdc);
3866 if (r != ARCHIVE_OK)
3868 /* Volume Identifier */
3869 r = set_str_d_characters_bp(a, bp, 41, 72,
3870 iso9660->volume_identifier.s, vdc);
3871 if (r != ARCHIVE_OK)
3874 set_unused_field_bp(bp, 73, 80);
3875 /* Volume Space Size */
3876 set_num_733(bp+81, iso9660->volume_space_size);
3877 if (vdd->vdd_type == VDD_JOLIET) {
3878 /* Escape Sequences */
3879 bp[89] = 0x25;/* UCS-2 Level 3 */
3882 memset(bp + 92, 0, 120 - 92 + 1);
3885 set_unused_field_bp(bp, 89, 120);
3887 /* Volume Set Size */
3888 set_num_723(bp+121, volume_set_size);
3889 /* Volume Sequence Number */
3890 set_num_723(bp+125, iso9660->volume_sequence_number);
3891 /* Logical Block Size */
3892 set_num_723(bp+129, LOGICAL_BLOCK_SIZE);
3893 /* Path Table Size */
3894 set_num_733(bp+133, vdd->path_table_size);
3895 /* Location of Occurrence of Type L Path Table */
3896 set_num_731(bp+141, vdd->location_type_L_path_table);
3897 /* Location of Optional Occurrence of Type L Path Table */
3898 set_num_731(bp+145, 0);
3899 /* Location of Occurrence of Type M Path Table */
3900 set_num_732(bp+149, vdd->location_type_M_path_table);
3901 /* Location of Optional Occurrence of Type M Path Table */
3902 set_num_732(bp+153, 0);
3903 /* Directory Record for Root Directory(BP 157 to 190) */
3904 set_directory_record(bp+157, 190-157+1, vdd->rootent,
3905 iso9660, DIR_REC_VD, vdd->vdd_type);
3906 /* Volume Set Identifier */
3907 r = set_str_d_characters_bp(a, bp, 191, 318, "", vdc);
3908 if (r != ARCHIVE_OK)
3910 /* Publisher Identifier */
3911 r = set_file_identifier(bp, 319, 446, vdc, a, vdd,
3912 &(iso9660->publisher_identifier),
3913 "Publisher File", 1, A_CHAR);
3914 if (r != ARCHIVE_OK)
3916 /* Data Preparer Identifier */
3917 r = set_file_identifier(bp, 447, 574, vdc, a, vdd,
3918 &(iso9660->data_preparer_identifier),
3919 "Data Preparer File", 1, A_CHAR);
3920 if (r != ARCHIVE_OK)
3922 /* Application Identifier */
3923 r = set_file_identifier(bp, 575, 702, vdc, a, vdd,
3924 &(iso9660->application_identifier),
3925 "Application File", 1, A_CHAR);
3926 if (r != ARCHIVE_OK)
3928 /* Copyright File Identifier */
3929 r = set_file_identifier(bp, 703, 739, vdc, a, vdd,
3930 &(iso9660->copyright_file_identifier),
3931 "Copyright File", 0, D_CHAR);
3932 if (r != ARCHIVE_OK)
3934 /* Abstract File Identifier */
3935 r = set_file_identifier(bp, 740, 776, vdc, a, vdd,
3936 &(iso9660->abstract_file_identifier),
3937 "Abstract File", 0, D_CHAR);
3938 if (r != ARCHIVE_OK)
3940 /* Bibliongraphic File Identifier */
3941 r = set_file_identifier(bp, 777, 813, vdc, a, vdd,
3942 &(iso9660->bibliographic_file_identifier),
3943 "Bibliongraphic File", 0, D_CHAR);
3944 if (r != ARCHIVE_OK)
3946 /* Volume Creation Date and Time */
3947 set_date_time(bp+814, iso9660->birth_time);
3948 /* Volume Modification Date and Time */
3949 set_date_time(bp+831, iso9660->birth_time);
3950 /* Volume Expiration Date and Time(obsolete) */
3951 set_date_time_null(bp+848);
3952 /* Volume Effective Date and Time */
3953 set_date_time(bp+865, iso9660->birth_time);
3954 /* File Structure Version */
3958 /* Application Use */
3959 memset(bp + 884, 0x20, 1395 - 884 + 1);
3961 set_unused_field_bp(bp, 1396, LOGICAL_BLOCK_SIZE);
3963 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
3967 * Write Boot Record Volume Descriptor
3970 write_VD_boot_record(struct archive_write *a)
3972 struct iso9660 *iso9660;
3975 iso9660 = a->format_data;
3976 bp = wb_buffptr(a) -1;
3977 /* Volume Descriptor Type */
3978 set_VD_bp(bp, VDT_BOOT_RECORD, 1);
3979 /* Boot System Identifier */
3980 memcpy(bp+8, "EL TORITO SPECIFICATION", 23);
3981 set_unused_field_bp(bp, 8+23, 39);
3983 set_unused_field_bp(bp, 40, 71);
3984 /* Absolute pointer to first sector of Boot Catalog */
3986 iso9660->el_torito.catalog->file->content.location);
3988 set_unused_field_bp(bp, 76, LOGICAL_BLOCK_SIZE);
3990 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4000 set_option_info(struct archive_string *info, int *opt, const char *key,
4001 enum keytype type, ...)
4008 prefix = (*opt==0)? ' ':',';
4012 d = va_arg(ap, int);
4013 archive_string_sprintf(info, "%c%s%s",
4014 prefix, (d == 0)?"!":"", key);
4017 s = va_arg(ap, const char *);
4018 archive_string_sprintf(info, "%c%s=%s",
4022 d = va_arg(ap, int);
4023 archive_string_sprintf(info, "%c%s=%d",
4027 d = va_arg(ap, int);
4028 archive_string_sprintf(info, "%c%s=%x",
4038 * Make Non-ISO File System Information
4041 write_information_block(struct archive_write *a)
4043 struct iso9660 *iso9660;
4047 struct archive_string info;
4048 size_t info_size = LOGICAL_BLOCK_SIZE *
4049 NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK;
4051 iso9660 = (struct iso9660 *)a->format_data;
4052 if (info_size > wb_remaining(a)) {
4053 r = wb_write_out(a);
4054 if (r != ARCHIVE_OK)
4057 archive_string_init(&info);
4058 if (archive_string_ensure(&info, info_size) == NULL) {
4059 archive_set_error(&a->archive, ENOMEM,
4060 "Can't allocate memory");
4061 return (ARCHIVE_FATAL);
4063 memset(info.s, 0, info_size);
4065 #if defined(HAVE__CTIME64_S)
4066 _ctime64_s(buf, sizeof(buf), &(iso9660->birth_time));
4067 #elif defined(HAVE_CTIME_R)
4068 ctime_r(&(iso9660->birth_time), buf);
4070 strncpy(buf, ctime(&(iso9660->birth_time)), sizeof(buf)-1);
4071 buf[sizeof(buf)-1] = '\0';
4073 archive_string_sprintf(&info,
4074 "INFO %s%s", buf, archive_version_string());
4075 if (iso9660->opt.abstract_file != OPT_ABSTRACT_FILE_DEFAULT)
4076 set_option_info(&info, &opt, "abstract-file",
4077 KEY_STR, iso9660->abstract_file_identifier.s);
4078 if (iso9660->opt.application_id != OPT_APPLICATION_ID_DEFAULT)
4079 set_option_info(&info, &opt, "application-id",
4080 KEY_STR, iso9660->application_identifier.s);
4081 if (iso9660->opt.allow_vernum != OPT_ALLOW_VERNUM_DEFAULT)
4082 set_option_info(&info, &opt, "allow-vernum",
4083 KEY_FLG, iso9660->opt.allow_vernum);
4084 if (iso9660->opt.biblio_file != OPT_BIBLIO_FILE_DEFAULT)
4085 set_option_info(&info, &opt, "biblio-file",
4086 KEY_STR, iso9660->bibliographic_file_identifier.s);
4087 if (iso9660->opt.boot != OPT_BOOT_DEFAULT)
4088 set_option_info(&info, &opt, "boot",
4089 KEY_STR, iso9660->el_torito.boot_filename.s);
4090 if (iso9660->opt.boot_catalog != OPT_BOOT_CATALOG_DEFAULT)
4091 set_option_info(&info, &opt, "boot-catalog",
4092 KEY_STR, iso9660->el_torito.catalog_filename.s);
4093 if (iso9660->opt.boot_info_table != OPT_BOOT_INFO_TABLE_DEFAULT)
4094 set_option_info(&info, &opt, "boot-info-table",
4095 KEY_FLG, iso9660->opt.boot_info_table);
4096 if (iso9660->opt.boot_load_seg != OPT_BOOT_LOAD_SEG_DEFAULT)
4097 set_option_info(&info, &opt, "boot-load-seg",
4098 KEY_HEX, iso9660->el_torito.boot_load_seg);
4099 if (iso9660->opt.boot_load_size != OPT_BOOT_LOAD_SIZE_DEFAULT)
4100 set_option_info(&info, &opt, "boot-load-size",
4101 KEY_INT, iso9660->el_torito.boot_load_size);
4102 if (iso9660->opt.boot_type != OPT_BOOT_TYPE_DEFAULT) {
4104 if (iso9660->opt.boot_type == OPT_BOOT_TYPE_FD)
4106 if (iso9660->opt.boot_type == OPT_BOOT_TYPE_HARD_DISK)
4108 set_option_info(&info, &opt, "boot-type",
4112 if (iso9660->opt.compression_level != OPT_COMPRESSION_LEVEL_DEFAULT)
4113 set_option_info(&info, &opt, "compression-level",
4114 KEY_INT, iso9660->zisofs.compression_level);
4116 if (iso9660->opt.copyright_file != OPT_COPYRIGHT_FILE_DEFAULT)
4117 set_option_info(&info, &opt, "copyright-file",
4118 KEY_STR, iso9660->copyright_file_identifier.s);
4119 if (iso9660->opt.iso_level != OPT_ISO_LEVEL_DEFAULT)
4120 set_option_info(&info, &opt, "iso-level",
4121 KEY_INT, iso9660->opt.iso_level);
4122 if (iso9660->opt.joliet != OPT_JOLIET_DEFAULT) {
4123 if (iso9660->opt.joliet == OPT_JOLIET_LONGNAME)
4124 set_option_info(&info, &opt, "joliet",
4127 set_option_info(&info, &opt, "joliet",
4128 KEY_FLG, iso9660->opt.joliet);
4130 if (iso9660->opt.limit_depth != OPT_LIMIT_DEPTH_DEFAULT)
4131 set_option_info(&info, &opt, "limit-depth",
4132 KEY_FLG, iso9660->opt.limit_depth);
4133 if (iso9660->opt.limit_dirs != OPT_LIMIT_DIRS_DEFAULT)
4134 set_option_info(&info, &opt, "limit-dirs",
4135 KEY_FLG, iso9660->opt.limit_dirs);
4136 if (iso9660->opt.pad != OPT_PAD_DEFAULT)
4137 set_option_info(&info, &opt, "pad",
4138 KEY_FLG, iso9660->opt.pad);
4139 if (iso9660->opt.publisher != OPT_PUBLISHER_DEFAULT)
4140 set_option_info(&info, &opt, "publisher",
4141 KEY_STR, iso9660->publisher_identifier.s);
4142 if (iso9660->opt.rr != OPT_RR_DEFAULT) {
4143 if (iso9660->opt.rr == OPT_RR_DISABLED)
4144 set_option_info(&info, &opt, "rockridge",
4145 KEY_FLG, iso9660->opt.rr);
4146 else if (iso9660->opt.rr == OPT_RR_STRICT)
4147 set_option_info(&info, &opt, "rockridge",
4149 else if (iso9660->opt.rr == OPT_RR_USEFUL)
4150 set_option_info(&info, &opt, "rockridge",
4153 if (iso9660->opt.volume_id != OPT_VOLUME_ID_DEFAULT)
4154 set_option_info(&info, &opt, "volume-id",
4155 KEY_STR, iso9660->volume_identifier.s);
4156 if (iso9660->opt.zisofs != OPT_ZISOFS_DEFAULT)
4157 set_option_info(&info, &opt, "zisofs",
4158 KEY_FLG, iso9660->opt.zisofs);
4160 memcpy(wb_buffptr(a), info.s, info_size);
4161 archive_string_free(&info);
4162 return (wb_consume(a, info_size));
4166 write_rr_ER(struct archive_write *a)
4172 memset(p, 0, LOGICAL_BLOCK_SIZE);
4176 p[2] = RRIP_ER_SIZE;
4177 p[4] = RRIP_ER_ID_SIZE;
4178 p[5] = RRIP_ER_DSC_SIZE;
4179 p[6] = RRIP_ER_SRC_SIZE;
4181 memcpy(&p[8], rrip_identifier, p[4]);
4182 memcpy(&p[8+p[4]], rrip_descriptor, p[5]);
4183 memcpy(&p[8+p[4]+p[5]], rrip_source, p[6]);
4185 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4189 calculate_path_table_size(struct vdd *vdd)
4192 struct path_table *pt;
4196 for (depth = 0; depth < vdd->max_depth; depth++) {
4197 struct isoent **ptbl;
4200 if ((cnt = pt[depth].cnt) == 0)
4203 ptbl = pt[depth].sorted;
4204 for (i = 0; i < cnt; i++) {
4207 if (ptbl[i]->identifier == NULL)
4208 len = 1; /* root directory */
4210 len = ptbl[i]->id_len;
4212 len++; /* Padding Field */
4216 vdd->path_table_size = size;
4217 vdd->path_table_block =
4218 ((size + PATH_TABLE_BLOCK_SIZE -1) /
4219 PATH_TABLE_BLOCK_SIZE) *
4220 (PATH_TABLE_BLOCK_SIZE / LOGICAL_BLOCK_SIZE);
4224 _write_path_table(struct archive_write *a, int type_m, int depth,
4227 unsigned char *bp, *wb;
4228 struct isoent **ptbl;
4232 if (vdd->pathtbl[depth].cnt == 0)
4237 wbremaining = wb_remaining(a);
4239 ptbl = vdd->pathtbl[depth].sorted;
4240 for (i = 0; i < vdd->pathtbl[depth].cnt; i++) {
4245 if (np->identifier == NULL)
4246 len = 1; /* root directory */
4249 if (wbremaining - ((bp+1) - wb) < (len + 1 + 8)) {
4250 r = wb_consume(a, (bp+1) - wb);
4254 wbremaining = wb_remaining(a);
4257 /* Length of Directory Identifier */
4258 set_num_711(bp+1, len);
4259 /* Extended Attribute Record Length */
4260 set_num_711(bp+2, 0);
4261 /* Location of Extent */
4263 set_num_732(bp+3, np->dir_location);
4265 set_num_731(bp+3, np->dir_location);
4266 /* Parent Directory Number */
4268 set_num_722(bp+7, np->parent->dir_number);
4270 set_num_721(bp+7, np->parent->dir_number);
4271 /* Directory Identifier */
4272 if (np->identifier == NULL)
4275 memcpy(&bp[9], np->identifier, len);
4284 if ((bp + 1) > wb) {
4285 r = wb_consume(a, (bp+1)-wb);
4293 write_path_table(struct archive_write *a, int type_m, struct vdd *vdd)
4296 size_t path_table_size;
4299 path_table_size = 0;
4300 for (depth = 0; depth < vdd->max_depth; depth++) {
4301 r = _write_path_table(a, type_m, depth, vdd);
4304 path_table_size += r;
4307 /* Write padding data. */
4308 path_table_size = path_table_size % PATH_TABLE_BLOCK_SIZE;
4309 if (path_table_size > 0)
4310 r = write_null(a, PATH_TABLE_BLOCK_SIZE - path_table_size);
4315 calculate_directory_descriptors(struct iso9660 *iso9660, struct vdd *vdd,
4316 struct isoent *isoent, int depth)
4318 struct isoent **enttbl;
4322 bs = get_dir_rec_size(iso9660, isoent, DIR_REC_SELF, vdd->vdd_type);
4323 bs += get_dir_rec_size(iso9660, isoent, DIR_REC_PARENT, vdd->vdd_type);
4325 if (isoent->children.cnt <= 0 || (vdd->vdd_type != VDD_JOLIET &&
4326 !iso9660->opt.rr && depth + 1 >= vdd->max_depth))
4329 enttbl = isoent->children_sorted;
4330 for (i = 0; i < isoent->children.cnt; i++) {
4331 struct isoent *np = enttbl[i];
4332 struct isofile *file;
4335 if (file->hardlink_target != NULL)
4336 file = file->hardlink_target;
4337 file->cur_content = &(file->content);
4341 dr_l = get_dir_rec_size(iso9660, np, DIR_REC_NORMAL,
4343 if ((bs + dr_l) > LOGICAL_BLOCK_SIZE) {
4348 file->cur_content = file->cur_content->next;
4349 } while (file->cur_content != NULL);
4355 _write_directory_descriptors(struct archive_write *a, struct vdd *vdd,
4356 struct isoent *isoent, int depth)
4358 struct iso9660 *iso9660 = a->format_data;
4359 struct isoent **enttbl;
4360 unsigned char *p, *wb;
4364 p = wb = wb_buffptr(a);
4365 #define WD_REMAINING (LOGICAL_BLOCK_SIZE - (p - wb))
4366 p += set_directory_record(p, WD_REMAINING, isoent,
4367 iso9660, DIR_REC_SELF, vdd->vdd_type);
4368 p += set_directory_record(p, WD_REMAINING, isoent,
4369 iso9660, DIR_REC_PARENT, vdd->vdd_type);
4371 if (isoent->children.cnt <= 0 || (vdd->vdd_type != VDD_JOLIET &&
4372 !iso9660->opt.rr && depth + 1 >= vdd->max_depth)) {
4373 memset(p, 0, WD_REMAINING);
4374 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4377 enttbl = isoent->children_sorted;
4378 for (i = 0; i < isoent->children.cnt; i++) {
4379 struct isoent *np = enttbl[i];
4380 struct isofile *file = np->file;
4382 if (file->hardlink_target != NULL)
4383 file = file->hardlink_target;
4384 file->cur_content = &(file->content);
4386 dr_l = set_directory_record(p, WD_REMAINING,
4387 np, iso9660, DIR_REC_NORMAL,
4390 memset(p, 0, WD_REMAINING);
4391 r = wb_consume(a, LOGICAL_BLOCK_SIZE);
4394 p = wb = wb_buffptr(a);
4395 dr_l = set_directory_record(p,
4396 WD_REMAINING, np, iso9660,
4397 DIR_REC_NORMAL, vdd->vdd_type);
4400 file->cur_content = file->cur_content->next;
4401 } while (file->cur_content != NULL);
4403 memset(p, 0, WD_REMAINING);
4404 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4408 write_directory_descriptors(struct archive_write *a, struct vdd *vdd)
4416 struct extr_rec *extr;
4418 r = _write_directory_descriptors(a, vdd, np, depth);
4421 if (vdd->vdd_type != VDD_JOLIET) {
4423 * This extract record is used by SUSP,RRIP.
4426 for (extr = np->extr_rec_list.first;
4428 extr = extr->next) {
4432 memcpy(wb, extr->buf, extr->offset);
4433 memset(wb + extr->offset, 0,
4434 LOGICAL_BLOCK_SIZE - extr->offset);
4435 r = wb_consume(a, LOGICAL_BLOCK_SIZE);
4441 if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) {
4442 /* Enter to sub directories. */
4443 np = np->subdirs.first;
4447 while (np != np->parent) {
4448 if (np->drnext == NULL) {
4449 /* Return to the parent directory. */
4457 } while (np != np->parent);
4459 return (ARCHIVE_OK);
4463 * Read file contents from the temporary file, and write it.
4466 write_file_contents(struct archive_write *a, int64_t offset, int64_t size)
4468 struct iso9660 *iso9660 = a->format_data;
4471 lseek(iso9660->temp_fd, offset, SEEK_SET);
4479 rsize = wb_remaining(a);
4480 if (rsize > (size_t)size)
4481 rsize = (size_t)size;
4482 rs = read(iso9660->temp_fd, wb, rsize);
4484 archive_set_error(&a->archive, errno,
4485 "Can't read temporary file(%jd)", (intmax_t)rs);
4486 return (ARCHIVE_FATAL);
4489 r = wb_consume(a, rs);
4493 return (ARCHIVE_OK);
4497 write_file_descriptors(struct archive_write *a)
4499 struct iso9660 *iso9660 = a->format_data;
4500 struct isofile *file;
4501 int64_t blocks, offset;
4507 /* Make the boot catalog contents, and write it. */
4508 if (iso9660->el_torito.catalog != NULL) {
4509 r = make_boot_catalog(a);
4514 /* Write the boot file contents. */
4515 if (iso9660->el_torito.boot != NULL) {
4516 file = iso9660->el_torito.boot->file;
4517 blocks = file->content.blocks;
4518 offset = file->content.offset_of_temp;
4520 r = write_file_contents(a, offset,
4521 blocks << LOGICAL_BLOCK_BITS);
4529 /* Write out all file contents. */
4530 for (file = iso9660->data_file_list.first;
4531 file != NULL; file = file->datanext) {
4533 if (!file->write_content)
4536 if ((offset + (blocks << LOGICAL_BLOCK_BITS)) <
4537 file->content.offset_of_temp) {
4539 r = write_file_contents(a, offset,
4540 blocks << LOGICAL_BLOCK_BITS);
4545 offset = file->content.offset_of_temp;
4548 file->cur_content = &(file->content);
4550 blocks += file->cur_content->blocks;
4551 /* Next fragument */
4552 file->cur_content = file->cur_content->next;
4553 } while (file->cur_content != NULL);
4556 /* Flush out remaining blocks. */
4558 r = write_file_contents(a, offset,
4559 blocks << LOGICAL_BLOCK_BITS);
4564 return (ARCHIVE_OK);
4568 isofile_init_entry_list(struct iso9660 *iso9660)
4570 iso9660->all_file_list.first = NULL;
4571 iso9660->all_file_list.last = &(iso9660->all_file_list.first);
4575 isofile_add_entry(struct iso9660 *iso9660, struct isofile *file)
4577 file->allnext = NULL;
4578 *iso9660->all_file_list.last = file;
4579 iso9660->all_file_list.last = &(file->allnext);
4583 isofile_free_all_entries(struct iso9660 *iso9660)
4585 struct isofile *file, *file_next;
4587 file = iso9660->all_file_list.first;
4588 while (file != NULL) {
4589 file_next = file->allnext;
4596 isofile_init_entry_data_file_list(struct iso9660 *iso9660)
4598 iso9660->data_file_list.first = NULL;
4599 iso9660->data_file_list.last = &(iso9660->data_file_list.first);
4603 isofile_add_data_file(struct iso9660 *iso9660, struct isofile *file)
4605 file->datanext = NULL;
4606 *iso9660->data_file_list.last = file;
4607 iso9660->data_file_list.last = &(file->datanext);
4611 static struct isofile *
4612 isofile_new(struct archive_write *a, struct archive_entry *entry)
4614 struct isofile *file;
4616 file = calloc(1, sizeof(*file));
4621 file->entry = archive_entry_clone(entry);
4623 file->entry = archive_entry_new2(&a->archive);
4624 if (file->entry == NULL) {
4628 archive_string_init(&(file->parentdir));
4629 archive_string_init(&(file->basename));
4630 archive_string_init(&(file->basename_utf16));
4631 archive_string_init(&(file->symlink));
4632 file->cur_content = &(file->content);
4638 isofile_free(struct isofile *file)
4640 struct content *con, *tmp;
4642 con = file->content.next;
4643 while (con != NULL) {
4648 archive_entry_free(file->entry);
4649 archive_string_free(&(file->parentdir));
4650 archive_string_free(&(file->basename));
4651 archive_string_free(&(file->basename_utf16));
4652 archive_string_free(&(file->symlink));
4656 #if defined(_WIN32) || defined(__CYGWIN__)
4658 cleanup_backslash_1(char *p)
4664 if (*(unsigned char *)p > 127)
4667 /* If we have not met any multi-byte characters,
4668 * we can replace '\' with '/'. */
4681 cleanup_backslash_2(wchar_t *p)
4684 /* Convert a path-separator from '\' to '/' */
4685 while (*p != L'\0') {
4694 * Generate a parent directory name and a base name from a pathname.
4697 isofile_gen_utility_names(struct archive_write *a, struct isofile *file)
4699 struct iso9660 *iso9660;
4700 const char *pathname;
4701 char *p, *dirname, *slash;
4703 int ret = ARCHIVE_OK;
4705 iso9660 = a->format_data;
4707 archive_string_empty(&(file->parentdir));
4708 archive_string_empty(&(file->basename));
4709 archive_string_empty(&(file->basename_utf16));
4710 archive_string_empty(&(file->symlink));
4712 pathname = archive_entry_pathname(file->entry);
4713 if (pathname == NULL || pathname[0] == '\0') {/* virtual root */
4719 * Make a UTF-16BE basename if Joliet extension enabled.
4721 if (iso9660->opt.joliet) {
4722 const char *u16, *ulast;
4723 size_t u16len, ulen_last;
4725 if (iso9660->sconv_to_utf16be == NULL) {
4726 iso9660->sconv_to_utf16be =
4727 archive_string_conversion_to_charset(
4728 &(a->archive), "UTF-16BE", 1);
4729 if (iso9660->sconv_to_utf16be == NULL)
4730 /* Couldn't allocate memory */
4731 return (ARCHIVE_FATAL);
4732 iso9660->sconv_from_utf16be =
4733 archive_string_conversion_from_charset(
4734 &(a->archive), "UTF-16BE", 1);
4735 if (iso9660->sconv_from_utf16be == NULL)
4736 /* Couldn't allocate memory */
4737 return (ARCHIVE_FATAL);
4741 * Converte a filename to UTF-16BE.
4743 if (0 > archive_entry_pathname_l(file->entry, &u16, &u16len,
4744 iso9660->sconv_to_utf16be)) {
4745 if (errno == ENOMEM) {
4746 archive_set_error(&a->archive, ENOMEM,
4747 "Can't allocate memory for UTF-16BE");
4748 return (ARCHIVE_FATAL);
4750 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
4751 "A filename cannot be converted to UTF-16BE;"
4752 "You should disable making Joliet extension");
4757 * Make sure a path separator is not in the last;
4758 * Remove trailing '/'.
4760 while (u16len >= 2) {
4761 #if defined(_WIN32) || defined(__CYGWIN__)
4762 if (u16[u16len-2] == 0 &&
4763 (u16[u16len-1] == '/' || u16[u16len-1] == '\\'))
4765 if (u16[u16len-2] == 0 && u16[u16len-1] == '/')
4774 * Find a basename in UTF-16BE.
4779 while (u16len > 0) {
4780 #if defined(_WIN32) || defined(__CYGWIN__)
4781 if (u16[0] == 0 && (u16[1] == '/' || u16[1] == '\\'))
4783 if (u16[0] == 0 && u16[1] == '/')
4787 ulen_last = u16len -1;
4793 if (archive_string_ensure(&(file->basename_utf16),
4794 ulen_last) == NULL) {
4795 archive_set_error(&a->archive, ENOMEM,
4796 "Can't allocate memory for UTF-16BE");
4797 return (ARCHIVE_FATAL);
4801 * Set UTF-16BE basename.
4803 memcpy(file->basename_utf16.s, ulast, ulen_last);
4804 file->basename_utf16.length = ulen_last;
4807 archive_strcpy(&(file->parentdir), pathname);
4808 #if defined(_WIN32) || defined(__CYGWIN__)
4810 * Convert a path-separator from '\' to '/'
4812 if (cleanup_backslash_1(file->parentdir.s) != 0) {
4813 const wchar_t *wp = archive_entry_pathname_w(file->entry);
4814 struct archive_wstring ws;
4817 archive_string_init(&ws);
4818 archive_wstrcpy(&ws, wp);
4819 cleanup_backslash_2(ws.s);
4820 archive_string_empty(&(file->parentdir));
4821 archive_string_append_from_wcs(&(file->parentdir),
4823 archive_wstring_free(&ws);
4828 len = file->parentdir.length;
4829 p = dirname = file->parentdir.s;
4832 * Remove leading '/', '../' and './' elements
4838 } else if (p[0] != '.')
4840 else if (p[1] == '.' && p[2] == '/') {
4843 } else if (p[1] == '/' || (p[1] == '.' && p[2] == '\0')) {
4846 } else if (p[1] == '\0') {
4853 memmove(dirname, p, len+1);
4857 * Remove "/","/." and "/.." elements from tail.
4862 if (len > 0 && p[len-1] == '/') {
4866 if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
4870 if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
4881 /* Convert '//' --> '/' */
4883 else if (p[1] == '.' && p[2] == '/')
4884 /* Convert '/./' --> '/' */
4886 else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
4887 /* Convert 'dir/dir1/../dir2/'
4891 while (rp >= dirname) {
4900 strcpy(dirname, p+4);
4911 if (archive_entry_filetype(file->entry) == AE_IFLNK) {
4912 /* Convert symlink name too. */
4913 pathname = archive_entry_symlink(file->entry);
4914 archive_strcpy(&(file->symlink), pathname);
4915 #if defined(_WIN32) || defined(__CYGWIN__)
4917 * Convert a path-separator from '\' to '/'
4919 if (archive_strlen(&(file->symlink)) > 0 &&
4920 cleanup_backslash_1(file->symlink.s) != 0) {
4922 archive_entry_symlink_w(file->entry);
4923 struct archive_wstring ws;
4926 archive_string_init(&ws);
4927 archive_wstrcpy(&ws, wp);
4928 cleanup_backslash_2(ws.s);
4929 archive_string_empty(&(file->symlink));
4930 archive_string_append_from_wcs(
4933 archive_wstring_free(&ws);
4939 * - Count up directory elements.
4940 * - Find out the position which points the last position of
4941 * path separator('/').
4945 for (; *p != '\0'; p++)
4950 if (slash == NULL) {
4951 /* The pathname doesn't have a parent directory. */
4952 file->parentdir.length = len;
4953 archive_string_copy(&(file->basename), &(file->parentdir));
4954 archive_string_empty(&(file->parentdir));
4955 *file->parentdir.s = '\0';
4959 /* Make a basename from dirname and slash */
4961 file->parentdir.length = slash - dirname;
4962 archive_strcpy(&(file->basename), slash + 1);
4963 if (archive_entry_filetype(file->entry) == AE_IFDIR)
4969 * Register a entry to get a hardlink target.
4972 isofile_register_hardlink(struct archive_write *a, struct isofile *file)
4974 struct iso9660 *iso9660 = a->format_data;
4975 struct hardlink *hl;
4976 const char *pathname;
4978 archive_entry_set_nlink(file->entry, 1);
4979 pathname = archive_entry_hardlink(file->entry);
4980 if (pathname == NULL) {
4981 /* This `file` is a hardlink target. */
4982 hl = malloc(sizeof(*hl));
4984 archive_set_error(&a->archive, ENOMEM,
4985 "Can't allocate memory");
4986 return (ARCHIVE_FATAL);
4989 /* A hardlink target must be the first position. */
4990 file->hlnext = NULL;
4991 hl->file_list.first = file;
4992 hl->file_list.last = &(file->hlnext);
4993 __archive_rb_tree_insert_node(&(iso9660->hardlink_rbtree),
4994 (struct archive_rb_node *)hl);
4996 hl = (struct hardlink *)__archive_rb_tree_find_node(
4997 &(iso9660->hardlink_rbtree), pathname);
4999 /* Insert `file` entry into the tail. */
5000 file->hlnext = NULL;
5001 *hl->file_list.last = file;
5002 hl->file_list.last = &(file->hlnext);
5005 archive_entry_unset_size(file->entry);
5008 return (ARCHIVE_OK);
5012 * Hardlinked files have to have the same location of extent.
5013 * We have to find out hardlink target entries for the entries
5014 * which have a hardlink target name.
5017 isofile_connect_hardlink_files(struct iso9660 *iso9660)
5019 struct archive_rb_node *n;
5020 struct hardlink *hl;
5021 struct isofile *target, *nf;
5023 ARCHIVE_RB_TREE_FOREACH(n, &(iso9660->hardlink_rbtree)) {
5024 hl = (struct hardlink *)n;
5026 /* The first entry must be a hardlink target. */
5027 target = hl->file_list.first;
5028 archive_entry_set_nlink(target->entry, hl->nlink);
5029 /* Set a hardlink target to reference entries. */
5030 for (nf = target->hlnext;
5031 nf != NULL; nf = nf->hlnext) {
5032 nf->hardlink_target = target;
5033 archive_entry_set_nlink(nf->entry, hl->nlink);
5039 isofile_hd_cmp_node(const struct archive_rb_node *n1,
5040 const struct archive_rb_node *n2)
5042 const struct hardlink *h1 = (const struct hardlink *)n1;
5043 const struct hardlink *h2 = (const struct hardlink *)n2;
5045 return (strcmp(archive_entry_pathname(h1->file_list.first->entry),
5046 archive_entry_pathname(h2->file_list.first->entry)));
5050 isofile_hd_cmp_key(const struct archive_rb_node *n, const void *key)
5052 const struct hardlink *h = (const struct hardlink *)n;
5054 return (strcmp(archive_entry_pathname(h->file_list.first->entry),
5055 (const char *)key));
5059 isofile_init_hardlinks(struct iso9660 *iso9660)
5061 static const struct archive_rb_tree_ops rb_ops = {
5062 isofile_hd_cmp_node, isofile_hd_cmp_key,
5065 __archive_rb_tree_init(&(iso9660->hardlink_rbtree), &rb_ops);
5069 isofile_free_hardlinks(struct iso9660 *iso9660)
5071 struct archive_rb_node *n, *next;
5073 for (n = ARCHIVE_RB_TREE_MIN(&(iso9660->hardlink_rbtree)); n;) {
5074 next = __archive_rb_tree_iterate(&(iso9660->hardlink_rbtree),
5075 n, ARCHIVE_RB_DIR_RIGHT);
5081 static struct isoent *
5082 isoent_new(struct isofile *file)
5084 struct isoent *isoent;
5085 static const struct archive_rb_tree_ops rb_ops = {
5086 isoent_cmp_node, isoent_cmp_key,
5089 isoent = calloc(1, sizeof(*isoent));
5092 isoent->file = file;
5093 isoent->children.first = NULL;
5094 isoent->children.last = &(isoent->children.first);
5095 __archive_rb_tree_init(&(isoent->rbtree), &rb_ops);
5096 isoent->subdirs.first = NULL;
5097 isoent->subdirs.last = &(isoent->subdirs.first);
5098 isoent->extr_rec_list.first = NULL;
5099 isoent->extr_rec_list.last = &(isoent->extr_rec_list.first);
5100 isoent->extr_rec_list.current = NULL;
5101 if (archive_entry_filetype(file->entry) == AE_IFDIR)
5107 static inline struct isoent *
5108 isoent_clone(struct isoent *src)
5110 return (isoent_new(src->file));
5114 _isoent_free(struct isoent *isoent)
5116 struct extr_rec *er, *er_next;
5118 free(isoent->children_sorted);
5119 free(isoent->identifier);
5120 er = isoent->extr_rec_list.first;
5121 while (er != NULL) {
5130 isoent_free_all(struct isoent *isoent)
5132 struct isoent *np, *np_temp;
5139 if (np->children.first != NULL) {
5140 /* Enter to sub directories. */
5141 np = np->children.first;
5147 if (np->chnext == NULL) {
5148 /* Return to the parent directory. */
5150 _isoent_free(np_temp);
5155 _isoent_free(np_temp);
5162 static struct isoent *
5163 isoent_create_virtual_dir(struct archive_write *a, struct iso9660 *iso9660, const char *pathname)
5165 struct isofile *file;
5166 struct isoent *isoent;
5168 file = isofile_new(a, NULL);
5171 archive_entry_set_pathname(file->entry, pathname);
5172 archive_entry_unset_mtime(file->entry);
5173 archive_entry_unset_atime(file->entry);
5174 archive_entry_unset_ctime(file->entry);
5175 archive_entry_set_uid(file->entry, getuid());
5176 archive_entry_set_gid(file->entry, getgid());
5177 archive_entry_set_mode(file->entry, 0555 | AE_IFDIR);
5178 archive_entry_set_nlink(file->entry, 2);
5179 if (isofile_gen_utility_names(a, file) < ARCHIVE_WARN) {
5183 isofile_add_entry(iso9660, file);
5185 isoent = isoent_new(file);
5189 isoent->virtual = 1;
5195 isoent_cmp_node(const struct archive_rb_node *n1,
5196 const struct archive_rb_node *n2)
5198 const struct isoent *e1 = (const struct isoent *)n1;
5199 const struct isoent *e2 = (const struct isoent *)n2;
5201 return (strcmp(e1->file->basename.s, e2->file->basename.s));
5205 isoent_cmp_key(const struct archive_rb_node *n, const void *key)
5207 const struct isoent *e = (const struct isoent *)n;
5209 return (strcmp(e->file->basename.s, (const char *)key));
5213 isoent_add_child_head(struct isoent *parent, struct isoent *child)
5216 if (!__archive_rb_tree_insert_node(
5217 &(parent->rbtree), (struct archive_rb_node *)child))
5219 if ((child->chnext = parent->children.first) == NULL)
5220 parent->children.last = &(child->chnext);
5221 parent->children.first = child;
5222 parent->children.cnt++;
5223 child->parent = parent;
5225 /* Add a child to a sub-directory chain */
5227 if ((child->drnext = parent->subdirs.first) == NULL)
5228 parent->subdirs.last = &(child->drnext);
5229 parent->subdirs.first = child;
5230 parent->subdirs.cnt++;
5231 child->parent = parent;
5233 child->drnext = NULL;
5238 isoent_add_child_tail(struct isoent *parent, struct isoent *child)
5241 if (!__archive_rb_tree_insert_node(
5242 &(parent->rbtree), (struct archive_rb_node *)child))
5244 child->chnext = NULL;
5245 *parent->children.last = child;
5246 parent->children.last = &(child->chnext);
5247 parent->children.cnt++;
5248 child->parent = parent;
5250 /* Add a child to a sub-directory chain */
5251 child->drnext = NULL;
5253 *parent->subdirs.last = child;
5254 parent->subdirs.last = &(child->drnext);
5255 parent->subdirs.cnt++;
5256 child->parent = parent;
5262 isoent_remove_child(struct isoent *parent, struct isoent *child)
5266 /* Remove a child entry from children chain. */
5267 ent = parent->children.first;
5268 while (ent->chnext != child)
5270 if ((ent->chnext = ent->chnext->chnext) == NULL)
5271 parent->children.last = &(ent->chnext);
5272 parent->children.cnt--;
5275 /* Remove a child entry from sub-directory chain. */
5276 ent = parent->subdirs.first;
5277 while (ent->drnext != child)
5279 if ((ent->drnext = ent->drnext->drnext) == NULL)
5280 parent->subdirs.last = &(ent->drnext);
5281 parent->subdirs.cnt--;
5284 __archive_rb_tree_remove_node(&(parent->rbtree),
5285 (struct archive_rb_node *)child);
5289 isoent_clone_tree(struct archive_write *a, struct isoent **nroot,
5290 struct isoent *root)
5292 struct isoent *np, *xroot, *newent;
5297 newent = isoent_clone(np);
5298 if (newent == NULL) {
5299 archive_set_error(&a->archive, ENOMEM,
5300 "Can't allocate memory");
5301 return (ARCHIVE_FATAL);
5303 if (xroot == NULL) {
5304 *nroot = xroot = newent;
5305 newent->parent = xroot;
5307 isoent_add_child_tail(xroot, newent);
5308 if (np->dir && np->children.first != NULL) {
5309 /* Enter to sub directories. */
5310 np = np->children.first;
5314 while (np != np->parent) {
5315 if (np->chnext == NULL) {
5316 /* Return to the parent directory. */
5318 xroot = xroot->parent;
5324 } while (np != np->parent);
5326 return (ARCHIVE_OK);
5330 * Setup directory locations.
5333 isoent_setup_directory_location(struct iso9660 *iso9660, int location,
5339 vdd->total_dir_block = 0;
5345 np->dir_block = calculate_directory_descriptors(
5346 iso9660, vdd, np, depth);
5347 vdd->total_dir_block += np->dir_block;
5348 np->dir_location = location;
5349 location += np->dir_block;
5350 block = extra_setup_location(np, location);
5351 vdd->total_dir_block += block;
5354 if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) {
5355 /* Enter to sub directories. */
5356 np = np->subdirs.first;
5360 while (np != np->parent) {
5361 if (np->drnext == NULL) {
5362 /* Return to the parent directory. */
5370 } while (np != np->parent);
5374 _isoent_file_location(struct iso9660 *iso9660, struct isoent *isoent,
5377 struct isoent **children;
5380 if (isoent->children.cnt == 0)
5383 children = isoent->children_sorted;
5384 for (n = 0; n < isoent->children.cnt; n++) {
5386 struct isofile *file;
5391 if (np == iso9660->el_torito.boot)
5394 if (file->boot || file->hardlink_target != NULL)
5396 if (archive_entry_filetype(file->entry) == AE_IFLNK ||
5397 file->content.size == 0) {
5399 * Do not point a valid location.
5400 * Make sure entry is not hardlink file.
5402 file->content.location = (*symlocation)--;
5406 file->write_content = 1;
5411 * Setup file locations.
5414 isoent_setup_file_location(struct iso9660 *iso9660, int location)
5416 struct isoent *isoent;
5418 struct isofile *file;
5426 iso9660->total_file_block = 0;
5427 if ((isoent = iso9660->el_torito.catalog) != NULL) {
5428 isoent->file->content.location = location;
5429 block = (archive_entry_size(isoent->file->entry) +
5430 LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS;
5432 iso9660->total_file_block += block;
5434 if ((isoent = iso9660->el_torito.boot) != NULL) {
5435 isoent->file->content.location = location;
5436 size = fd_boot_image_size(iso9660->el_torito.media_type);
5438 size = archive_entry_size(isoent->file->entry);
5439 block = (size + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS;
5441 iso9660->total_file_block += block;
5442 isoent->file->content.blocks = block;
5447 if (!iso9660->opt.rr && iso9660->opt.joliet) {
5449 np = iso9660->joliet.rootent;
5452 np = iso9660->primary.rootent;
5455 _isoent_file_location(iso9660, np, &symlocation);
5457 if (np->subdirs.first != NULL &&
5459 ((iso9660->opt.rr == OPT_RR_DISABLED &&
5460 depth + 2 < iso9660->primary.max_depth) ||
5462 depth + 1 < iso9660->primary.max_depth)))) {
5463 /* Enter to sub directories. */
5464 np = np->subdirs.first;
5468 while (np != np->parent) {
5469 if (np->drnext == NULL) {
5470 /* Return to the parent directory. */
5478 } while (np != np->parent);
5481 for (file = iso9660->data_file_list.first;
5482 file != NULL; file = file->datanext) {
5484 if (!file->write_content)
5487 file->cur_content = &(file->content);
5489 file->cur_content->location = location;
5490 location += file->cur_content->blocks;
5491 total_block += file->cur_content->blocks;
5492 /* Next fragument */
5493 file->cur_content = file->cur_content->next;
5494 } while (file->cur_content != NULL);
5496 iso9660->total_file_block += total_block;
5500 get_path_component(char *name, int n, const char *fn)
5505 p = strchr(fn, '/');
5507 if ((l = strlen(fn)) == 0)
5513 memcpy(name, fn, l);
5520 * Add a new entry into the tree.
5523 isoent_tree(struct archive_write *a, struct isoent **isoentpp)
5525 #if defined(_WIN32) && !defined(__CYGWIN__)
5526 char name[_MAX_FNAME];/* Included null terminator size. */
5527 #elif defined(NAME_MAX) && NAME_MAX >= 255
5528 char name[NAME_MAX+1];
5532 struct iso9660 *iso9660 = a->format_data;
5533 struct isoent *dent, *isoent, *np;
5534 struct isofile *f1, *f2;
5539 dent = iso9660->primary.rootent;
5540 if (isoent->file->parentdir.length > 0)
5541 fn = p = isoent->file->parentdir.s;
5546 * If the path of the parent directory of `isoent' entry is
5547 * the same as the path of `cur_dirent', add isoent to
5550 if (archive_strlen(&(iso9660->cur_dirstr))
5551 == archive_strlen(&(isoent->file->parentdir)) &&
5552 strcmp(iso9660->cur_dirstr.s, fn) == 0) {
5553 if (!isoent_add_child_tail(iso9660->cur_dirent, isoent)) {
5554 np = (struct isoent *)__archive_rb_tree_find_node(
5555 &(iso9660->cur_dirent->rbtree),
5556 isoent->file->basename.s);
5559 return (ARCHIVE_OK);
5563 l = get_path_component(name, sizeof(name), fn);
5569 archive_set_error(&a->archive,
5571 "A name buffer is too small");
5572 _isoent_free(isoent);
5573 return (ARCHIVE_FATAL);
5576 np = isoent_find_child(dent, name);
5577 if (np == NULL || fn[0] == '\0')
5580 /* Find next subdirectory. */
5582 /* NOT Directory! */
5583 archive_set_error(&a->archive,
5585 "`%s' is not directory, we cannot insert `%s' ",
5586 archive_entry_pathname(np->file->entry),
5587 archive_entry_pathname(isoent->file->entry));
5588 _isoent_free(isoent);
5590 return (ARCHIVE_FAILED);
5599 * Create virtual parent directories.
5601 while (fn[0] != '\0') {
5603 struct archive_string as;
5605 archive_string_init(&as);
5606 archive_strncat(&as, p, fn - p + l);
5607 if (as.s[as.length-1] == '/') {
5608 as.s[as.length-1] = '\0';
5611 vp = isoent_create_virtual_dir(a, iso9660, as.s);
5613 archive_string_free(&as);
5614 archive_set_error(&a->archive, ENOMEM,
5615 "Can't allocate memory");
5616 _isoent_free(isoent);
5618 return (ARCHIVE_FATAL);
5620 archive_string_free(&as);
5622 if (vp->file->dircnt > iso9660->dircnt_max)
5623 iso9660->dircnt_max = vp->file->dircnt;
5624 isoent_add_child_tail(dent, vp);
5630 l = get_path_component(name, sizeof(name), fn);
5632 archive_string_free(&as);
5633 archive_set_error(&a->archive,
5635 "A name buffer is too small");
5636 _isoent_free(isoent);
5638 return (ARCHIVE_FATAL);
5643 /* Found out the parent directory where isoent can be
5645 iso9660->cur_dirent = dent;
5646 archive_string_empty(&(iso9660->cur_dirstr));
5647 archive_string_ensure(&(iso9660->cur_dirstr),
5648 archive_strlen(&(dent->file->parentdir)) +
5649 archive_strlen(&(dent->file->basename)) + 2);
5650 if (archive_strlen(&(dent->file->parentdir)) +
5651 archive_strlen(&(dent->file->basename)) == 0)
5652 iso9660->cur_dirstr.s[0] = 0;
5654 if (archive_strlen(&(dent->file->parentdir)) > 0) {
5655 archive_string_copy(&(iso9660->cur_dirstr),
5656 &(dent->file->parentdir));
5657 archive_strappend_char(&(iso9660->cur_dirstr), '/');
5659 archive_string_concat(&(iso9660->cur_dirstr),
5660 &(dent->file->basename));
5663 if (!isoent_add_child_tail(dent, isoent)) {
5664 np = (struct isoent *)__archive_rb_tree_find_node(
5665 &(dent->rbtree), isoent->file->basename.s);
5668 return (ARCHIVE_OK);
5673 * We have already has the entry the filename of which is
5679 /* If the file type of entries is different,
5680 * we cannot handle it. */
5681 if (archive_entry_filetype(f1->entry) !=
5682 archive_entry_filetype(f2->entry)) {
5683 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
5684 "Found duplicate entries `%s' and its file type is "
5686 archive_entry_pathname(f1->entry));
5687 _isoent_free(isoent);
5689 return (ARCHIVE_FAILED);
5692 /* Swap file entries. */
5697 _isoent_free(isoent);
5699 return (ARCHIVE_OK);
5703 * Find a entry from `isoent'
5705 static struct isoent *
5706 isoent_find_child(struct isoent *isoent, const char *child_name)
5710 np = (struct isoent *)__archive_rb_tree_find_node(
5711 &(isoent->rbtree), child_name);
5716 * Find a entry full-path of which is specified by `fn' parameter,
5719 static struct isoent *
5720 isoent_find_entry(struct isoent *rootent, const char *fn)
5722 #if defined(_WIN32) && !defined(__CYGWIN__)
5723 char name[_MAX_FNAME];/* Included null terminator size. */
5724 #elif defined(NAME_MAX) && NAME_MAX >= 255
5725 char name[NAME_MAX+1];
5729 struct isoent *isoent, *np;
5735 l = get_path_component(name, sizeof(name), fn);
5742 np = isoent_find_child(isoent, name);
5746 break;/* We found out the entry */
5748 /* Try sub directory. */
5752 break;/* Not directory */
5759 * Following idr_* functions are used for resolving duplicated filenames
5760 * and unreceivable filenames to generate ISO9660/Joliet Identifiers.
5764 idr_relaxed_filenames(char *map)
5768 for (i = 0x21; i <= 0x2F; i++)
5770 for (i = 0x3A; i <= 0x41; i++)
5772 for (i = 0x5B; i <= 0x5E; i++)
5775 for (i = 0x7B; i <= 0x7E; i++)
5780 idr_init(struct iso9660 *iso9660, struct vdd *vdd, struct idr *idr)
5783 idr->idrent_pool = NULL;
5785 if (vdd->vdd_type != VDD_JOLIET) {
5786 if (iso9660->opt.iso_level <= 3) {
5787 memcpy(idr->char_map, d_characters_map,
5788 sizeof(idr->char_map));
5790 memcpy(idr->char_map, d1_characters_map,
5791 sizeof(idr->char_map));
5792 idr_relaxed_filenames(idr->char_map);
5798 idr_cleanup(struct idr *idr)
5800 free(idr->idrent_pool);
5804 idr_ensure_poolsize(struct archive_write *a, struct idr *idr,
5808 if (idr->pool_size < cnt) {
5809 const int bk = (1 << 7) - 1;
5812 psize = (cnt + bk) & ~bk;
5813 idr->idrent_pool = realloc(idr->idrent_pool,
5814 sizeof(struct idrent) * psize);
5815 if (idr->idrent_pool == NULL) {
5816 archive_set_error(&a->archive, ENOMEM,
5817 "Can't allocate memory");
5818 return (ARCHIVE_FATAL);
5820 idr->pool_size = psize;
5822 return (ARCHIVE_OK);
5826 idr_start(struct archive_write *a, struct idr *idr, int cnt, int ffmax,
5827 int num_size, int null_size, const struct archive_rb_tree_ops *rbt_ops)
5831 (void)ffmax; /* UNUSED */
5833 r = idr_ensure_poolsize(a, idr, cnt);
5834 if (r != ARCHIVE_OK)
5836 __archive_rb_tree_init(&(idr->rbtree), rbt_ops);
5837 idr->wait_list.first = NULL;
5838 idr->wait_list.last = &(idr->wait_list.first);
5840 idr->num_size = num_size;
5841 idr->null_size = null_size;
5842 return (ARCHIVE_OK);
5846 idr_register(struct idr *idr, struct isoent *isoent, int weight, int noff)
5848 struct idrent *idrent, *n;
5850 idrent = &(idr->idrent_pool[idr->pool_idx++]);
5851 idrent->wnext = idrent->avail = NULL;
5852 idrent->isoent = isoent;
5853 idrent->weight = weight;
5854 idrent->noff = noff;
5855 idrent->rename_num = 0;
5857 if (!__archive_rb_tree_insert_node(&(idr->rbtree), &(idrent->rbnode))) {
5858 n = (struct idrent *)__archive_rb_tree_find_node(
5859 &(idr->rbtree), idrent->isoent);
5861 /* this `idrent' needs to rename. */
5863 *idr->wait_list.last = idrent;
5864 idr->wait_list.last = &(idrent->wnext);
5870 idr_extend_identifier(struct idrent *wnp, int numsize, int nullsize)
5875 wnp_ext_off = wnp->isoent->ext_off;
5876 if (wnp->noff + numsize != wnp_ext_off) {
5877 p = (unsigned char *)wnp->isoent->identifier;
5878 /* Extend the filename; foo.c --> foo___.c */
5879 memmove(p + wnp->noff + numsize, p + wnp_ext_off,
5880 wnp->isoent->ext_len + nullsize);
5881 wnp->isoent->ext_off = wnp_ext_off = wnp->noff + numsize;
5882 wnp->isoent->id_len = wnp_ext_off + wnp->isoent->ext_len;
5887 idr_resolve(struct idr *idr, void (*fsetnum)(unsigned char *p, int num))
5892 for (n = idr->wait_list.first; n != NULL; n = n->wnext) {
5893 idr_extend_identifier(n, idr->num_size, idr->null_size);
5894 p = (unsigned char *)n->isoent->identifier + n->noff;
5896 fsetnum(p, n->avail->rename_num++);
5897 } while (!__archive_rb_tree_insert_node(
5898 &(idr->rbtree), &(n->rbnode)));
5903 idr_set_num(unsigned char *p, int num)
5905 static const char xdig[] = {
5906 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
5907 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
5908 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
5909 'U', 'V', 'W', 'X', 'Y', 'Z'
5912 num %= sizeof(xdig) * sizeof(xdig) * sizeof(xdig);
5913 p[0] = xdig[(num / (sizeof(xdig) * sizeof(xdig)))];
5914 num %= sizeof(xdig) * sizeof(xdig);
5915 p[1] = xdig[ (num / sizeof(xdig))];
5916 num %= sizeof(xdig);
5921 idr_set_num_beutf16(unsigned char *p, int num)
5923 static const uint16_t xdig[] = {
5924 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
5925 0x0036, 0x0037, 0x0038, 0x0039,
5926 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046,
5927 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C,
5928 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052,
5929 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
5932 #define XDIG_CNT (sizeof(xdig)/sizeof(xdig[0]))
5934 num %= XDIG_CNT * XDIG_CNT * XDIG_CNT;
5935 archive_be16enc(p, xdig[(num / (XDIG_CNT * XDIG_CNT))]);
5936 num %= XDIG_CNT * XDIG_CNT;
5937 archive_be16enc(p+2, xdig[ (num / XDIG_CNT)]);
5939 archive_be16enc(p+4, xdig[num]);
5943 * Generate ISO9660 Identifier.
5946 isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent,
5949 struct iso9660 *iso9660;
5953 const char *char_map;
5954 char allow_ldots, allow_multidot, allow_period, allow_vernum;
5955 int fnmax, ffmax, dnmax;
5956 static const struct archive_rb_tree_ops rb_ops = {
5957 isoent_cmp_node_iso9660, isoent_cmp_key_iso9660
5960 if (isoent->children.cnt == 0)
5963 iso9660 = a->format_data;
5964 char_map = idr->char_map;
5965 if (iso9660->opt.iso_level <= 3) {
5969 allow_vernum = iso9660->opt.allow_vernum;
5970 if (iso9660->opt.iso_level == 1) {
5972 ffmax = 12;/* fnmax + '.' + 3 */
5980 allow_ldots = allow_multidot = 1;
5981 allow_period = allow_vernum = 0;
5982 if (iso9660->opt.rr)
5984 * MDR : The maximum size of Directory Record(254).
5985 * DRL : A Directory Record Length(33).
5986 * CE : A size of SUSP CE System Use Entry(28).
5987 * MDR - DRL - CE = 254 - 33 - 28 = 193.
5989 fnmax = ffmax = dnmax = 193;
5992 * XA : CD-ROM XA System Use Extension
5994 * MDR - DRL - XA = 254 - 33 -14 = 207.
5996 fnmax = ffmax = dnmax = 207;
5999 r = idr_start(a, idr, isoent->children.cnt, ffmax, 3, 1, &rb_ops);
6003 for (np = isoent->children.first; np != NULL; np = np->chnext) {
6005 int ext_off, noff, weight;
6007 l = np->file->basename.length;
6008 p = malloc(l+31+2+1);
6010 archive_set_error(&a->archive, ENOMEM,
6011 "Can't allocate memory");
6012 return (ARCHIVE_FATAL);
6014 memcpy(p, np->file->basename.s, l);
6021 * If there is a '.' character at the first byte,
6022 * it has to be replaced by '_' character.
6032 if (char_map[(unsigned char)*p]) {
6033 /* if iso-level is '4', a character '.' is
6034 * allowed by char_map. */
6041 if (*p >= 'a' && *p <= 'z') {
6073 if (iso9660->opt.iso_level == 1) {
6075 if (strlen(dot) > 4) {
6076 /* A length of a file extension
6077 * must be less than 4 */
6090 } else if (np->dir) {
6094 if (ext_off > dnmax)
6097 } else if (l > ffmax) {
6098 int extlen = strlen(dot);
6106 if (extlen > 1 && xdoff < fnmax-1) {
6111 off = ffmax - extlen;
6113 /* A dot('.') character
6114 * does't place to the first
6115 * byte of identifier. */
6119 memmove(p+off, dot, extlen);
6123 #ifdef COMPAT_MKISOFS
6124 } else if (xdoff >= fnmax-1) {
6125 /* Simulate a bug(?) of mkisofs. */
6137 /* Save an offset of a file name extension to sort files. */
6138 np->ext_off = ext_off;
6139 np->ext_len = strlen(&p[ext_off]);
6140 np->id_len = l = ext_off + np->ext_len;
6142 /* Make an offset of the number which is used to be set
6143 * hexadecimal number to avoid duplicate identififier. */
6144 if (iso9660->opt.iso_level == 1) {
6152 else if (l == ffmax-1)
6154 else if (l == ffmax-2)
6159 /* Register entry to the identifier resolver. */
6160 idr_register(idr, np, weight, noff);
6163 /* Resolve duplicate identifier. */
6164 idr_resolve(idr, idr_set_num);
6166 /* Add a period and a version number to identifiers. */
6167 for (np = isoent->children.first; np != NULL; np = np->chnext) {
6168 if (!np->dir && np->rr_child == NULL) {
6169 p = np->identifier + np->ext_off + np->ext_len;
6170 if (np->ext_len == 0 && allow_period) {
6174 if (np->ext_len == 1 && !allow_period) {
6178 np->id_len = np->ext_off + np->ext_len;
6186 np->id_len = np->ext_off + np->ext_len;
6187 np->mb_len = np->id_len;
6189 return (ARCHIVE_OK);
6193 * Generate Joliet Identifier.
6196 isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent,
6199 struct iso9660 *iso9660;
6204 int ffmax, parent_len;
6205 static const struct archive_rb_tree_ops rb_ops = {
6206 isoent_cmp_node_joliet, isoent_cmp_key_joliet
6209 if (isoent->children.cnt == 0)
6212 iso9660 = a->format_data;
6213 if (iso9660->opt.joliet == OPT_JOLIET_LONGNAME)
6218 r = idr_start(a, idr, isoent->children.cnt, ffmax, 6, 2, &rb_ops);
6223 for (np = isoent; np->parent != np; np = np->parent)
6224 parent_len += np->mb_len + 1;
6226 for (np = isoent->children.first; np != NULL; np = np->chnext) {
6228 int ext_off, noff, weight;
6231 if ((int)(l = np->file->basename_utf16.length) > ffmax)
6234 p = malloc((l+1)*2);
6236 archive_set_error(&a->archive, ENOMEM,
6237 "Can't allocate memory");
6238 return (ARCHIVE_FATAL);
6240 memcpy(p, np->file->basename_utf16.s, l);
6244 np->identifier = (char *)p;
6249 if (!joliet_allowed_char(p[0], p[1]))
6250 archive_be16enc(p, 0x005F); /* '_' */
6251 else if (p[0] == 0 && p[1] == 0x2E) /* '.' */
6256 ext_off = dot - (unsigned char *)np->identifier;
6257 np->ext_off = ext_off;
6258 np->ext_len = l - ext_off;
6262 * Get a length of MBS of a full-pathname.
6264 if ((int)np->file->basename_utf16.length > ffmax) {
6265 archive_strncpy_in_locale(&iso9660->mbs,
6266 (const char *)np->identifier, l,
6267 iso9660->sconv_from_utf16be);
6268 np->mb_len = iso9660->mbs.length;
6269 if (np->mb_len != (int)np->file->basename.length)
6270 weight = np->mb_len;
6272 np->mb_len = np->file->basename.length;
6274 /* If a length of full-pathname is longer than 240 bytes,
6275 * it violates Joliet extensions regulation. */
6276 if (parent_len + np->mb_len > 240) {
6277 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
6278 "The regulation of Joliet extensions;"
6279 " A length of a full-pathname of `%s' is "
6280 "longer than 240 bytes, (p=%d, b=%d)",
6281 archive_entry_pathname(np->file->entry),
6282 (int)parent_len, (int)np->mb_len);
6283 return (ARCHIVE_FATAL);
6286 /* Make an offset of the number which is used to be set
6287 * hexadecimal number to avoid duplicate identifier. */
6288 if ((int)l == ffmax)
6290 else if ((int)l == ffmax-2)
6292 else if ((int)l == ffmax-4)
6296 /* Register entry to the identifier resolver. */
6297 idr_register(idr, np, weight, noff);
6300 /* Resolve duplicate identifier with Joliet Volume. */
6301 idr_resolve(idr, idr_set_num_beutf16);
6303 return (ARCHIVE_OK);
6307 * This comparing rule is according to ISO9660 Standard 9.3
6310 isoent_cmp_iso9660_identifier(const struct isoent *p1, const struct isoent *p2)
6312 const char *s1, *s2;
6316 s1 = p1->identifier;
6317 s2 = p2->identifier;
6319 /* Compare File Name */
6321 if (l > p2->ext_off)
6323 cmp = memcmp(s1, s2, l);
6326 if (p1->ext_off < p2->ext_off) {
6328 l = p2->ext_off - p1->ext_off;
6332 - *(const unsigned char *)(s2 - 1));
6333 } else if (p1->ext_off > p2->ext_off) {
6335 l = p1->ext_off - p2->ext_off;
6338 return (*(const unsigned char *)(s1 - 1)
6341 /* Compare File Name Extension */
6342 if (p1->ext_len == 0 && p2->ext_len == 0)
6344 if (p1->ext_len == 1 && p2->ext_len == 1)
6346 if (p1->ext_len <= 1)
6348 if (p2->ext_len <= 1)
6351 if (l > p2->ext_len)
6353 s1 = p1->identifier + p1->ext_off;
6354 s2 = p2->identifier + p2->ext_off;
6356 cmp = memcmp(s1, s2, l);
6360 if (p1->ext_len < p2->ext_len) {
6362 l = p2->ext_len - p1->ext_len;
6366 - *(const unsigned char *)(s2 - 1));
6367 } else if (p1->ext_len < p2->ext_len) {
6369 l = p1->ext_len - p2->ext_len;
6372 return (*(const unsigned char *)(s1 - 1)
6375 /* Compare File Version Number */
6376 /* No operation. The File Version Number is always one. */
6382 isoent_cmp_node_iso9660(const struct archive_rb_node *n1,
6383 const struct archive_rb_node *n2)
6385 const struct idrent *e1 = (const struct idrent *)n1;
6386 const struct idrent *e2 = (const struct idrent *)n2;
6388 return (isoent_cmp_iso9660_identifier(e2->isoent, e1->isoent));
6392 isoent_cmp_key_iso9660(const struct archive_rb_node *node, const void *key)
6394 const struct isoent *isoent = (const struct isoent *)key;
6395 const struct idrent *idrent = (const struct idrent *)node;
6397 return (isoent_cmp_iso9660_identifier(isoent, idrent->isoent));
6401 isoent_cmp_joliet_identifier(const struct isoent *p1, const struct isoent *p2)
6403 const unsigned char *s1, *s2;
6407 s1 = (const unsigned char *)p1->identifier;
6408 s2 = (const unsigned char *)p2->identifier;
6410 /* Compare File Name */
6412 if (l > p2->ext_off)
6414 cmp = memcmp(s1, s2, l);
6417 if (p1->ext_off < p2->ext_off) {
6419 l = p2->ext_off - p1->ext_off;
6422 return (- *(const unsigned char *)(s2 - 1));
6423 } else if (p1->ext_off > p2->ext_off) {
6425 l = p1->ext_off - p2->ext_off;
6428 return (*(const unsigned char *)(s1 - 1));
6430 /* Compare File Name Extension */
6431 if (p1->ext_len == 0 && p2->ext_len == 0)
6433 if (p1->ext_len == 2 && p2->ext_len == 2)
6435 if (p1->ext_len <= 2)
6437 if (p2->ext_len <= 2)
6440 if (l > p2->ext_len)
6442 s1 = (unsigned char *)(p1->identifier + p1->ext_off);
6443 s2 = (unsigned char *)(p2->identifier + p2->ext_off);
6445 cmp = memcmp(s1, s2, l);
6449 if (p1->ext_len < p2->ext_len) {
6451 l = p2->ext_len - p1->ext_len;
6454 return (- *(const unsigned char *)(s2 - 1));
6455 } else if (p1->ext_len < p2->ext_len) {
6457 l = p1->ext_len - p2->ext_len;
6460 return (*(const unsigned char *)(s1 - 1));
6462 /* Compare File Version Number */
6463 /* No operation. The File Version Number is always one. */
6469 isoent_cmp_node_joliet(const struct archive_rb_node *n1,
6470 const struct archive_rb_node *n2)
6472 const struct idrent *e1 = (const struct idrent *)n1;
6473 const struct idrent *e2 = (const struct idrent *)n2;
6475 return (isoent_cmp_joliet_identifier(e2->isoent, e1->isoent));
6479 isoent_cmp_key_joliet(const struct archive_rb_node *node, const void *key)
6481 const struct isoent *isoent = (const struct isoent *)key;
6482 const struct idrent *idrent = (const struct idrent *)node;
6484 return (isoent_cmp_joliet_identifier(isoent, idrent->isoent));
6488 isoent_make_sorted_files(struct archive_write *a, struct isoent *isoent,
6491 struct archive_rb_node *rn;
6492 struct isoent **children;
6494 children = malloc(isoent->children.cnt * sizeof(struct isoent *));
6495 if (children == NULL) {
6496 archive_set_error(&a->archive, ENOMEM,
6497 "Can't allocate memory");
6498 return (ARCHIVE_FATAL);
6500 isoent->children_sorted = children;
6502 ARCHIVE_RB_TREE_FOREACH(rn, &(idr->rbtree)) {
6503 struct idrent *idrent = (struct idrent *)rn;
6504 *children ++ = idrent->isoent;
6506 return (ARCHIVE_OK);
6510 * - Generate ISO9660 and Joliet identifiers from basenames.
6511 * - Sort files by each directory.
6514 isoent_traverse_tree(struct archive_write *a, struct vdd* vdd)
6516 struct iso9660 *iso9660 = a->format_data;
6521 int (*genid)(struct archive_write *, struct isoent *, struct idr *);
6523 idr_init(iso9660, vdd, &idr);
6526 if (vdd->vdd_type == VDD_JOLIET)
6527 genid = isoent_gen_joliet_identifier;
6529 genid = isoent_gen_iso9660_identifier;
6532 !archive_entry_mtime_is_set(np->file->entry)) {
6533 /* Set properly times to virtual directory */
6534 archive_entry_set_mtime(np->file->entry,
6535 iso9660->birth_time, 0);
6536 archive_entry_set_atime(np->file->entry,
6537 iso9660->birth_time, 0);
6538 archive_entry_set_ctime(np->file->entry,
6539 iso9660->birth_time, 0);
6541 if (np->children.first != NULL) {
6542 if (vdd->vdd_type != VDD_JOLIET &&
6543 !iso9660->opt.rr && depth + 1 >= vdd->max_depth) {
6544 if (np->children.cnt > 0)
6545 iso9660->directories_too_deep = np;
6547 /* Generate Identifier */
6548 r = genid(a, np, &idr);
6550 goto exit_traverse_tree;
6551 r = isoent_make_sorted_files(a, np, &idr);
6553 goto exit_traverse_tree;
6555 if (np->subdirs.first != NULL &&
6556 depth + 1 < vdd->max_depth) {
6557 /* Enter to sub directories. */
6558 np = np->subdirs.first;
6564 while (np != np->parent) {
6565 if (np->drnext == NULL) {
6566 /* Return to the parent directory. */
6574 } while (np != np->parent);
6584 * Collect directory entries into path_table by a directory depth.
6587 isoent_collect_dirs(struct vdd *vdd, struct isoent *rootent, int depth)
6591 if (rootent == NULL)
6592 rootent = vdd->rootent;
6595 /* Register current directory to pathtable. */
6596 path_table_add_entry(&(vdd->pathtbl[depth]), np);
6598 if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) {
6599 /* Enter to sub directories. */
6600 np = np->subdirs.first;
6604 while (np != rootent) {
6605 if (np->drnext == NULL) {
6606 /* Return to the parent directory. */
6614 } while (np != rootent);
6616 return (ARCHIVE_OK);
6620 * The entry whose number of levels in a directory hierarchy is
6621 * large than eight relocate to rr_move directory.
6624 isoent_rr_move_dir(struct archive_write *a, struct isoent **rr_moved,
6625 struct isoent *isoent, struct isoent **newent)
6627 struct iso9660 *iso9660 = a->format_data;
6628 struct isoent *rrmoved, *mvent, *np;
6630 if ((rrmoved = *rr_moved) == NULL) {
6631 struct isoent *rootent = iso9660->primary.rootent;
6632 /* There isn't rr_move entry.
6633 * Create rr_move entry and insert it into the root entry.
6635 rrmoved = isoent_create_virtual_dir(a, iso9660, "rr_moved");
6636 if (rrmoved == NULL) {
6637 archive_set_error(&a->archive, ENOMEM,
6638 "Can't allocate memory");
6639 return (ARCHIVE_FATAL);
6641 /* Add "rr_moved" entry to the root entry. */
6642 isoent_add_child_head(rootent, rrmoved);
6643 archive_entry_set_nlink(rootent->file->entry,
6644 archive_entry_nlink(rootent->file->entry) + 1);
6645 /* Register "rr_moved" entry to second level pathtable. */
6646 path_table_add_entry(&(iso9660->primary.pathtbl[1]), rrmoved);
6647 /* Save rr_moved. */
6648 *rr_moved = rrmoved;
6651 * Make a clone of isoent which is going to be relocated
6654 mvent = isoent_clone(isoent);
6655 if (mvent == NULL) {
6656 archive_set_error(&a->archive, ENOMEM,
6657 "Can't allocate memory");
6658 return (ARCHIVE_FATAL);
6660 /* linking.. and use for creating "CL", "PL" and "RE" */
6661 mvent->rr_parent = isoent->parent;
6662 isoent->rr_child = mvent;
6664 * Move subdirectories from the isoent to mvent
6666 if (isoent->children.first != NULL) {
6667 *mvent->children.last = isoent->children.first;
6668 mvent->children.last = isoent->children.last;
6670 for (np = mvent->children.first; np != NULL; np = np->chnext)
6672 mvent->children.cnt = isoent->children.cnt;
6673 isoent->children.cnt = 0;
6674 isoent->children.first = NULL;
6675 isoent->children.last = &isoent->children.first;
6677 if (isoent->subdirs.first != NULL) {
6678 *mvent->subdirs.last = isoent->subdirs.first;
6679 mvent->subdirs.last = isoent->subdirs.last;
6681 mvent->subdirs.cnt = isoent->subdirs.cnt;
6682 isoent->subdirs.cnt = 0;
6683 isoent->subdirs.first = NULL;
6684 isoent->subdirs.last = &isoent->subdirs.first;
6687 * The mvent becomes a child of the rr_moved entry.
6689 isoent_add_child_tail(rrmoved, mvent);
6690 archive_entry_set_nlink(rrmoved->file->entry,
6691 archive_entry_nlink(rrmoved->file->entry) + 1);
6693 * This entry which relocated to the rr_moved directory
6694 * has to set the flag as a file.
6695 * See also RRIP 4.1.5.1 Description of the "CL" System Use Entry.
6701 return (ARCHIVE_OK);
6705 isoent_rr_move(struct archive_write *a)
6707 struct iso9660 *iso9660 = a->format_data;
6708 struct path_table *pt;
6709 struct isoent *rootent, *rr_moved;
6710 struct isoent *np, *last;
6713 pt = &(iso9660->primary.pathtbl[MAX_DEPTH-1]);
6714 /* Theare aren't level 8 directories reaching a deepr level. */
6716 return (ARCHIVE_OK);
6718 rootent = iso9660->primary.rootent;
6719 /* If "rr_moved" directory is already existing,
6720 * we have to use it. */
6721 rr_moved = isoent_find_child(rootent, "rr_moved");
6722 if (rr_moved != NULL &&
6723 rr_moved != rootent->children.first) {
6725 * It's necessary that rr_move is the first entry
6728 /* Remove "rr_moved" entry from children chain. */
6729 isoent_remove_child(rootent, rr_moved);
6731 /* Add "rr_moved" entry into the head of children chain. */
6732 isoent_add_child_head(rootent, rr_moved);
6736 * Check level 8 path_table.
6737 * If find out sub directory entries, that entries move to rr_move.
6740 while (np != NULL) {
6741 last = path_table_last_entry(pt);
6742 for (; np != NULL; np = np->ptnext) {
6743 struct isoent *mvent;
6744 struct isoent *newent;
6748 for (mvent = np->subdirs.first;
6749 mvent != NULL; mvent = mvent->drnext) {
6750 r = isoent_rr_move_dir(a, &rr_moved,
6754 isoent_collect_dirs(&(iso9660->primary),
6758 /* If new entries are added to level 8 path_talbe,
6759 * its sub directory entries move to rr_move too.
6764 return (ARCHIVE_OK);
6768 * This comparing rule is according to ISO9660 Standard 6.9.1
6771 _compare_path_table(const void *v1, const void *v2)
6773 const struct isoent *p1, *p2;
6774 const char *s1, *s2;
6777 p1 = *((const struct isoent **)(uintptr_t)v1);
6778 p2 = *((const struct isoent **)(uintptr_t)v2);
6780 /* Compare parent directory number */
6781 cmp = p1->parent->dir_number - p2->parent->dir_number;
6785 /* Compare indetifier */
6786 s1 = p1->identifier;
6787 s2 = p2->identifier;
6789 if (l > p2->ext_off)
6791 cmp = strncmp(s1, s2, l);
6794 if (p1->ext_off < p2->ext_off) {
6796 l = p2->ext_off - p1->ext_off;
6800 - *(const unsigned char *)(s2 - 1));
6801 } else if (p1->ext_off > p2->ext_off) {
6803 l = p1->ext_off - p2->ext_off;
6806 return (*(const unsigned char *)(s1 - 1)
6813 _compare_path_table_joliet(const void *v1, const void *v2)
6815 const struct isoent *p1, *p2;
6816 const unsigned char *s1, *s2;
6819 p1 = *((const struct isoent **)(uintptr_t)v1);
6820 p2 = *((const struct isoent **)(uintptr_t)v2);
6822 /* Compare parent directory number */
6823 cmp = p1->parent->dir_number - p2->parent->dir_number;
6827 /* Compare indetifier */
6828 s1 = (const unsigned char *)p1->identifier;
6829 s2 = (const unsigned char *)p2->identifier;
6831 if (l > p2->ext_off)
6833 cmp = memcmp(s1, s2, l);
6836 if (p1->ext_off < p2->ext_off) {
6838 l = p2->ext_off - p1->ext_off;
6841 return (- *(const unsigned char *)(s2 - 1));
6842 } else if (p1->ext_off > p2->ext_off) {
6844 l = p1->ext_off - p2->ext_off;
6847 return (*(const unsigned char *)(s1 - 1));
6853 path_table_add_entry(struct path_table *pathtbl, struct isoent *ent)
6856 *pathtbl->last = ent;
6857 pathtbl->last = &(ent->ptnext);
6861 static inline struct isoent *
6862 path_table_last_entry(struct path_table *pathtbl)
6864 if (pathtbl->first == NULL)
6866 return (((struct isoent *)(void *)
6867 ((char *)(pathtbl->last) - offsetof(struct isoent, ptnext))));
6871 * Sort directory entries in path_table
6872 * and assign directory number to each entries.
6875 isoent_make_path_table_2(struct archive_write *a, struct vdd *vdd,
6876 int depth, int *dir_number)
6879 struct isoent **enttbl;
6880 struct path_table *pt;
6883 pt = &vdd->pathtbl[depth];
6886 return (ARCHIVE_OK);
6888 enttbl = malloc(pt->cnt * sizeof(struct isoent *));
6889 if (enttbl == NULL) {
6890 archive_set_error(&a->archive, ENOMEM,
6891 "Can't allocate memory");
6892 return (ARCHIVE_FATAL);
6894 pt->sorted = enttbl;
6895 for (np = pt->first; np != NULL; np = np->ptnext)
6897 enttbl = pt->sorted;
6899 switch (vdd->vdd_type) {
6902 qsort(enttbl, pt->cnt, sizeof(struct isoent *),
6903 _compare_path_table);
6906 qsort(enttbl, pt->cnt, sizeof(struct isoent *),
6907 _compare_path_table_joliet);
6910 for (i = 0; i < pt->cnt; i++)
6911 enttbl[i]->dir_number = (*dir_number)++;
6913 return (ARCHIVE_OK);
6917 isoent_alloc_path_table(struct archive_write *a, struct vdd *vdd,
6922 vdd->max_depth = max_depth;
6923 vdd->pathtbl = malloc(sizeof(*vdd->pathtbl) * vdd->max_depth);
6924 if (vdd->pathtbl == NULL) {
6925 archive_set_error(&a->archive, ENOMEM,
6926 "Can't allocate memory");
6927 return (ARCHIVE_FATAL);
6929 for (i = 0; i < vdd->max_depth; i++) {
6930 vdd->pathtbl[i].first = NULL;
6931 vdd->pathtbl[i].last = &(vdd->pathtbl[i].first);
6932 vdd->pathtbl[i].sorted = NULL;
6933 vdd->pathtbl[i].cnt = 0;
6935 return (ARCHIVE_OK);
6942 isoent_make_path_table(struct archive_write *a)
6944 struct iso9660 *iso9660 = a->format_data;
6951 if (iso9660->dircnt_max >= MAX_DEPTH &&
6952 (!iso9660->opt.limit_depth || iso9660->opt.iso_level == 4))
6953 r = isoent_alloc_path_table(a, &(iso9660->primary),
6954 iso9660->dircnt_max + 1);
6956 /* The number of levels in the hierarchy cannot exceed
6958 r = isoent_alloc_path_table(a, &(iso9660->primary),
6962 if (iso9660->opt.joliet) {
6963 r = isoent_alloc_path_table(a, &(iso9660->joliet),
6964 iso9660->dircnt_max + 1);
6970 * - Collect directories for primary and joliet.
6972 isoent_collect_dirs(&(iso9660->primary), NULL, 0);
6973 if (iso9660->opt.joliet)
6974 isoent_collect_dirs(&(iso9660->joliet), NULL, 0);
6976 * Rockridge; move deeper depth directories to rr_moved.
6978 if (iso9660->opt.rr) {
6979 r = isoent_rr_move(a);
6985 isofile_connect_hardlink_files(iso9660);
6988 * - Renew a value of the depth of that directories.
6989 * - Resolve hardlinks.
6990 * - Convert pathnames to ISO9660 name or UCS2(joliet).
6991 * - Sort files by each directory.
6993 r = isoent_traverse_tree(a, &(iso9660->primary));
6996 if (iso9660->opt.joliet) {
6997 r = isoent_traverse_tree(a, &(iso9660->joliet));
7003 * - Sort directories.
7004 * - Assign all directory number.
7007 for (depth = 0; depth < iso9660->primary.max_depth; depth++) {
7008 r = isoent_make_path_table_2(a, &(iso9660->primary),
7009 depth, &dir_number);
7013 if (iso9660->opt.joliet) {
7015 for (depth = 0; depth < iso9660->joliet.max_depth; depth++) {
7016 r = isoent_make_path_table_2(a, &(iso9660->joliet),
7017 depth, &dir_number);
7022 if (iso9660->opt.limit_dirs && dir_number > 0xffff) {
7024 * Maximum number of directories is 65535(0xffff)
7025 * doe to size(16bit) of Parent Directory Number of
7027 * See also ISO9660 Standard 9.4.
7029 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7030 "Too many directories(%d) over 65535.", dir_number);
7031 return (ARCHIVE_FATAL);
7034 /* Get the size of the Path Table. */
7035 calculate_path_table_size(&(iso9660->primary));
7036 if (iso9660->opt.joliet)
7037 calculate_path_table_size(&(iso9660->joliet));
7039 return (ARCHIVE_OK);
7043 isoent_find_out_boot_file(struct archive_write *a, struct isoent *rootent)
7045 struct iso9660 *iso9660 = a->format_data;
7047 /* Find a isoent of the boot file. */
7048 iso9660->el_torito.boot = isoent_find_entry(rootent,
7049 iso9660->el_torito.boot_filename.s);
7050 if (iso9660->el_torito.boot == NULL) {
7051 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7052 "Can't find the boot image file ``%s''",
7053 iso9660->el_torito.boot_filename.s);
7054 return (ARCHIVE_FATAL);
7056 iso9660->el_torito.boot->file->boot = BOOT_IMAGE;
7057 return (ARCHIVE_OK);
7061 isoent_create_boot_catalog(struct archive_write *a, struct isoent *rootent)
7063 struct iso9660 *iso9660 = a->format_data;
7064 struct isofile *file;
7065 struct isoent *isoent;
7066 struct archive_entry *entry;
7068 (void)rootent; /* UNUSED */
7070 * Create the entry which is the "boot.catalog" file.
7072 file = isofile_new(a, NULL);
7074 archive_set_error(&a->archive, ENOMEM,
7075 "Can't allocate memory");
7076 return (ARCHIVE_FATAL);
7078 archive_entry_set_pathname(file->entry,
7079 iso9660->el_torito.catalog_filename.s);
7080 archive_entry_set_size(file->entry, LOGICAL_BLOCK_SIZE);
7081 archive_entry_set_mtime(file->entry, iso9660->birth_time, 0);
7082 archive_entry_set_atime(file->entry, iso9660->birth_time, 0);
7083 archive_entry_set_ctime(file->entry, iso9660->birth_time, 0);
7084 archive_entry_set_uid(file->entry, getuid());
7085 archive_entry_set_gid(file->entry, getgid());
7086 archive_entry_set_mode(file->entry, AE_IFREG | 0444);
7087 archive_entry_set_nlink(file->entry, 1);
7089 if (isofile_gen_utility_names(a, file) < ARCHIVE_WARN) {
7091 return (ARCHIVE_FATAL);
7093 file->boot = BOOT_CATALOG;
7094 file->content.size = LOGICAL_BLOCK_SIZE;
7095 isofile_add_entry(iso9660, file);
7097 isoent = isoent_new(file);
7098 if (isoent == NULL) {
7099 archive_set_error(&a->archive, ENOMEM,
7100 "Can't allocate memory");
7101 return (ARCHIVE_FATAL);
7103 isoent->virtual = 1;
7105 /* Add the "boot.catalog" entry into tree */
7106 if (isoent_tree(a, &isoent) != ARCHIVE_OK)
7107 return (ARCHIVE_FATAL);
7109 iso9660->el_torito.catalog = isoent;
7111 * Get a boot medai type.
7113 switch (iso9660->opt.boot_type) {
7115 case OPT_BOOT_TYPE_AUTO:
7116 /* Try detecting a media type of the boot image. */
7117 entry = iso9660->el_torito.boot->file->entry;
7118 if (archive_entry_size(entry) == FD_1_2M_SIZE)
7119 iso9660->el_torito.media_type =
7120 BOOT_MEDIA_1_2M_DISKETTE;
7121 else if (archive_entry_size(entry) == FD_1_44M_SIZE)
7122 iso9660->el_torito.media_type =
7123 BOOT_MEDIA_1_44M_DISKETTE;
7124 else if (archive_entry_size(entry) == FD_2_88M_SIZE)
7125 iso9660->el_torito.media_type =
7126 BOOT_MEDIA_2_88M_DISKETTE;
7128 /* We cannot decide whether the boot image is
7130 iso9660->el_torito.media_type =
7131 BOOT_MEDIA_NO_EMULATION;
7133 case OPT_BOOT_TYPE_NO_EMU:
7134 iso9660->el_torito.media_type = BOOT_MEDIA_NO_EMULATION;
7136 case OPT_BOOT_TYPE_HARD_DISK:
7137 iso9660->el_torito.media_type = BOOT_MEDIA_HARD_DISK;
7139 case OPT_BOOT_TYPE_FD:
7140 entry = iso9660->el_torito.boot->file->entry;
7141 if (archive_entry_size(entry) <= FD_1_2M_SIZE)
7142 iso9660->el_torito.media_type =
7143 BOOT_MEDIA_1_2M_DISKETTE;
7144 else if (archive_entry_size(entry) <= FD_1_44M_SIZE)
7145 iso9660->el_torito.media_type =
7146 BOOT_MEDIA_1_44M_DISKETTE;
7147 else if (archive_entry_size(entry) <= FD_2_88M_SIZE)
7148 iso9660->el_torito.media_type =
7149 BOOT_MEDIA_2_88M_DISKETTE;
7151 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7152 "Boot image file(``%s'') size is too big "
7154 iso9660->el_torito.boot_filename.s);
7155 return (ARCHIVE_FATAL);
7161 * Get a system type.
7162 * TODO: `El Torito' specification says "A copy of byte 5 from the
7163 * Partition Table found in the boot image".
7165 iso9660->el_torito.system_type = 0;
7170 if (iso9660->opt.publisher)
7171 archive_string_copy(&(iso9660->el_torito.id),
7172 &(iso9660->publisher_identifier));
7175 return (ARCHIVE_OK);
7179 * If a media type is floppy, return its image size.
7180 * otherwise return 0.
7183 fd_boot_image_size(int media_type)
7185 switch (media_type) {
7186 case BOOT_MEDIA_1_2M_DISKETTE:
7187 return (FD_1_2M_SIZE);
7188 case BOOT_MEDIA_1_44M_DISKETTE:
7189 return (FD_1_44M_SIZE);
7190 case BOOT_MEDIA_2_88M_DISKETTE:
7191 return (FD_2_88M_SIZE);
7198 * Make a boot catalog image data.
7201 make_boot_catalog(struct archive_write *a)
7203 struct iso9660 *iso9660 = a->format_data;
7204 unsigned char *block;
7208 block = wb_buffptr(a);
7209 memset(block, 0, LOGICAL_BLOCK_SIZE);
7217 p[1] = iso9660->el_torito.platform_id;
7221 if (archive_strlen(&(iso9660->el_torito.id)) > 0)
7222 strncpy((char *)p+4, iso9660->el_torito.id.s, 23);
7231 wp = (uint16_t *)block;
7232 while (wp < (uint16_t *)&block[32])
7233 sum += archive_le16dec(wp++);
7234 set_num_721(&block[28], (~sum) + 1);
7237 * Initial/Default Entry
7240 /* Boot Indicator */
7242 /* Boot media type */
7243 p[1] = iso9660->el_torito.media_type;
7245 if (iso9660->el_torito.media_type == BOOT_MEDIA_NO_EMULATION)
7246 set_num_721(&p[2], iso9660->el_torito.boot_load_seg);
7248 set_num_721(&p[2], 0);
7250 p[4] = iso9660->el_torito.system_type;
7254 if (iso9660->el_torito.media_type == BOOT_MEDIA_NO_EMULATION)
7255 set_num_721(&p[6], iso9660->el_torito.boot_load_size);
7257 set_num_721(&p[6], 1);
7260 iso9660->el_torito.boot->file->content.location);
7262 memset(&p[12], 0, 20);
7264 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
7268 setup_boot_information(struct archive_write *a)
7270 struct iso9660 *iso9660 = a->format_data;
7274 unsigned char buff[4096];
7276 np = iso9660->el_torito.boot;
7277 lseek(iso9660->temp_fd,
7278 np->file->content.offset_of_temp + 64, SEEK_SET);
7279 size = archive_entry_size(np->file->entry) - 64;
7281 archive_set_error(&a->archive, errno,
7282 "Boot file(%jd) is too small", (intmax_t)size + 64);
7283 return (ARCHIVE_FATAL);
7290 if (size > (int64_t)sizeof(buff))
7291 rsize = sizeof(buff);
7293 rsize = (size_t)size;
7295 rs = read(iso9660->temp_fd, buff, rsize);
7297 archive_set_error(&a->archive, errno,
7298 "Can't read temporary file(%jd)",
7300 return (ARCHIVE_FATAL);
7302 for (i = 0; i < rs; i += 4)
7303 sum += archive_le32dec(buff + i);
7306 /* Set the location of Primary Volume Descriptor. */
7307 set_num_731(buff, SYSTEM_AREA_BLOCK);
7308 /* Set the location of the boot file. */
7309 set_num_731(buff+4, np->file->content.location);
7310 /* Set the size of the boot file. */
7311 size = fd_boot_image_size(iso9660->el_torito.media_type);
7313 size = archive_entry_size(np->file->entry);
7314 set_num_731(buff+8, (uint32_t)size);
7315 /* Set the sum of the boot file. */
7316 set_num_731(buff+12, sum);
7317 /* Clear reserved bytes. */
7318 memset(buff+16, 0, 40);
7320 /* Overwrite the boot file. */
7321 lseek(iso9660->temp_fd,
7322 np->file->content.offset_of_temp + 8, SEEK_SET);
7323 return (write_to_temp(a, buff, 56));
7329 zisofs_init_zstream(struct archive_write *a)
7331 struct iso9660 *iso9660 = a->format_data;
7334 iso9660->zisofs.stream.next_in = NULL;
7335 iso9660->zisofs.stream.avail_in = 0;
7336 iso9660->zisofs.stream.total_in = 0;
7337 iso9660->zisofs.stream.total_out = 0;
7338 if (iso9660->zisofs.stream_valid)
7339 r = deflateReset(&(iso9660->zisofs.stream));
7341 r = deflateInit(&(iso9660->zisofs.stream),
7342 iso9660->zisofs.compression_level);
7343 iso9660->zisofs.stream_valid = 1;
7349 case Z_STREAM_ERROR:
7350 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7351 "Internal error initializing "
7352 "compression library: invalid setup parameter");
7353 return (ARCHIVE_FATAL);
7355 archive_set_error(&a->archive, ENOMEM,
7356 "Internal error initializing "
7357 "compression library");
7358 return (ARCHIVE_FATAL);
7359 case Z_VERSION_ERROR:
7360 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7361 "Internal error initializing "
7362 "compression library: invalid library version");
7363 return (ARCHIVE_FATAL);
7365 return (ARCHIVE_OK);
7368 #endif /* HAVE_ZLIB_H */
7371 zisofs_init(struct archive_write *a, struct isofile *file)
7373 struct iso9660 *iso9660 = a->format_data;
7376 size_t ceil, bpsize;
7380 iso9660->zisofs.detect_magic = 0;
7381 iso9660->zisofs.making = 0;
7383 if (!iso9660->opt.rr || !iso9660->opt.zisofs)
7384 return (ARCHIVE_OK);
7386 if (archive_entry_size(file->entry) >= 24 &&
7387 archive_entry_size(file->entry) < MULTI_EXTENT_SIZE) {
7388 /* Acceptable file size for zisofs. */
7389 iso9660->zisofs.detect_magic = 1;
7390 iso9660->zisofs.magic_cnt = 0;
7392 if (!iso9660->zisofs.detect_magic)
7393 return (ARCHIVE_OK);
7396 /* The number of Logical Blocks which uncompressed data
7397 * will use in iso-image file is the same as the number of
7398 * Logical Blocks which zisofs(compressed) data will use
7399 * in ISO-image file. It won't reduce iso-image file size. */
7400 if (archive_entry_size(file->entry) <= LOGICAL_BLOCK_SIZE)
7401 return (ARCHIVE_OK);
7403 /* Initialize compression library */
7404 r = zisofs_init_zstream(a);
7405 if (r != ARCHIVE_OK)
7406 return (ARCHIVE_FATAL);
7408 /* Mark file->zisofs to create RRIP 'ZF' Use Entry. */
7409 file->zisofs.header_size = ZF_HEADER_SIZE >> 2;
7410 file->zisofs.log2_bs = ZF_LOG2_BS;
7411 file->zisofs.uncompressed_size = archive_entry_size(file->entry);
7413 /* Calculate a size of Block Pointers of zisofs. */
7414 ceil = (file->zisofs.uncompressed_size + ZF_BLOCK_SIZE -1)
7415 >> file->zisofs.log2_bs;
7416 iso9660->zisofs.block_pointers_cnt = ceil + 1;
7417 iso9660->zisofs.block_pointers_idx = 0;
7419 /* Ensure a buffer size used for Block Pointers */
7420 bpsize = iso9660->zisofs.block_pointers_cnt *
7421 sizeof(iso9660->zisofs.block_pointers[0]);
7422 if (iso9660->zisofs.block_pointers_allocated < bpsize) {
7423 free(iso9660->zisofs.block_pointers);
7424 iso9660->zisofs.block_pointers = malloc(bpsize);
7425 if (iso9660->zisofs.block_pointers == NULL) {
7426 archive_set_error(&a->archive, ENOMEM,
7427 "Can't allocate data");
7428 return (ARCHIVE_FATAL);
7430 iso9660->zisofs.block_pointers_allocated = bpsize;
7434 * Skip zisofs header and Block Pointers, which we will write
7435 * after all compressed data of a file written to the temporary
7438 tsize = ZF_HEADER_SIZE + bpsize;
7439 if (write_null(a, tsize) != ARCHIVE_OK)
7440 return (ARCHIVE_FATAL);
7443 * Initialize some variables to make zisofs.
7445 archive_le32enc(&(iso9660->zisofs.block_pointers[0]), tsize);
7446 iso9660->zisofs.remaining = file->zisofs.uncompressed_size;
7447 iso9660->zisofs.making = 1;
7448 iso9660->zisofs.allzero = 1;
7449 iso9660->zisofs.block_offset = tsize;
7450 iso9660->zisofs.total_size = tsize;
7451 iso9660->cur_file->cur_content->size = tsize;
7454 return (ARCHIVE_OK);
7458 zisofs_detect_magic(struct archive_write *a, const void *buff, size_t s)
7460 struct iso9660 *iso9660 = a->format_data;
7461 struct isofile *file = iso9660->cur_file;
7462 const unsigned char *p, *endp;
7463 const unsigned char *magic_buff;
7464 uint32_t uncompressed_size;
7465 unsigned char header_size;
7466 unsigned char log2_bs;
7472 entry_size = archive_entry_size(file->entry);
7473 if ((int64_t)sizeof(iso9660->zisofs.magic_buffer) > entry_size)
7474 magic_max = entry_size;
7476 magic_max = sizeof(iso9660->zisofs.magic_buffer);
7478 if (iso9660->zisofs.magic_cnt == 0 && s >= (size_t)magic_max)
7479 /* It's unnecessary we copy buffer. */
7482 if (iso9660->zisofs.magic_cnt < magic_max) {
7485 l = sizeof(iso9660->zisofs.magic_buffer)
7486 - iso9660->zisofs.magic_cnt;
7489 memcpy(iso9660->zisofs.magic_buffer
7490 + iso9660->zisofs.magic_cnt, buff, l);
7491 iso9660->zisofs.magic_cnt += l;
7492 if (iso9660->zisofs.magic_cnt < magic_max)
7495 magic_buff = iso9660->zisofs.magic_buffer;
7497 iso9660->zisofs.detect_magic = 0;
7500 /* Check the magic code of zisofs. */
7501 if (memcmp(p, zisofs_magic, sizeof(zisofs_magic)) != 0)
7502 /* This is not zisofs file which made by mkzftree. */
7504 p += sizeof(zisofs_magic);
7506 /* Read a zisofs header. */
7507 uncompressed_size = archive_le32dec(p);
7510 if (uncompressed_size < 24 || header_size != 4 ||
7511 log2_bs > 30 || log2_bs < 7)
7512 return;/* Invalid or not supported header. */
7514 /* Calculate a size of Block Pointers of zisofs. */
7515 ceil = (uncompressed_size +
7516 (ARCHIVE_LITERAL_LL(1) << log2_bs) -1) >> log2_bs;
7517 doff = (ceil + 1) * 4 + 16;
7518 if (entry_size < (int64_t)doff)
7519 return;/* Invalid data. */
7521 /* Check every Block Pointer has valid value. */
7522 p = magic_buff + 16;
7523 endp = magic_buff + magic_max;
7524 while (ceil && p + 8 <= endp) {
7525 bst = archive_le32dec(p);
7527 return;/* Invalid data. */
7529 bed = archive_le32dec(p);
7530 if (bed < bst || bed > entry_size)
7531 return;/* Invalid data. */
7536 file->zisofs.uncompressed_size = uncompressed_size;
7537 file->zisofs.header_size = header_size;
7538 file->zisofs.log2_bs = log2_bs;
7540 /* Disable making a zisofs image. */
7541 iso9660->zisofs.making = 0;
7547 * Compress data and write it to a temporary file.
7550 zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s)
7552 struct iso9660 *iso9660 = a->format_data;
7553 struct isofile *file = iso9660->cur_file;
7554 const unsigned char *b;
7556 size_t avail, csize;
7559 zstrm = &(iso9660->zisofs.stream);
7560 zstrm->next_out = wb_buffptr(a);
7561 zstrm->avail_out = wb_remaining(a);
7562 b = (const unsigned char *)buff;
7564 avail = ZF_BLOCK_SIZE - zstrm->total_in;
7570 iso9660->zisofs.remaining -= avail;
7571 if (iso9660->zisofs.remaining <= 0)
7574 zstrm->next_in = (Bytef *)(uintptr_t)(const void *)b;
7575 zstrm->avail_in = avail;
7578 * Check if current data block are all zero.
7580 if (iso9660->zisofs.allzero) {
7581 const unsigned char *nonzero = b;
7582 const unsigned char *nonzeroend = b + avail;
7584 while (nonzero < nonzeroend)
7586 iso9660->zisofs.allzero = 0;
7594 * If current data block are all zero, we do not use
7597 if (flush == Z_FINISH && iso9660->zisofs.allzero &&
7598 avail + zstrm->total_in == ZF_BLOCK_SIZE) {
7599 if (iso9660->zisofs.block_offset !=
7600 file->cur_content->size) {
7603 r = wb_set_offset(a,
7604 file->cur_content->offset_of_temp +
7605 iso9660->zisofs.block_offset);
7606 if (r != ARCHIVE_OK)
7608 diff = file->cur_content->size -
7609 iso9660->zisofs.block_offset;
7610 file->cur_content->size -= diff;
7611 iso9660->zisofs.total_size -= diff;
7613 zstrm->avail_in = 0;
7617 * Compress file data.
7619 while (zstrm->avail_in > 0) {
7620 csize = zstrm->total_out;
7621 r = deflate(zstrm, flush);
7625 csize = zstrm->total_out - csize;
7626 if (wb_consume(a, csize) != ARCHIVE_OK)
7627 return (ARCHIVE_FATAL);
7628 iso9660->zisofs.total_size += csize;
7629 iso9660->cur_file->cur_content->size += csize;
7630 zstrm->next_out = wb_buffptr(a);
7631 zstrm->avail_out = wb_remaining(a);
7634 archive_set_error(&a->archive,
7636 "Compression failed:"
7637 " deflate() call returned status %d",
7639 return (ARCHIVE_FATAL);
7643 if (flush == Z_FINISH) {
7645 * Save the information of one zisofs block.
7647 iso9660->zisofs.block_pointers_idx ++;
7648 archive_le32enc(&(iso9660->zisofs.block_pointers[
7649 iso9660->zisofs.block_pointers_idx]),
7650 iso9660->zisofs.total_size);
7651 r = zisofs_init_zstream(a);
7652 if (r != ARCHIVE_OK)
7653 return (ARCHIVE_FATAL);
7654 iso9660->zisofs.allzero = 1;
7655 iso9660->zisofs.block_offset = file->cur_content->size;
7659 return (ARCHIVE_OK);
7663 zisofs_finish_entry(struct archive_write *a)
7665 struct iso9660 *iso9660 = a->format_data;
7666 struct isofile *file = iso9660->cur_file;
7667 unsigned char buff[16];
7671 /* Direct temp file stream to zisofs temp file stream. */
7672 archive_entry_set_size(file->entry, iso9660->zisofs.total_size);
7675 * Save a file pointer which points the end of current zisofs data.
7677 tail = wb_offset(a);
7682 * +-----------------+----------------+-----------------+
7683 * | Header 16 bytes | Block Pointers | Compressed data |
7684 * +-----------------+----------------+-----------------+
7687 * 4 * (((Uncompressed file size + block_size -1) / block_size) + 1)
7689 * Write zisofs header.
7691 * +----+----+----+----+----+----+----+----+
7692 * | 37 | E4 | 53 | 96 | C9 | DB | D6 | 07 |
7693 * +----+----+----+----+----+----+----+----+
7696 * +------------------------+------------------+
7697 * | Uncompressed file size | header_size >> 2 |
7698 * +------------------------+------------------+
7701 * +-----------------+----------------+
7702 * | log2 block_size | Reserved(0000) |
7703 * +-----------------+----------------+
7706 memcpy(buff, zisofs_magic, 8);
7707 set_num_731(buff+8, file->zisofs.uncompressed_size);
7708 buff[12] = file->zisofs.header_size;
7709 buff[13] = file->zisofs.log2_bs;
7710 buff[14] = buff[15] = 0;/* Reserved */
7712 /* Move to the right position to write the header. */
7713 wb_set_offset(a, file->content.offset_of_temp);
7715 /* Write the header. */
7716 if (wb_write_to_temp(a, buff, 16) != ARCHIVE_OK)
7717 return (ARCHIVE_FATAL);
7720 * Write zisofs Block Pointers.
7722 s = iso9660->zisofs.block_pointers_cnt *
7723 sizeof(iso9660->zisofs.block_pointers[0]);
7724 if (wb_write_to_temp(a, iso9660->zisofs.block_pointers, s)
7726 return (ARCHIVE_FATAL);
7728 /* Set a file pointer back to the end of the temporary file. */
7729 wb_set_offset(a, tail);
7731 return (ARCHIVE_OK);
7735 zisofs_free(struct archive_write *a)
7737 struct iso9660 *iso9660 = a->format_data;
7738 int ret = ARCHIVE_OK;
7740 free(iso9660->zisofs.block_pointers);
7741 if (iso9660->zisofs.stream_valid &&
7742 deflateEnd(&(iso9660->zisofs.stream)) != Z_OK) {
7743 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7744 "Failed to clean up compressor");
7745 ret = ARCHIVE_FATAL;
7747 iso9660->zisofs.block_pointers = NULL;
7748 iso9660->zisofs.stream_valid = 0;
7752 struct zisofs_extract {
7753 int pz_log2_bs; /* Log2 of block size */
7754 uint64_t pz_uncompressed_size;
7755 size_t uncompressed_buffer_size;
7758 int header_passed:1;
7761 unsigned char *block_pointers;
7762 size_t block_pointers_size;
7763 size_t block_pointers_avail;
7765 uint32_t block_avail;
7772 zisofs_extract_init(struct archive_write *a, struct zisofs_extract *zisofs,
7773 const unsigned char *p, size_t bytes)
7775 size_t avail = bytes;
7778 /* Allocate block pointers buffer. */
7779 ceil = (zisofs->pz_uncompressed_size +
7780 (1LL << zisofs->pz_log2_bs) - 1)
7781 >> zisofs->pz_log2_bs;
7782 xsize = (ceil + 1) * 4;
7783 if (zisofs->block_pointers == NULL) {
7784 size_t alloc = ((xsize >> 10) + 1) << 10;
7785 zisofs->block_pointers = malloc(alloc);
7786 if (zisofs->block_pointers == NULL) {
7787 archive_set_error(&a->archive, ENOMEM,
7788 "No memory for zisofs decompression");
7789 return (ARCHIVE_FATAL);
7792 zisofs->block_pointers_size = xsize;
7794 /* Allocate uncompressed data buffer. */
7795 zisofs->uncompressed_buffer_size = 1UL << zisofs->pz_log2_bs;
7798 * Read the file header, and check the magic code of zisofs.
7800 if (!zisofs->header_passed) {
7803 archive_set_error(&a->archive,
7804 ARCHIVE_ERRNO_FILE_FORMAT,
7805 "Illegal zisofs file body");
7806 return (ARCHIVE_FATAL);
7809 if (memcmp(p, zisofs_magic, sizeof(zisofs_magic)) != 0)
7811 else if (archive_le32dec(p + 8) != zisofs->pz_uncompressed_size)
7813 else if (p[12] != 4 || p[13] != zisofs->pz_log2_bs)
7816 archive_set_error(&a->archive,
7817 ARCHIVE_ERRNO_FILE_FORMAT,
7818 "Illegal zisofs file body");
7819 return (ARCHIVE_FATAL);
7823 zisofs->header_passed = 1;
7827 * Read block pointers.
7829 if (zisofs->header_passed &&
7830 zisofs->block_pointers_avail < zisofs->block_pointers_size) {
7831 xsize = zisofs->block_pointers_size
7832 - zisofs->block_pointers_avail;
7835 memcpy(zisofs->block_pointers
7836 + zisofs->block_pointers_avail, p, xsize);
7837 zisofs->block_pointers_avail += xsize;
7839 if (zisofs->block_pointers_avail
7840 == zisofs->block_pointers_size) {
7841 /* We've got all block pointers and initialize
7842 * related variables. */
7843 zisofs->block_off = 0;
7844 zisofs->block_avail = 0;
7845 /* Complete a initialization */
7846 zisofs->initialized = 1;
7849 return ((ssize_t)avail);
7853 zisofs_extract(struct archive_write *a, struct zisofs_extract *zisofs,
7854 const unsigned char *p, size_t bytes)
7859 if (!zisofs->initialized) {
7860 ssize_t rs = zisofs_extract_init(a, zisofs, p, bytes);
7863 if (!zisofs->initialized) {
7864 /* We need more data. */
7865 zisofs->pz_offset += bytes;
7874 * Get block offsets from block pointers.
7876 if (zisofs->block_avail == 0) {
7879 if (zisofs->block_off + 4 >= zisofs->block_pointers_size) {
7880 /* There isn't a pair of offsets. */
7881 archive_set_error(&a->archive,
7882 ARCHIVE_ERRNO_FILE_FORMAT,
7883 "Illegal zisofs block pointers");
7884 return (ARCHIVE_FATAL);
7886 bst = archive_le32dec(
7887 zisofs->block_pointers + zisofs->block_off);
7888 if (bst != zisofs->pz_offset + (bytes - avail)) {
7889 archive_set_error(&a->archive,
7890 ARCHIVE_ERRNO_FILE_FORMAT,
7891 "Illegal zisofs block pointers(cannot seek)");
7892 return (ARCHIVE_FATAL);
7894 bed = archive_le32dec(
7895 zisofs->block_pointers + zisofs->block_off + 4);
7897 archive_set_error(&a->archive,
7898 ARCHIVE_ERRNO_FILE_FORMAT,
7899 "Illegal zisofs block pointers");
7900 return (ARCHIVE_FATAL);
7902 zisofs->block_avail = bed - bst;
7903 zisofs->block_off += 4;
7905 /* Initialize compression library for new block. */
7906 if (zisofs->stream_valid)
7907 r = inflateReset(&zisofs->stream);
7909 r = inflateInit(&zisofs->stream);
7911 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7912 "Can't initialize zisofs decompression.");
7913 return (ARCHIVE_FATAL);
7915 zisofs->stream_valid = 1;
7916 zisofs->stream.total_in = 0;
7917 zisofs->stream.total_out = 0;
7921 * Make uncompressed data.
7923 if (zisofs->block_avail == 0) {
7925 * It's basically 32K bytes NUL data.
7930 size = zisofs->uncompressed_buffer_size;
7933 if (size > wb_remaining(a))
7934 wsize = wb_remaining(a);
7937 memset(wb, 0, wsize);
7938 r = wb_consume(a, wsize);
7944 zisofs->stream.next_in = (Bytef *)(uintptr_t)(const void *)p;
7945 if (avail > zisofs->block_avail)
7946 zisofs->stream.avail_in = zisofs->block_avail;
7948 zisofs->stream.avail_in = avail;
7949 zisofs->stream.next_out = wb_buffptr(a);
7950 zisofs->stream.avail_out = wb_remaining(a);
7952 r = inflate(&zisofs->stream, 0);
7954 case Z_OK: /* Decompressor made some progress.*/
7955 case Z_STREAM_END: /* Found end of stream. */
7958 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7959 "zisofs decompression failed (%d)", r);
7960 return (ARCHIVE_FATAL);
7962 avail -= zisofs->stream.next_in - p;
7963 zisofs->block_avail -= zisofs->stream.next_in - p;
7964 r = wb_consume(a, wb_remaining(a) - zisofs->stream.avail_out);
7968 zisofs->pz_offset += bytes;
7969 return (bytes - avail);
7973 zisofs_rewind_boot_file(struct archive_write *a)
7975 struct iso9660 *iso9660 = a->format_data;
7976 struct isofile *file;
7977 unsigned char *rbuff;
7979 size_t remaining, rbuff_size;
7980 struct zisofs_extract zext;
7981 int64_t read_offset, write_offset, new_offset;
7982 int fd, ret = ARCHIVE_OK;
7984 file = iso9660->el_torito.boot->file;
7986 * There is nothing to do if this boot file does not have
7989 if (file->zisofs.header_size == 0)
7990 return (ARCHIVE_OK);
7993 * Uncompress the zisofs'ed file contents.
7995 memset(&zext, 0, sizeof(zext));
7996 zext.pz_uncompressed_size = file->zisofs.uncompressed_size;
7997 zext.pz_log2_bs = file->zisofs.log2_bs;
7999 fd = iso9660->temp_fd;
8000 new_offset = wb_offset(a);
8001 read_offset = file->content.offset_of_temp;
8002 remaining = file->content.size;
8003 if (remaining > 1024 * 32)
8004 rbuff_size = 1024 * 32;
8006 rbuff_size = remaining;
8008 rbuff = malloc(rbuff_size);
8009 if (rbuff == NULL) {
8010 archive_set_error(&a->archive, ENOMEM, "Can't allocate memory");
8011 return (ARCHIVE_FATAL);
8017 /* Get the current file pointer. */
8018 write_offset = lseek(fd, 0, SEEK_CUR);
8020 /* Change the file pointer to read. */
8021 lseek(fd, read_offset, SEEK_SET);
8024 if (rsize > remaining)
8026 rs = read(iso9660->temp_fd, rbuff, rsize);
8028 archive_set_error(&a->archive, errno,
8029 "Can't read temporary file(%jd)", (intmax_t)rs);
8030 ret = ARCHIVE_FATAL;
8036 /* Put the file pointer back to write. */
8037 lseek(fd, write_offset, SEEK_SET);
8039 r = zisofs_extract(a, &zext, rbuff, rs);
8046 if (ret == ARCHIVE_OK) {
8048 * Change the boot file content from zisofs'ed data
8051 file->content.offset_of_temp = new_offset;
8052 file->content.size = file->zisofs.uncompressed_size;
8053 archive_entry_set_size(file->entry, file->content.size);
8054 /* Set to be no zisofs. */
8055 file->zisofs.header_size = 0;
8056 file->zisofs.log2_bs = 0;
8057 file->zisofs.uncompressed_size = 0;
8058 r = wb_write_padding_to_temp(a, file->content.size);
8060 ret = ARCHIVE_FATAL;
8064 * Free the resource we used in this function only.
8067 free(zext.block_pointers);
8068 if (zext.stream_valid && inflateEnd(&(zext.stream)) != Z_OK) {
8069 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
8070 "Failed to clean up compressor");
8071 ret = ARCHIVE_FATAL;
8080 zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s)
8082 (void)buff; /* UNUSED */
8083 (void)s; /* UNUSED */
8084 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Programing error");
8085 return (ARCHIVE_FATAL);
8089 zisofs_rewind_boot_file(struct archive_write *a)
8091 struct iso9660 *iso9660 = a->format_data;
8093 if (iso9660->el_torito.boot->file->zisofs.header_size != 0) {
8094 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
8095 "We cannot extract the zisofs imaged boot file;"
8096 " this may not boot in being zisofs imaged");
8097 return (ARCHIVE_FAILED);
8099 return (ARCHIVE_OK);
8103 zisofs_finish_entry(struct archive_write *a)
8105 (void)a; /* UNUSED */
8106 return (ARCHIVE_OK);
8110 zisofs_free(struct archive_write *a)
8112 (void)a; /* UNUSED */
8113 return (ARCHIVE_OK);
8116 #endif /* HAVE_ZLIB_H */