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 hardlinked 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;
292 signed int virtual:1;
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 the 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 maximum 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 * : bsdtar 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 * : reduce 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 image 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 hardlinked 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. */
758 signed int detect_magic:1;
760 signed int allzero:1;
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 *, size_t, 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 = (size_t)(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 = (size_t)(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 = (int)
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 = (size_t)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 = (int)
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 converters.
1911 * if there is no file entry, converters 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 /* Switch 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_l(&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 __time64_t tmp_t = (__time64_t) *t; //time_t may be shorter than 64 bits
2528 _localtime64_s(tm, &tmp_t);
2530 memcpy(tm, localtime(t), sizeof(*tm));
2535 * Date and Time Format.
2536 * ISO9660 Standard 8.4.26.1
2539 set_date_time(unsigned char *p, time_t t)
2543 get_tmfromtime(&tm, &t);
2544 set_digit(p, 4, tm.tm_year + 1900);
2545 set_digit(p+4, 2, tm.tm_mon + 1);
2546 set_digit(p+6, 2, tm.tm_mday);
2547 set_digit(p+8, 2, tm.tm_hour);
2548 set_digit(p+10, 2, tm.tm_min);
2549 set_digit(p+12, 2, tm.tm_sec);
2550 set_digit(p+14, 2, 0);
2551 set_num_712(p+16, (char)(get_gmoffset(&tm)/(60*15)));
2555 set_date_time_null(unsigned char *p)
2557 memset(p, (int)'0', 16);
2562 set_time_915(unsigned char *p, time_t t)
2566 get_tmfromtime(&tm, &t);
2567 set_num_711(p+0, tm.tm_year);
2568 set_num_711(p+1, tm.tm_mon+1);
2569 set_num_711(p+2, tm.tm_mday);
2570 set_num_711(p+3, tm.tm_hour);
2571 set_num_711(p+4, tm.tm_min);
2572 set_num_711(p+5, tm.tm_sec);
2573 set_num_712(p+6, (char)(get_gmoffset(&tm)/(60*15)));
2578 * Write SUSP "CE" System Use Entry.
2581 set_SUSP_CE(unsigned char *p, int location, int offset, int size)
2583 unsigned char *bp = p -1;
2584 /* Extend the System Use Area
2587 * +----+----+----+----+-----------+-----------+
2588 * | 'C'| 'E'| 1C | 01 | LOCATION1 | LOCATION2 |
2589 * +----+----+----+----+-----------+-----------+
2595 * LOCATION1 : Location of Continuation of System Use Area.
2596 * LOCATION2 : Offset to Start of Continuation.
2597 * LOCATION3 : Length of the Continuation.
2602 bp[3] = RR_CE_SIZE; /* length */
2603 bp[4] = 1; /* version */
2604 set_num_733(bp+5, location);
2605 set_num_733(bp+13, offset);
2606 set_num_733(bp+21, size);
2607 return (RR_CE_SIZE);
2611 * The functions, which names are beginning with extra_, are used to
2612 * control extra records.
2613 * The maximum size of a Directory Record is 254. When a filename is
2614 * very long, all of RRIP data of a file won't stored to the Directory
2615 * Record and so remaining RRIP data store to an extra record instead.
2617 static unsigned char *
2618 extra_open_record(unsigned char *bp, int dr_len, struct isoent *isoent,
2619 struct ctl_extr_rec *ctl)
2625 ctl->isoent = isoent;
2627 ctl->cur_len = ctl->dr_len = dr_len;
2628 ctl->limit = DR_LIMIT;
2634 extra_close_record(struct ctl_extr_rec *ctl, int ce_size)
2639 extra_tell_used_size(ctl, ce_size);
2641 if (ctl->cur_len & 0x01) {
2643 if (ctl->bp != NULL)
2644 ctl->bp[ctl->cur_len] = 0;
2647 if (ctl->use_extr) {
2648 if (ctl->ce_ptr != NULL)
2649 set_SUSP_CE(ctl->ce_ptr, ctl->extr_loc,
2650 ctl->extr_off, ctl->cur_len - padding);
2652 ctl->dr_len = ctl->cur_len;
2655 #define extra_space(ctl) ((ctl)->limit - (ctl)->cur_len)
2657 static unsigned char *
2658 extra_next_record(struct ctl_extr_rec *ctl, int length)
2660 int cur_len = ctl->cur_len;/* save cur_len */
2662 /* Close the current extra record or Directory Record. */
2663 extra_close_record(ctl, RR_CE_SIZE);
2665 /* Get a next extra record. */
2667 if (ctl->bp != NULL) {
2668 /* Storing data into an extra record. */
2671 /* Save the pointer where a CE extension will be
2673 ctl->ce_ptr = &ctl->bp[cur_len+1];
2674 p = extra_get_record(ctl->isoent,
2675 &ctl->limit, &ctl->extr_off, &ctl->extr_loc);
2676 ctl->bp = p - 1;/* the base of bp offset is 1. */
2678 /* Calculating the size of an extra record. */
2679 (void)extra_get_record(ctl->isoent,
2680 &ctl->limit, NULL, NULL);
2682 /* Check if an extra record is almost full.
2683 * If so, get a next one. */
2684 if (extra_space(ctl) < length)
2685 (void)extra_next_record(ctl, length);
2690 static inline struct extr_rec *
2691 extra_last_record(struct isoent *isoent)
2693 if (isoent->extr_rec_list.first == NULL)
2695 return ((struct extr_rec *)(void *)
2696 ((char *)(isoent->extr_rec_list.last)
2697 - offsetof(struct extr_rec, next)));
2700 static unsigned char *
2701 extra_get_record(struct isoent *isoent, int *space, int *off, int *loc)
2703 struct extr_rec *rec;
2705 isoent = isoent->parent;
2707 /* Storing data into an extra record. */
2708 rec = isoent->extr_rec_list.current;
2709 if (DR_SAFETY > LOGICAL_BLOCK_SIZE - rec->offset)
2712 /* Calculating the size of an extra record. */
2713 rec = extra_last_record(isoent);
2715 DR_SAFETY > LOGICAL_BLOCK_SIZE - rec->offset) {
2716 rec = malloc(sizeof(*rec));
2721 /* Insert `rec` into the tail of isoent->extr_rec_list */
2724 * Note: testing isoent->extr_rec_list.last == NULL
2725 * here is really unneeded since it has been already
2726 * initialized at isoent_new function but Clang Static
2727 * Analyzer claims that it is dereference of null
2730 if (isoent->extr_rec_list.last == NULL)
2731 isoent->extr_rec_list.last =
2732 &(isoent->extr_rec_list.first);
2733 *isoent->extr_rec_list.last = rec;
2734 isoent->extr_rec_list.last = &(rec->next);
2737 *space = LOGICAL_BLOCK_SIZE - rec->offset - DR_SAFETY;
2739 *space -= 1;/* Keep padding space. */
2743 *loc = rec->location;
2744 isoent->extr_rec_list.current = rec;
2746 return (&rec->buf[rec->offset]);
2750 extra_tell_used_size(struct ctl_extr_rec *ctl, int size)
2752 struct isoent *isoent;
2753 struct extr_rec *rec;
2755 if (ctl->use_extr) {
2756 isoent = ctl->isoent->parent;
2757 rec = isoent->extr_rec_list.current;
2759 rec->offset += size;
2761 ctl->cur_len += size;
2765 extra_setup_location(struct isoent *isoent, int location)
2767 struct extr_rec *rec;
2771 rec = isoent->extr_rec_list.first;
2772 isoent->extr_rec_list.current = rec;
2775 rec->location = location++;
2783 * Create the RRIP entries.
2786 set_directory_record_rr(unsigned char *bp, int dr_len,
2787 struct isoent *isoent, struct iso9660 *iso9660, enum dir_rec_type t)
2789 /* Flags(BP 5) of the Rockridge "RR" System Use Field */
2790 unsigned char rr_flag;
2791 #define RR_USE_PX 0x01
2792 #define RR_USE_PN 0x02
2793 #define RR_USE_SL 0x04
2794 #define RR_USE_NM 0x08
2795 #define RR_USE_CL 0x10
2796 #define RR_USE_PL 0x20
2797 #define RR_USE_RE 0x40
2798 #define RR_USE_TF 0x80
2800 struct ctl_extr_rec ctl;
2801 struct isoent *rr_parent, *pxent;
2802 struct isofile *file;
2804 bp = extra_open_record(bp, dr_len, isoent, &ctl);
2806 if (t == DIR_REC_PARENT) {
2807 rr_parent = isoent->rr_parent;
2808 pxent = isoent->parent;
2809 if (rr_parent != NULL)
2812 isoent = isoent->parent;
2817 file = isoent->file;
2819 if (t != DIR_REC_NORMAL) {
2820 rr_flag = RR_USE_PX | RR_USE_TF;
2821 if (rr_parent != NULL)
2822 rr_flag |= RR_USE_PL;
2824 rr_flag = RR_USE_PX | RR_USE_NM | RR_USE_TF;
2825 if (archive_entry_filetype(file->entry) == AE_IFLNK)
2826 rr_flag |= RR_USE_SL;
2827 if (isoent->rr_parent != NULL)
2828 rr_flag |= RR_USE_RE;
2829 if (isoent->rr_child != NULL)
2830 rr_flag |= RR_USE_CL;
2831 if (archive_entry_filetype(file->entry) == AE_IFCHR ||
2832 archive_entry_filetype(file->entry) == AE_IFBLK)
2833 rr_flag |= RR_USE_PN;
2834 #ifdef COMPAT_MKISOFS
2836 * mkisofs 2.01.01a63 records "RE" extension to
2837 * the entry of "rr_moved" directory.
2838 * I don't understand this behavior.
2840 if (isoent->virtual &&
2841 isoent->parent == iso9660->primary.rootent &&
2842 strcmp(isoent->file->basename.s, "rr_moved") == 0)
2843 rr_flag |= RR_USE_RE;
2847 /* Write "SP" System Use Entry. */
2848 if (t == DIR_REC_SELF && isoent == isoent->parent) {
2854 bp[4] = 1; /* version */
2855 bp[5] = 0xBE; /* Check Byte */
2856 bp[6] = 0xEF; /* Check Byte */
2860 extra_tell_used_size(&ctl, length);
2863 /* Write "RR" System Use Entry. */
2865 if (extra_space(&ctl) < length)
2866 bp = extra_next_record(&ctl, length);
2871 bp[4] = 1; /* version */
2875 extra_tell_used_size(&ctl, length);
2877 /* Write "NM" System Use Entry. */
2878 if (rr_flag & RR_USE_NM) {
2881 * e.g. a basename is 'foo'
2883 * +----+----+----+----+----+----+----+----+
2884 * | 'N'| 'M'| 08 | 01 | 00 | 'f'| 'o'| 'o'|
2885 * +----+----+----+----+----+----+----+----+
2886 * <----------------- len ----------------->
2888 size_t nmlen = file->basename.length;
2889 const char *nm = file->basename.s;
2892 if (extra_space(&ctl) < 6)
2893 bp = extra_next_record(&ctl, 6);
2897 bp[4] = 1; /* version */
2899 nmmax = extra_space(&ctl);
2902 while (nmlen + 5 > nmmax) {
2903 length = (int)nmmax;
2906 bp[5] = 0x01;/* Alternate Name continues
2907 * in next "NM" field */
2908 memcpy(bp+6, nm, length - 5);
2911 nmlen -= length - 5;
2913 extra_tell_used_size(&ctl, length);
2914 if (extra_space(&ctl) < 6) {
2915 bp = extra_next_record(&ctl, 6);
2916 nmmax = extra_space(&ctl);
2923 bp[4] = 1; /* version */
2926 length = 5 + (int)nmlen;
2930 memcpy(bp+6, nm, nmlen);
2933 extra_tell_used_size(&ctl, length);
2936 /* Write "PX" System Use Entry. */
2937 if (rr_flag & RR_USE_PX) {
2941 * +----+----+----+----+-----------+-----------+
2942 * | 'P'| 'X'| 2C | 01 | FILE MODE | LINKS |
2943 * +----+----+----+----+-----------+-----------+
2945 * +-----------+-----------+------------------+
2946 * | USER ID | GROUP ID |FILE SERIAL NUMBER|
2947 * +-----------+-----------+------------------+
2951 if (extra_space(&ctl) < length)
2952 bp = extra_next_record(&ctl, length);
2958 mode = archive_entry_mode(file->entry);
2959 uid = archive_entry_uid(file->entry);
2960 gid = archive_entry_gid(file->entry);
2961 if (iso9660->opt.rr == OPT_RR_USEFUL) {
2963 * This action is similar to mkisofs -r option
2964 * but our rockridge=useful option does not
2965 * set a zero to uid and gid.
2967 /* set all read bit ON */
2969 #if !defined(_WIN32) && !defined(__CYGWIN__)
2972 /* set all exec bit ON */
2974 /* clear all write bits. */
2976 /* clear setuid,setgid,sticky bits. */
2983 bp[4] = 1; /* version */
2985 set_num_733(bp+5, mode);
2986 /* file links (stat.st_nlink) */
2988 archive_entry_nlink(file->entry));
2989 set_num_733(bp+21, (uint32_t)uid);
2990 set_num_733(bp+29, (uint32_t)gid);
2991 /* File Serial Number */
2993 set_num_733(bp+37, pxent->dir_location);
2994 else if (file->hardlink_target != NULL)
2996 file->hardlink_target->cur_content->location);
2999 file->cur_content->location);
3002 extra_tell_used_size(&ctl, length);
3005 /* Write "SL" System Use Entry. */
3006 if (rr_flag & RR_USE_SL) {
3009 * e.g. a symbolic name is 'foo/bar'
3011 * +----+----+----+----+----+------------+
3012 * | 'S'| 'L'| 0F | 01 | 00 | components |
3013 * +----+----+----+----+----+-----+------+
3014 * 0 1 2 3 4 5 ...|... 15
3015 * <----------------- len --------+------>
3018 * +----+----+----+----+----+ |
3019 * | 00 | 03 | 'f'| 'o'| 'o'| <---+
3020 * +----+----+----+----+----+ |
3023 * +----+----+----+----+----+ |
3024 * | 00 | 03 | 'b'| 'a'| 'r'| <---+
3025 * +----+----+----+----+----+
3028 * - cflg : flag of component
3029 * - clen : length of component
3034 if (extra_space(&ctl) < 7)
3035 bp = extra_next_record(&ctl, 7);
3036 sl = file->symlink.s;
3041 bp[4] = 1; /* version */
3044 unsigned char *nc, *cf, *cl, cldmy = 0;
3047 slmax = extra_space(&ctl);
3056 while (*sl && sllen + 11 < slmax) {
3057 if (sl_last == '\0' && sl[0] == '/') {
3061 * | 08 | 00 | ROOT component.
3064 * Root component has to appear
3065 * at the first component only.
3069 *cf = 0x08; /* ROOT */
3078 if (((sl_last == '\0' || sl_last == '/') &&
3079 sl[0] == '.' && sl[1] == '.' &&
3080 (sl[2] == '/' || sl[2] == '\0')) ||
3082 sl[1] == '.' && sl[2] == '.' &&
3083 (sl[3] == '/' || sl[3] == '\0'))) {
3087 * | 04 | 00 | PARENT component.
3088 * +----+----+ ("..")
3092 *cf = 0x04; /* PARENT */
3097 sl += 3;/* skip "/.." */
3099 sl += 2;/* skip ".." */
3104 if (((sl_last == '\0' || sl_last == '/') &&
3106 (sl[1] == '/' || sl[1] == '\0')) ||
3107 (sl[0] == '/' && sl[1] == '.' &&
3108 (sl[2] == '/' || sl[2] == '\0'))) {
3112 * | 02 | 00 | CURRENT component.
3117 *cf = 0x02; /* CURRENT */
3122 sl += 2;/* skip "/." */
3124 sl ++; /* skip "." */
3129 if (sl[0] == '/' || cl == NULL) {
3154 * Mark flg as CONTINUE component.
3159 * +----+----+----+----+----+-
3160 * | 'S'| 'L'| XX | 01 | 01 |
3161 * +----+----+----+----+----+-
3163 * continues in next "SL"
3166 bp[5] = 0x01;/* This Symbolic Link
3171 extra_tell_used_size(&ctl, length);
3172 if (extra_space(&ctl) < 11)
3173 bp = extra_next_record(&ctl, 11);
3178 bp[4] = 1; /* version */
3187 extra_tell_used_size(&ctl, length);
3193 /* Write "TF" System Use Entry. */
3194 if (rr_flag & RR_USE_TF) {
3198 * +----+----+----+----+-----+-------------+
3199 * | 'T'| 'F'| XX | 01 |FLAGS| TIME STAMPS |
3200 * +----+----+----+----+-----+-------------+
3202 * TIME STAMPS : ISO 9660 Standard 9.1.5.
3203 * If TF_LONG_FORM FLAGS is set,
3204 * use ISO9660 Standard 8.4.26.1.
3206 #define TF_CREATION 0x01 /* Creation time recorded */
3207 #define TF_MODIFY 0x02 /* Modification time recorded */
3208 #define TF_ACCESS 0x04 /* Last Access time recorded */
3209 #define TF_ATTRIBUTES 0x08 /* Last Attribute Change time recorded */
3210 #define TF_BACKUP 0x10 /* Last Backup time recorded */
3211 #define TF_EXPIRATION 0x20 /* Expiration time recorded */
3212 #define TF_EFFECTIVE 0x40 /* Effective time recorded */
3213 #define TF_LONG_FORM 0x80 /* ISO 9660 17-byte time format used */
3214 unsigned char tf_flags;
3218 #ifndef COMPAT_MKISOFS
3219 if (archive_entry_birthtime_is_set(file->entry) &&
3220 archive_entry_birthtime(file->entry) <=
3221 archive_entry_mtime(file->entry)) {
3223 tf_flags |= TF_CREATION;
3226 if (archive_entry_mtime_is_set(file->entry)) {
3228 tf_flags |= TF_MODIFY;
3230 if (archive_entry_atime_is_set(file->entry)) {
3232 tf_flags |= TF_ACCESS;
3234 if (archive_entry_ctime_is_set(file->entry)) {
3236 tf_flags |= TF_ATTRIBUTES;
3238 if (extra_space(&ctl) < length)
3239 bp = extra_next_record(&ctl, length);
3244 bp[4] = 1; /* version */
3248 if (tf_flags & TF_CREATION) {
3250 archive_entry_birthtime(file->entry));
3253 /* Modification time */
3254 if (tf_flags & TF_MODIFY) {
3256 archive_entry_mtime(file->entry));
3259 /* Last Access time */
3260 if (tf_flags & TF_ACCESS) {
3262 archive_entry_atime(file->entry));
3265 /* Last Attribute Change time */
3266 if (tf_flags & TF_ATTRIBUTES) {
3268 archive_entry_ctime(file->entry));
3272 extra_tell_used_size(&ctl, length);
3275 /* Write "RE" System Use Entry. */
3276 if (rr_flag & RR_USE_RE) {
3280 * +----+----+----+----+
3281 * | 'R'| 'E'| 04 | 01 |
3282 * +----+----+----+----+
3286 if (extra_space(&ctl) < length)
3287 bp = extra_next_record(&ctl, length);
3292 bp[4] = 1; /* version */
3295 extra_tell_used_size(&ctl, length);
3298 /* Write "PL" System Use Entry. */
3299 if (rr_flag & RR_USE_PL) {
3303 * +----+----+----+----+------------+
3304 * | 'P'| 'L'| 0C | 01 | *LOCATION |
3305 * +----+----+----+----+------------+
3307 * *LOCATION: location of parent directory
3310 if (extra_space(&ctl) < length)
3311 bp = extra_next_record(&ctl, length);
3316 bp[4] = 1; /* version */
3318 rr_parent->dir_location);
3321 extra_tell_used_size(&ctl, length);
3324 /* Write "CL" System Use Entry. */
3325 if (rr_flag & RR_USE_CL) {
3329 * +----+----+----+----+------------+
3330 * | 'C'| 'L'| 0C | 01 | *LOCATION |
3331 * +----+----+----+----+------------+
3333 * *LOCATION: location of child directory
3336 if (extra_space(&ctl) < length)
3337 bp = extra_next_record(&ctl, length);
3342 bp[4] = 1; /* version */
3344 isoent->rr_child->dir_location);
3347 extra_tell_used_size(&ctl, length);
3350 /* Write "PN" System Use Entry. */
3351 if (rr_flag & RR_USE_PN) {
3355 * +----+----+----+----+------------+------------+
3356 * | 'P'| 'N'| 14 | 01 | dev_t high | dev_t low |
3357 * +----+----+----+----+------------+------------+
3361 if (extra_space(&ctl) < length)
3362 bp = extra_next_record(&ctl, length);
3369 bp[4] = 1; /* version */
3370 dev = (uint64_t)archive_entry_rdev(file->entry);
3371 set_num_733(bp + 5, (uint32_t)(dev >> 32));
3372 set_num_733(bp + 13, (uint32_t)(dev & 0xFFFFFFFF));
3375 extra_tell_used_size(&ctl, length);
3378 /* Write "ZF" System Use Entry. */
3379 if (file->zisofs.header_size) {
3383 * +----+----+----+----+----+----+-------------+
3384 * | 'Z'| 'F'| 10 | 01 | 'p'| 'z'| Header Size |
3385 * +----+----+----+----+----+----+-------------+
3387 * +--------------------+-------------------+
3388 * | Log2 of block Size | Uncompressed Size |
3389 * +--------------------+-------------------+
3393 if (extra_space(&ctl) < length)
3394 bp = extra_next_record(&ctl, length);
3399 bp[4] = 1; /* version */
3402 bp[7] = file->zisofs.header_size;
3403 bp[8] = file->zisofs.log2_bs;
3404 set_num_733(bp + 9, file->zisofs.uncompressed_size);
3407 extra_tell_used_size(&ctl, length);
3410 /* Write "CE" System Use Entry. */
3411 if (t == DIR_REC_SELF && isoent == isoent->parent) {
3412 length = RR_CE_SIZE;
3414 set_SUSP_CE(bp+1, iso9660->location_rrip_er,
3416 extra_tell_used_size(&ctl, length);
3419 extra_close_record(&ctl, 0);
3421 return (ctl.dr_len);
3425 * Write data of a Directory Record or calculate writing bytes itself.
3426 * If parameter `p' is NULL, calculates the size of writing data, which
3427 * a Directory Record needs to write, then it saved and return
3428 * the calculated size.
3429 * Parameter `n' is a remaining size of buffer. when parameter `p' is
3430 * not NULL, check whether that `n' is not less than the saved size.
3431 * if that `n' is small, return zero.
3433 * This format of the Directory Record is according to
3434 * ISO9660 Standard 9.1
3437 set_directory_record(unsigned char *p, size_t n, struct isoent *isoent,
3438 struct iso9660 *iso9660, enum dir_rec_type t,
3439 enum vdd_type vdd_type)
3447 * Check whether a write buffer size is less than the
3448 * saved size which is needed to write this Directory
3453 dr_len = isoent->dr_len.vd; break;
3455 dr_len = isoent->dr_len.self; break;
3456 case DIR_REC_PARENT:
3457 dr_len = isoent->dr_len.parent; break;
3458 case DIR_REC_NORMAL:
3460 dr_len = isoent->dr_len.normal; break;
3463 return (0);/* Needs more buffer size. */
3466 if (t == DIR_REC_NORMAL && isoent->identifier != NULL)
3467 fi_len = isoent->id_len;
3472 struct isoent *xisoent;
3473 struct isofile *file;
3476 if (t == DIR_REC_PARENT)
3477 xisoent = isoent->parent;
3480 file = isoent->file;
3481 if (file->hardlink_target != NULL)
3482 file = file->hardlink_target;
3483 /* Make a file flag. */
3485 flag = FILE_FLAG_DIRECTORY;
3487 if (file->cur_content->next != NULL)
3488 flag = FILE_FLAG_MULTI_EXTENT;
3494 /* Extended Attribute Record Length */
3495 set_num_711(bp+2, 0);
3496 /* Location of Extent */
3498 set_num_733(bp+3, xisoent->dir_location);
3500 set_num_733(bp+3, file->cur_content->location);
3504 xisoent->dir_block * LOGICAL_BLOCK_SIZE);
3506 set_num_733(bp+11, (uint32_t)file->cur_content->size);
3507 /* Recording Date and Time */
3509 * If a file type is symbolic link, you are seeing this
3510 * field value is different from a value mkisofs makes.
3511 * libarchive uses lstat to get this one, but it
3512 * seems mkisofs uses stat to get.
3515 archive_entry_mtime(xisoent->file->entry));
3518 /* File Unit Size */
3519 set_num_711(bp+27, 0);
3520 /* Interleave Gap Size */
3521 set_num_711(bp+28, 0);
3522 /* Volume Sequence Number */
3523 set_num_723(bp+29, iso9660->volume_sequence_number);
3524 /* Length of File Identifier */
3525 set_num_711(bp+33, (unsigned char)fi_len);
3526 /* File Identifier */
3530 set_num_711(bp+34, 0);
3532 case DIR_REC_PARENT:
3533 set_num_711(bp+34, 1);
3535 case DIR_REC_NORMAL:
3536 if (isoent->identifier != NULL)
3537 memcpy(bp+34, isoent->identifier, fi_len);
3539 set_num_711(bp+34, 0);
3544 dr_len = 33 + fi_len;
3546 if (dr_len & 0x01) {
3552 /* Volume Descriptor does not record extension. */
3553 if (t == DIR_REC_VD) {
3555 /* Length of Directory Record */
3556 set_num_711(p, (unsigned char)dr_len);
3558 isoent->dr_len.vd = (int)dr_len;
3559 return ((int)dr_len);
3563 if (iso9660->opt.rr && vdd_type != VDD_JOLIET)
3564 dr_len = set_directory_record_rr(bp, (int)dr_len,
3565 isoent, iso9660, t);
3568 /* Length of Directory Record */
3569 set_num_711(p, (unsigned char)dr_len);
3572 * Save the size which is needed to write this
3577 /* This case does not come, but compiler
3578 * complains that DIR_REC_VD not handled
3582 isoent->dr_len.self = (int)dr_len; break;
3583 case DIR_REC_PARENT:
3584 isoent->dr_len.parent = (int)dr_len; break;
3585 case DIR_REC_NORMAL:
3586 isoent->dr_len.normal = (int)dr_len; break;
3590 return ((int)dr_len);
3594 * Calculate the size of a directory record.
3597 get_dir_rec_size(struct iso9660 *iso9660, struct isoent *isoent,
3598 enum dir_rec_type t, enum vdd_type vdd_type)
3601 return (set_directory_record(NULL, SIZE_MAX,
3602 isoent, iso9660, t, vdd_type));
3606 * Manage to write ISO-image data with wbuff to reduce calling
3607 * __archive_write_output() for performance.
3611 static inline unsigned char *
3612 wb_buffptr(struct archive_write *a)
3614 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3616 return (&(iso9660->wbuff[sizeof(iso9660->wbuff)
3617 - iso9660->wbuff_remaining]));
3621 wb_write_out(struct archive_write *a)
3623 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3627 wsize = sizeof(iso9660->wbuff) - iso9660->wbuff_remaining;
3628 nw = wsize % LOGICAL_BLOCK_SIZE;
3629 if (iso9660->wbuff_type == WB_TO_STREAM)
3630 r = __archive_write_output(a, iso9660->wbuff, wsize - nw);
3632 r = write_to_temp(a, iso9660->wbuff, wsize - nw);
3633 /* Increase the offset. */
3634 iso9660->wbuff_offset += wsize - nw;
3635 if (iso9660->wbuff_offset > iso9660->wbuff_written)
3636 iso9660->wbuff_written = iso9660->wbuff_offset;
3637 iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
3639 iso9660->wbuff_remaining -= nw;
3640 memmove(iso9660->wbuff, iso9660->wbuff + wsize - nw, nw);
3646 wb_consume(struct archive_write *a, size_t size)
3648 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3650 if (size > iso9660->wbuff_remaining ||
3651 iso9660->wbuff_remaining == 0) {
3652 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
3653 "Internal Programming error: iso9660:wb_consume()"
3654 " size=%jd, wbuff_remaining=%jd",
3655 (intmax_t)size, (intmax_t)iso9660->wbuff_remaining);
3656 return (ARCHIVE_FATAL);
3658 iso9660->wbuff_remaining -= size;
3659 if (iso9660->wbuff_remaining < LOGICAL_BLOCK_SIZE)
3660 return (wb_write_out(a));
3661 return (ARCHIVE_OK);
3667 wb_set_offset(struct archive_write *a, int64_t off)
3669 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3670 int64_t used, ext_bytes;
3672 if (iso9660->wbuff_type != WB_TO_TEMP) {
3673 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
3674 "Internal Programming error: iso9660:wb_set_offset()");
3675 return (ARCHIVE_FATAL);
3678 used = sizeof(iso9660->wbuff) - iso9660->wbuff_remaining;
3679 if (iso9660->wbuff_offset + used > iso9660->wbuff_tail)
3680 iso9660->wbuff_tail = iso9660->wbuff_offset + used;
3681 if (iso9660->wbuff_offset < iso9660->wbuff_written) {
3683 write_to_temp(a, iso9660->wbuff, (size_t)used) != ARCHIVE_OK)
3684 return (ARCHIVE_FATAL);
3685 iso9660->wbuff_offset = iso9660->wbuff_written;
3686 lseek(iso9660->temp_fd, iso9660->wbuff_offset, SEEK_SET);
3687 iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
3690 if (off < iso9660->wbuff_offset) {
3692 * Write out waiting data.
3695 if (wb_write_out(a) != ARCHIVE_OK)
3696 return (ARCHIVE_FATAL);
3698 lseek(iso9660->temp_fd, off, SEEK_SET);
3699 iso9660->wbuff_offset = off;
3700 iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
3701 } else if (off <= iso9660->wbuff_tail) {
3702 iso9660->wbuff_remaining = (size_t)
3703 (sizeof(iso9660->wbuff) - (off - iso9660->wbuff_offset));
3705 ext_bytes = off - iso9660->wbuff_tail;
3706 iso9660->wbuff_remaining = (size_t)(sizeof(iso9660->wbuff)
3707 - (iso9660->wbuff_tail - iso9660->wbuff_offset));
3708 while (ext_bytes >= (int64_t)iso9660->wbuff_remaining) {
3709 if (write_null(a, (size_t)iso9660->wbuff_remaining)
3711 return (ARCHIVE_FATAL);
3712 ext_bytes -= iso9660->wbuff_remaining;
3714 if (ext_bytes > 0) {
3715 if (write_null(a, (size_t)ext_bytes) != ARCHIVE_OK)
3716 return (ARCHIVE_FATAL);
3719 return (ARCHIVE_OK);
3722 #endif /* HAVE_ZLIB_H */
3725 write_null(struct archive_write *a, size_t size)
3728 unsigned char *p, *old;
3731 remaining = wb_remaining(a);
3733 if (size <= remaining) {
3735 return (wb_consume(a, size));
3737 memset(p, 0, remaining);
3738 r = wb_consume(a, remaining);
3739 if (r != ARCHIVE_OK)
3744 memset(p, 0, old - p);
3745 remaining = wb_remaining(a);
3747 size_t wsize = size;
3749 if (wsize > remaining)
3751 r = wb_consume(a, wsize);
3752 if (r != ARCHIVE_OK)
3756 return (ARCHIVE_OK);
3760 * Write Volume Descriptor Set Terminator
3763 write_VD_terminator(struct archive_write *a)
3767 bp = wb_buffptr(a) -1;
3768 set_VD_bp(bp, VDT_TERMINATOR, 1);
3769 set_unused_field_bp(bp, 8, LOGICAL_BLOCK_SIZE);
3771 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
3775 set_file_identifier(unsigned char *bp, int from, int to, enum vdc vdc,
3776 struct archive_write *a, struct vdd *vdd, struct archive_string *id,
3777 const char *label, int leading_under, enum char_type char_type)
3779 char identifier[256];
3780 struct isoent *isoent;
3785 if (id->length > 0 && leading_under && id->s[0] != '_') {
3786 if (char_type == A_CHAR)
3787 r = set_str_a_characters_bp(a, bp, from, to, id->s, vdc);
3789 r = set_str_d_characters_bp(a, bp, from, to, id->s, vdc);
3790 } else if (id->length > 0) {
3794 isoent = isoent_find_entry(vdd->rootent, ids);
3795 if (isoent == NULL) {
3796 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
3797 "Not Found %s `%s'.",
3799 return (ARCHIVE_FATAL);
3801 len = isoent->ext_off + isoent->ext_len;
3802 if (vdd->vdd_type == VDD_JOLIET) {
3803 if (len > sizeof(identifier)-2)
3804 len = sizeof(identifier)-2;
3806 if (len > sizeof(identifier)-1)
3807 len = sizeof(identifier)-1;
3809 memcpy(identifier, isoent->identifier, len);
3810 identifier[len] = '\0';
3811 if (vdd->vdd_type == VDD_JOLIET) {
3812 identifier[len+1] = 0;
3813 vdc = VDC_UCS2_DIRECT;
3815 if (char_type == A_CHAR)
3816 r = set_str_a_characters_bp(a, bp, from, to,
3819 r = set_str_d_characters_bp(a, bp, from, to,
3822 if (char_type == A_CHAR)
3823 r = set_str_a_characters_bp(a, bp, from, to, NULL, vdc);
3825 r = set_str_d_characters_bp(a, bp, from, to, NULL, vdc);
3831 * Write Primary/Supplementary Volume Descriptor
3834 write_VD(struct archive_write *a, struct vdd *vdd)
3836 struct iso9660 *iso9660;
3838 uint16_t volume_set_size = 1;
3839 char identifier[256];
3842 unsigned char vd_ver, fst_ver;
3845 iso9660 = a->format_data;
3846 switch (vdd->vdd_type) {
3848 vdt = VDT_SUPPLEMENTARY;
3849 vd_ver = fst_ver = 1;
3853 vdt = VDT_SUPPLEMENTARY;
3854 vd_ver = fst_ver = 2;
3855 vdc = VDC_LOWERCASE;
3860 vd_ver = fst_ver = 1;
3861 #ifdef COMPAT_MKISOFS
3862 vdc = VDC_LOWERCASE;
3869 bp = wb_buffptr(a) -1;
3870 /* Volume Descriptor Type */
3871 set_VD_bp(bp, vdt, vd_ver);
3873 set_unused_field_bp(bp, 8, 8);
3874 /* System Identifier */
3875 get_system_identitier(identifier, sizeof(identifier));
3876 r = set_str_a_characters_bp(a, bp, 9, 40, identifier, vdc);
3877 if (r != ARCHIVE_OK)
3879 /* Volume Identifier */
3880 r = set_str_d_characters_bp(a, bp, 41, 72,
3881 iso9660->volume_identifier.s, vdc);
3882 if (r != ARCHIVE_OK)
3885 set_unused_field_bp(bp, 73, 80);
3886 /* Volume Space Size */
3887 set_num_733(bp+81, iso9660->volume_space_size);
3888 if (vdd->vdd_type == VDD_JOLIET) {
3889 /* Escape Sequences */
3890 bp[89] = 0x25;/* UCS-2 Level 3 */
3893 memset(bp + 92, 0, 120 - 92 + 1);
3896 set_unused_field_bp(bp, 89, 120);
3898 /* Volume Set Size */
3899 set_num_723(bp+121, volume_set_size);
3900 /* Volume Sequence Number */
3901 set_num_723(bp+125, iso9660->volume_sequence_number);
3902 /* Logical Block Size */
3903 set_num_723(bp+129, LOGICAL_BLOCK_SIZE);
3904 /* Path Table Size */
3905 set_num_733(bp+133, vdd->path_table_size);
3906 /* Location of Occurrence of Type L Path Table */
3907 set_num_731(bp+141, vdd->location_type_L_path_table);
3908 /* Location of Optional Occurrence of Type L Path Table */
3909 set_num_731(bp+145, 0);
3910 /* Location of Occurrence of Type M Path Table */
3911 set_num_732(bp+149, vdd->location_type_M_path_table);
3912 /* Location of Optional Occurrence of Type M Path Table */
3913 set_num_732(bp+153, 0);
3914 /* Directory Record for Root Directory(BP 157 to 190) */
3915 set_directory_record(bp+157, 190-157+1, vdd->rootent,
3916 iso9660, DIR_REC_VD, vdd->vdd_type);
3917 /* Volume Set Identifier */
3918 r = set_str_d_characters_bp(a, bp, 191, 318, "", vdc);
3919 if (r != ARCHIVE_OK)
3921 /* Publisher Identifier */
3922 r = set_file_identifier(bp, 319, 446, vdc, a, vdd,
3923 &(iso9660->publisher_identifier),
3924 "Publisher File", 1, A_CHAR);
3925 if (r != ARCHIVE_OK)
3927 /* Data Preparer Identifier */
3928 r = set_file_identifier(bp, 447, 574, vdc, a, vdd,
3929 &(iso9660->data_preparer_identifier),
3930 "Data Preparer File", 1, A_CHAR);
3931 if (r != ARCHIVE_OK)
3933 /* Application Identifier */
3934 r = set_file_identifier(bp, 575, 702, vdc, a, vdd,
3935 &(iso9660->application_identifier),
3936 "Application File", 1, A_CHAR);
3937 if (r != ARCHIVE_OK)
3939 /* Copyright File Identifier */
3940 r = set_file_identifier(bp, 703, 739, vdc, a, vdd,
3941 &(iso9660->copyright_file_identifier),
3942 "Copyright File", 0, D_CHAR);
3943 if (r != ARCHIVE_OK)
3945 /* Abstract File Identifier */
3946 r = set_file_identifier(bp, 740, 776, vdc, a, vdd,
3947 &(iso9660->abstract_file_identifier),
3948 "Abstract File", 0, D_CHAR);
3949 if (r != ARCHIVE_OK)
3951 /* Bibliographic File Identifier */
3952 r = set_file_identifier(bp, 777, 813, vdc, a, vdd,
3953 &(iso9660->bibliographic_file_identifier),
3954 "Bibliongraphic File", 0, D_CHAR);
3955 if (r != ARCHIVE_OK)
3957 /* Volume Creation Date and Time */
3958 set_date_time(bp+814, iso9660->birth_time);
3959 /* Volume Modification Date and Time */
3960 set_date_time(bp+831, iso9660->birth_time);
3961 /* Volume Expiration Date and Time(obsolete) */
3962 set_date_time_null(bp+848);
3963 /* Volume Effective Date and Time */
3964 set_date_time(bp+865, iso9660->birth_time);
3965 /* File Structure Version */
3969 /* Application Use */
3970 memset(bp + 884, 0x20, 1395 - 884 + 1);
3972 set_unused_field_bp(bp, 1396, LOGICAL_BLOCK_SIZE);
3974 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
3978 * Write Boot Record Volume Descriptor
3981 write_VD_boot_record(struct archive_write *a)
3983 struct iso9660 *iso9660;
3986 iso9660 = a->format_data;
3987 bp = wb_buffptr(a) -1;
3988 /* Volume Descriptor Type */
3989 set_VD_bp(bp, VDT_BOOT_RECORD, 1);
3990 /* Boot System Identifier */
3991 memcpy(bp+8, "EL TORITO SPECIFICATION", 23);
3992 set_unused_field_bp(bp, 8+23, 39);
3994 set_unused_field_bp(bp, 40, 71);
3995 /* Absolute pointer to first sector of Boot Catalog */
3997 iso9660->el_torito.catalog->file->content.location);
3999 set_unused_field_bp(bp, 76, LOGICAL_BLOCK_SIZE);
4001 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4011 set_option_info(struct archive_string *info, int *opt, const char *key,
4012 enum keytype type, ...)
4019 prefix = (*opt==0)? ' ':',';
4023 d = va_arg(ap, int);
4024 archive_string_sprintf(info, "%c%s%s",
4025 prefix, (d == 0)?"!":"", key);
4028 s = va_arg(ap, const char *);
4029 archive_string_sprintf(info, "%c%s=%s",
4033 d = va_arg(ap, int);
4034 archive_string_sprintf(info, "%c%s=%d",
4038 d = va_arg(ap, int);
4039 archive_string_sprintf(info, "%c%s=%x",
4049 * Make Non-ISO File System Information
4052 write_information_block(struct archive_write *a)
4054 struct iso9660 *iso9660;
4058 struct archive_string info;
4059 size_t info_size = LOGICAL_BLOCK_SIZE *
4060 NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK;
4062 iso9660 = (struct iso9660 *)a->format_data;
4063 if (info_size > wb_remaining(a)) {
4064 r = wb_write_out(a);
4065 if (r != ARCHIVE_OK)
4068 archive_string_init(&info);
4069 if (archive_string_ensure(&info, info_size) == NULL) {
4070 archive_set_error(&a->archive, ENOMEM,
4071 "Can't allocate memory");
4072 return (ARCHIVE_FATAL);
4074 memset(info.s, 0, info_size);
4076 #if defined(HAVE__CTIME64_S)
4078 __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits
4079 _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp));
4081 #elif defined(HAVE_CTIME_R)
4082 ctime_r(&(iso9660->birth_time), buf);
4084 strncpy(buf, ctime(&(iso9660->birth_time)), sizeof(buf)-1);
4085 buf[sizeof(buf)-1] = '\0';
4087 archive_string_sprintf(&info,
4088 "INFO %s%s", buf, archive_version_string());
4089 if (iso9660->opt.abstract_file != OPT_ABSTRACT_FILE_DEFAULT)
4090 set_option_info(&info, &opt, "abstract-file",
4091 KEY_STR, iso9660->abstract_file_identifier.s);
4092 if (iso9660->opt.application_id != OPT_APPLICATION_ID_DEFAULT)
4093 set_option_info(&info, &opt, "application-id",
4094 KEY_STR, iso9660->application_identifier.s);
4095 if (iso9660->opt.allow_vernum != OPT_ALLOW_VERNUM_DEFAULT)
4096 set_option_info(&info, &opt, "allow-vernum",
4097 KEY_FLG, iso9660->opt.allow_vernum);
4098 if (iso9660->opt.biblio_file != OPT_BIBLIO_FILE_DEFAULT)
4099 set_option_info(&info, &opt, "biblio-file",
4100 KEY_STR, iso9660->bibliographic_file_identifier.s);
4101 if (iso9660->opt.boot != OPT_BOOT_DEFAULT)
4102 set_option_info(&info, &opt, "boot",
4103 KEY_STR, iso9660->el_torito.boot_filename.s);
4104 if (iso9660->opt.boot_catalog != OPT_BOOT_CATALOG_DEFAULT)
4105 set_option_info(&info, &opt, "boot-catalog",
4106 KEY_STR, iso9660->el_torito.catalog_filename.s);
4107 if (iso9660->opt.boot_info_table != OPT_BOOT_INFO_TABLE_DEFAULT)
4108 set_option_info(&info, &opt, "boot-info-table",
4109 KEY_FLG, iso9660->opt.boot_info_table);
4110 if (iso9660->opt.boot_load_seg != OPT_BOOT_LOAD_SEG_DEFAULT)
4111 set_option_info(&info, &opt, "boot-load-seg",
4112 KEY_HEX, iso9660->el_torito.boot_load_seg);
4113 if (iso9660->opt.boot_load_size != OPT_BOOT_LOAD_SIZE_DEFAULT)
4114 set_option_info(&info, &opt, "boot-load-size",
4115 KEY_INT, iso9660->el_torito.boot_load_size);
4116 if (iso9660->opt.boot_type != OPT_BOOT_TYPE_DEFAULT) {
4118 if (iso9660->opt.boot_type == OPT_BOOT_TYPE_FD)
4120 if (iso9660->opt.boot_type == OPT_BOOT_TYPE_HARD_DISK)
4122 set_option_info(&info, &opt, "boot-type",
4126 if (iso9660->opt.compression_level != OPT_COMPRESSION_LEVEL_DEFAULT)
4127 set_option_info(&info, &opt, "compression-level",
4128 KEY_INT, iso9660->zisofs.compression_level);
4130 if (iso9660->opt.copyright_file != OPT_COPYRIGHT_FILE_DEFAULT)
4131 set_option_info(&info, &opt, "copyright-file",
4132 KEY_STR, iso9660->copyright_file_identifier.s);
4133 if (iso9660->opt.iso_level != OPT_ISO_LEVEL_DEFAULT)
4134 set_option_info(&info, &opt, "iso-level",
4135 KEY_INT, iso9660->opt.iso_level);
4136 if (iso9660->opt.joliet != OPT_JOLIET_DEFAULT) {
4137 if (iso9660->opt.joliet == OPT_JOLIET_LONGNAME)
4138 set_option_info(&info, &opt, "joliet",
4141 set_option_info(&info, &opt, "joliet",
4142 KEY_FLG, iso9660->opt.joliet);
4144 if (iso9660->opt.limit_depth != OPT_LIMIT_DEPTH_DEFAULT)
4145 set_option_info(&info, &opt, "limit-depth",
4146 KEY_FLG, iso9660->opt.limit_depth);
4147 if (iso9660->opt.limit_dirs != OPT_LIMIT_DIRS_DEFAULT)
4148 set_option_info(&info, &opt, "limit-dirs",
4149 KEY_FLG, iso9660->opt.limit_dirs);
4150 if (iso9660->opt.pad != OPT_PAD_DEFAULT)
4151 set_option_info(&info, &opt, "pad",
4152 KEY_FLG, iso9660->opt.pad);
4153 if (iso9660->opt.publisher != OPT_PUBLISHER_DEFAULT)
4154 set_option_info(&info, &opt, "publisher",
4155 KEY_STR, iso9660->publisher_identifier.s);
4156 if (iso9660->opt.rr != OPT_RR_DEFAULT) {
4157 if (iso9660->opt.rr == OPT_RR_DISABLED)
4158 set_option_info(&info, &opt, "rockridge",
4159 KEY_FLG, iso9660->opt.rr);
4160 else if (iso9660->opt.rr == OPT_RR_STRICT)
4161 set_option_info(&info, &opt, "rockridge",
4163 else if (iso9660->opt.rr == OPT_RR_USEFUL)
4164 set_option_info(&info, &opt, "rockridge",
4167 if (iso9660->opt.volume_id != OPT_VOLUME_ID_DEFAULT)
4168 set_option_info(&info, &opt, "volume-id",
4169 KEY_STR, iso9660->volume_identifier.s);
4170 if (iso9660->opt.zisofs != OPT_ZISOFS_DEFAULT)
4171 set_option_info(&info, &opt, "zisofs",
4172 KEY_FLG, iso9660->opt.zisofs);
4174 memcpy(wb_buffptr(a), info.s, info_size);
4175 archive_string_free(&info);
4176 return (wb_consume(a, info_size));
4180 write_rr_ER(struct archive_write *a)
4186 memset(p, 0, LOGICAL_BLOCK_SIZE);
4190 p[2] = RRIP_ER_SIZE;
4191 p[4] = RRIP_ER_ID_SIZE;
4192 p[5] = RRIP_ER_DSC_SIZE;
4193 p[6] = RRIP_ER_SRC_SIZE;
4195 memcpy(&p[8], rrip_identifier, p[4]);
4196 memcpy(&p[8+p[4]], rrip_descriptor, p[5]);
4197 memcpy(&p[8+p[4]+p[5]], rrip_source, p[6]);
4199 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4203 calculate_path_table_size(struct vdd *vdd)
4206 struct path_table *pt;
4210 for (depth = 0; depth < vdd->max_depth; depth++) {
4211 struct isoent **ptbl;
4214 if ((cnt = pt[depth].cnt) == 0)
4217 ptbl = pt[depth].sorted;
4218 for (i = 0; i < cnt; i++) {
4221 if (ptbl[i]->identifier == NULL)
4222 len = 1; /* root directory */
4224 len = ptbl[i]->id_len;
4226 len++; /* Padding Field */
4230 vdd->path_table_size = size;
4231 vdd->path_table_block =
4232 ((size + PATH_TABLE_BLOCK_SIZE -1) /
4233 PATH_TABLE_BLOCK_SIZE) *
4234 (PATH_TABLE_BLOCK_SIZE / LOGICAL_BLOCK_SIZE);
4238 _write_path_table(struct archive_write *a, int type_m, int depth,
4241 unsigned char *bp, *wb;
4242 struct isoent **ptbl;
4246 if (vdd->pathtbl[depth].cnt == 0)
4251 wbremaining = wb_remaining(a);
4253 ptbl = vdd->pathtbl[depth].sorted;
4254 for (i = 0; i < vdd->pathtbl[depth].cnt; i++) {
4259 if (np->identifier == NULL)
4260 len = 1; /* root directory */
4263 if (wbremaining - ((bp+1) - wb) < (len + 1 + 8)) {
4264 r = wb_consume(a, (bp+1) - wb);
4268 wbremaining = wb_remaining(a);
4271 /* Length of Directory Identifier */
4272 set_num_711(bp+1, (unsigned char)len);
4273 /* Extended Attribute Record Length */
4274 set_num_711(bp+2, 0);
4275 /* Location of Extent */
4277 set_num_732(bp+3, np->dir_location);
4279 set_num_731(bp+3, np->dir_location);
4280 /* Parent Directory Number */
4282 set_num_722(bp+7, np->parent->dir_number);
4284 set_num_721(bp+7, np->parent->dir_number);
4285 /* Directory Identifier */
4286 if (np->identifier == NULL)
4289 memcpy(&bp[9], np->identifier, len);
4295 wsize += 8 + (int)len;
4298 if ((bp + 1) > wb) {
4299 r = wb_consume(a, (bp+1)-wb);
4307 write_path_table(struct archive_write *a, int type_m, struct vdd *vdd)
4310 size_t path_table_size;
4313 path_table_size = 0;
4314 for (depth = 0; depth < vdd->max_depth; depth++) {
4315 r = _write_path_table(a, type_m, depth, vdd);
4318 path_table_size += r;
4321 /* Write padding data. */
4322 path_table_size = path_table_size % PATH_TABLE_BLOCK_SIZE;
4323 if (path_table_size > 0)
4324 r = write_null(a, PATH_TABLE_BLOCK_SIZE - path_table_size);
4329 calculate_directory_descriptors(struct iso9660 *iso9660, struct vdd *vdd,
4330 struct isoent *isoent, int depth)
4332 struct isoent **enttbl;
4336 bs = get_dir_rec_size(iso9660, isoent, DIR_REC_SELF, vdd->vdd_type);
4337 bs += get_dir_rec_size(iso9660, isoent, DIR_REC_PARENT, vdd->vdd_type);
4339 if (isoent->children.cnt <= 0 || (vdd->vdd_type != VDD_JOLIET &&
4340 !iso9660->opt.rr && depth + 1 >= vdd->max_depth))
4343 enttbl = isoent->children_sorted;
4344 for (i = 0; i < isoent->children.cnt; i++) {
4345 struct isoent *np = enttbl[i];
4346 struct isofile *file;
4349 if (file->hardlink_target != NULL)
4350 file = file->hardlink_target;
4351 file->cur_content = &(file->content);
4355 dr_l = get_dir_rec_size(iso9660, np, DIR_REC_NORMAL,
4357 if ((bs + dr_l) > LOGICAL_BLOCK_SIZE) {
4362 file->cur_content = file->cur_content->next;
4363 } while (file->cur_content != NULL);
4369 _write_directory_descriptors(struct archive_write *a, struct vdd *vdd,
4370 struct isoent *isoent, int depth)
4372 struct iso9660 *iso9660 = a->format_data;
4373 struct isoent **enttbl;
4374 unsigned char *p, *wb;
4378 p = wb = wb_buffptr(a);
4379 #define WD_REMAINING (LOGICAL_BLOCK_SIZE - (p - wb))
4380 p += set_directory_record(p, WD_REMAINING, isoent,
4381 iso9660, DIR_REC_SELF, vdd->vdd_type);
4382 p += set_directory_record(p, WD_REMAINING, isoent,
4383 iso9660, DIR_REC_PARENT, vdd->vdd_type);
4385 if (isoent->children.cnt <= 0 || (vdd->vdd_type != VDD_JOLIET &&
4386 !iso9660->opt.rr && depth + 1 >= vdd->max_depth)) {
4387 memset(p, 0, WD_REMAINING);
4388 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4391 enttbl = isoent->children_sorted;
4392 for (i = 0; i < isoent->children.cnt; i++) {
4393 struct isoent *np = enttbl[i];
4394 struct isofile *file = np->file;
4396 if (file->hardlink_target != NULL)
4397 file = file->hardlink_target;
4398 file->cur_content = &(file->content);
4400 dr_l = set_directory_record(p, WD_REMAINING,
4401 np, iso9660, DIR_REC_NORMAL,
4404 memset(p, 0, WD_REMAINING);
4405 r = wb_consume(a, LOGICAL_BLOCK_SIZE);
4408 p = wb = wb_buffptr(a);
4409 dr_l = set_directory_record(p,
4410 WD_REMAINING, np, iso9660,
4411 DIR_REC_NORMAL, vdd->vdd_type);
4414 file->cur_content = file->cur_content->next;
4415 } while (file->cur_content != NULL);
4417 memset(p, 0, WD_REMAINING);
4418 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4422 write_directory_descriptors(struct archive_write *a, struct vdd *vdd)
4430 struct extr_rec *extr;
4432 r = _write_directory_descriptors(a, vdd, np, depth);
4435 if (vdd->vdd_type != VDD_JOLIET) {
4437 * This extract record is used by SUSP,RRIP.
4440 for (extr = np->extr_rec_list.first;
4442 extr = extr->next) {
4446 memcpy(wb, extr->buf, extr->offset);
4447 memset(wb + extr->offset, 0,
4448 LOGICAL_BLOCK_SIZE - extr->offset);
4449 r = wb_consume(a, LOGICAL_BLOCK_SIZE);
4455 if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) {
4456 /* Enter to sub directories. */
4457 np = np->subdirs.first;
4461 while (np != np->parent) {
4462 if (np->drnext == NULL) {
4463 /* Return to the parent directory. */
4471 } while (np != np->parent);
4473 return (ARCHIVE_OK);
4477 * Read file contents from the temporary file, and write it.
4480 write_file_contents(struct archive_write *a, int64_t offset, int64_t size)
4482 struct iso9660 *iso9660 = a->format_data;
4485 lseek(iso9660->temp_fd, offset, SEEK_SET);
4493 rsize = wb_remaining(a);
4494 if (rsize > (size_t)size)
4495 rsize = (size_t)size;
4496 rs = read(iso9660->temp_fd, wb, rsize);
4498 archive_set_error(&a->archive, errno,
4499 "Can't read temporary file(%jd)", (intmax_t)rs);
4500 return (ARCHIVE_FATAL);
4503 r = wb_consume(a, rs);
4507 return (ARCHIVE_OK);
4511 write_file_descriptors(struct archive_write *a)
4513 struct iso9660 *iso9660 = a->format_data;
4514 struct isofile *file;
4515 int64_t blocks, offset;
4521 /* Make the boot catalog contents, and write it. */
4522 if (iso9660->el_torito.catalog != NULL) {
4523 r = make_boot_catalog(a);
4528 /* Write the boot file contents. */
4529 if (iso9660->el_torito.boot != NULL) {
4530 file = iso9660->el_torito.boot->file;
4531 blocks = file->content.blocks;
4532 offset = file->content.offset_of_temp;
4534 r = write_file_contents(a, offset,
4535 blocks << LOGICAL_BLOCK_BITS);
4543 /* Write out all file contents. */
4544 for (file = iso9660->data_file_list.first;
4545 file != NULL; file = file->datanext) {
4547 if (!file->write_content)
4550 if ((offset + (blocks << LOGICAL_BLOCK_BITS)) <
4551 file->content.offset_of_temp) {
4553 r = write_file_contents(a, offset,
4554 blocks << LOGICAL_BLOCK_BITS);
4559 offset = file->content.offset_of_temp;
4562 file->cur_content = &(file->content);
4564 blocks += file->cur_content->blocks;
4566 file->cur_content = file->cur_content->next;
4567 } while (file->cur_content != NULL);
4570 /* Flush out remaining blocks. */
4572 r = write_file_contents(a, offset,
4573 blocks << LOGICAL_BLOCK_BITS);
4578 return (ARCHIVE_OK);
4582 isofile_init_entry_list(struct iso9660 *iso9660)
4584 iso9660->all_file_list.first = NULL;
4585 iso9660->all_file_list.last = &(iso9660->all_file_list.first);
4589 isofile_add_entry(struct iso9660 *iso9660, struct isofile *file)
4591 file->allnext = NULL;
4592 *iso9660->all_file_list.last = file;
4593 iso9660->all_file_list.last = &(file->allnext);
4597 isofile_free_all_entries(struct iso9660 *iso9660)
4599 struct isofile *file, *file_next;
4601 file = iso9660->all_file_list.first;
4602 while (file != NULL) {
4603 file_next = file->allnext;
4610 isofile_init_entry_data_file_list(struct iso9660 *iso9660)
4612 iso9660->data_file_list.first = NULL;
4613 iso9660->data_file_list.last = &(iso9660->data_file_list.first);
4617 isofile_add_data_file(struct iso9660 *iso9660, struct isofile *file)
4619 file->datanext = NULL;
4620 *iso9660->data_file_list.last = file;
4621 iso9660->data_file_list.last = &(file->datanext);
4625 static struct isofile *
4626 isofile_new(struct archive_write *a, struct archive_entry *entry)
4628 struct isofile *file;
4630 file = calloc(1, sizeof(*file));
4635 file->entry = archive_entry_clone(entry);
4637 file->entry = archive_entry_new2(&a->archive);
4638 if (file->entry == NULL) {
4642 archive_string_init(&(file->parentdir));
4643 archive_string_init(&(file->basename));
4644 archive_string_init(&(file->basename_utf16));
4645 archive_string_init(&(file->symlink));
4646 file->cur_content = &(file->content);
4652 isofile_free(struct isofile *file)
4654 struct content *con, *tmp;
4656 con = file->content.next;
4657 while (con != NULL) {
4662 archive_entry_free(file->entry);
4663 archive_string_free(&(file->parentdir));
4664 archive_string_free(&(file->basename));
4665 archive_string_free(&(file->basename_utf16));
4666 archive_string_free(&(file->symlink));
4670 #if defined(_WIN32) || defined(__CYGWIN__)
4672 cleanup_backslash_1(char *p)
4678 if (*(unsigned char *)p > 127)
4681 /* If we have not met any multi-byte characters,
4682 * we can replace '\' with '/'. */
4695 cleanup_backslash_2(wchar_t *p)
4698 /* Convert a path-separator from '\' to '/' */
4699 while (*p != L'\0') {
4708 * Generate a parent directory name and a base name from a pathname.
4711 isofile_gen_utility_names(struct archive_write *a, struct isofile *file)
4713 struct iso9660 *iso9660;
4714 const char *pathname;
4715 char *p, *dirname, *slash;
4717 int ret = ARCHIVE_OK;
4719 iso9660 = a->format_data;
4721 archive_string_empty(&(file->parentdir));
4722 archive_string_empty(&(file->basename));
4723 archive_string_empty(&(file->basename_utf16));
4724 archive_string_empty(&(file->symlink));
4726 pathname = archive_entry_pathname(file->entry);
4727 if (pathname == NULL || pathname[0] == '\0') {/* virtual root */
4733 * Make a UTF-16BE basename if Joliet extension enabled.
4735 if (iso9660->opt.joliet) {
4736 const char *u16, *ulast;
4737 size_t u16len, ulen_last;
4739 if (iso9660->sconv_to_utf16be == NULL) {
4740 iso9660->sconv_to_utf16be =
4741 archive_string_conversion_to_charset(
4742 &(a->archive), "UTF-16BE", 1);
4743 if (iso9660->sconv_to_utf16be == NULL)
4744 /* Couldn't allocate memory */
4745 return (ARCHIVE_FATAL);
4746 iso9660->sconv_from_utf16be =
4747 archive_string_conversion_from_charset(
4748 &(a->archive), "UTF-16BE", 1);
4749 if (iso9660->sconv_from_utf16be == NULL)
4750 /* Couldn't allocate memory */
4751 return (ARCHIVE_FATAL);
4755 * Convert a filename to UTF-16BE.
4757 if (0 > archive_entry_pathname_l(file->entry, &u16, &u16len,
4758 iso9660->sconv_to_utf16be)) {
4759 if (errno == ENOMEM) {
4760 archive_set_error(&a->archive, ENOMEM,
4761 "Can't allocate memory for UTF-16BE");
4762 return (ARCHIVE_FATAL);
4764 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
4765 "A filename cannot be converted to UTF-16BE;"
4766 "You should disable making Joliet extension");
4771 * Make sure a path separator is not in the last;
4772 * Remove trailing '/'.
4774 while (u16len >= 2) {
4775 #if defined(_WIN32) || defined(__CYGWIN__)
4776 if (u16[u16len-2] == 0 &&
4777 (u16[u16len-1] == '/' || u16[u16len-1] == '\\'))
4779 if (u16[u16len-2] == 0 && u16[u16len-1] == '/')
4788 * Find a basename in UTF-16BE.
4793 while (u16len > 0) {
4794 #if defined(_WIN32) || defined(__CYGWIN__)
4795 if (u16[0] == 0 && (u16[1] == '/' || u16[1] == '\\'))
4797 if (u16[0] == 0 && u16[1] == '/')
4801 ulen_last = u16len -1;
4807 if (archive_string_ensure(&(file->basename_utf16),
4808 ulen_last) == NULL) {
4809 archive_set_error(&a->archive, ENOMEM,
4810 "Can't allocate memory for UTF-16BE");
4811 return (ARCHIVE_FATAL);
4815 * Set UTF-16BE basename.
4817 memcpy(file->basename_utf16.s, ulast, ulen_last);
4818 file->basename_utf16.length = ulen_last;
4821 archive_strcpy(&(file->parentdir), pathname);
4822 #if defined(_WIN32) || defined(__CYGWIN__)
4824 * Convert a path-separator from '\' to '/'
4826 if (cleanup_backslash_1(file->parentdir.s) != 0) {
4827 const wchar_t *wp = archive_entry_pathname_w(file->entry);
4828 struct archive_wstring ws;
4832 archive_string_init(&ws);
4833 archive_wstrcpy(&ws, wp);
4834 cleanup_backslash_2(ws.s);
4835 archive_string_empty(&(file->parentdir));
4836 r = archive_string_append_from_wcs(&(file->parentdir),
4838 archive_wstring_free(&ws);
4839 if (r < 0 && errno == ENOMEM) {
4840 archive_set_error(&a->archive, ENOMEM,
4841 "Can't allocate memory");
4842 return (ARCHIVE_FATAL);
4848 len = file->parentdir.length;
4849 p = dirname = file->parentdir.s;
4852 * Remove leading '/', '../' and './' elements
4858 } else if (p[0] != '.')
4860 else if (p[1] == '.' && p[2] == '/') {
4863 } else if (p[1] == '/' || (p[1] == '.' && p[2] == '\0')) {
4866 } else if (p[1] == '\0') {
4873 memmove(dirname, p, len+1);
4877 * Remove "/","/." and "/.." elements from tail.
4882 if (len > 0 && p[len-1] == '/') {
4886 if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
4890 if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
4901 /* Convert '//' --> '/' */
4902 memmove(p, p+1, strlen(p+1) + 1);
4903 else if (p[1] == '.' && p[2] == '/')
4904 /* Convert '/./' --> '/' */
4905 memmove(p, p+2, strlen(p+2) + 1);
4906 else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
4907 /* Convert 'dir/dir1/../dir2/'
4911 while (rp >= dirname) {
4920 strcpy(dirname, p+4);
4931 if (archive_entry_filetype(file->entry) == AE_IFLNK) {
4932 /* Convert symlink name too. */
4933 pathname = archive_entry_symlink(file->entry);
4934 archive_strcpy(&(file->symlink), pathname);
4935 #if defined(_WIN32) || defined(__CYGWIN__)
4937 * Convert a path-separator from '\' to '/'
4939 if (archive_strlen(&(file->symlink)) > 0 &&
4940 cleanup_backslash_1(file->symlink.s) != 0) {
4942 archive_entry_symlink_w(file->entry);
4943 struct archive_wstring ws;
4947 archive_string_init(&ws);
4948 archive_wstrcpy(&ws, wp);
4949 cleanup_backslash_2(ws.s);
4950 archive_string_empty(&(file->symlink));
4951 r = archive_string_append_from_wcs(
4954 archive_wstring_free(&ws);
4955 if (r < 0 && errno == ENOMEM) {
4956 archive_set_error(&a->archive, ENOMEM,
4957 "Can't allocate memory");
4958 return (ARCHIVE_FATAL);
4965 * - Count up directory elements.
4966 * - Find out the position which points the last position of
4967 * path separator('/').
4971 for (; *p != '\0'; p++)
4976 if (slash == NULL) {
4977 /* The pathname doesn't have a parent directory. */
4978 file->parentdir.length = len;
4979 archive_string_copy(&(file->basename), &(file->parentdir));
4980 archive_string_empty(&(file->parentdir));
4981 *file->parentdir.s = '\0';
4985 /* Make a basename from dirname and slash */
4987 file->parentdir.length = slash - dirname;
4988 archive_strcpy(&(file->basename), slash + 1);
4989 if (archive_entry_filetype(file->entry) == AE_IFDIR)
4995 * Register a entry to get a hardlink target.
4998 isofile_register_hardlink(struct archive_write *a, struct isofile *file)
5000 struct iso9660 *iso9660 = a->format_data;
5001 struct hardlink *hl;
5002 const char *pathname;
5004 archive_entry_set_nlink(file->entry, 1);
5005 pathname = archive_entry_hardlink(file->entry);
5006 if (pathname == NULL) {
5007 /* This `file` is a hardlink target. */
5008 hl = malloc(sizeof(*hl));
5010 archive_set_error(&a->archive, ENOMEM,
5011 "Can't allocate memory");
5012 return (ARCHIVE_FATAL);
5015 /* A hardlink target must be the first position. */
5016 file->hlnext = NULL;
5017 hl->file_list.first = file;
5018 hl->file_list.last = &(file->hlnext);
5019 __archive_rb_tree_insert_node(&(iso9660->hardlink_rbtree),
5020 (struct archive_rb_node *)hl);
5022 hl = (struct hardlink *)__archive_rb_tree_find_node(
5023 &(iso9660->hardlink_rbtree), pathname);
5025 /* Insert `file` entry into the tail. */
5026 file->hlnext = NULL;
5027 *hl->file_list.last = file;
5028 hl->file_list.last = &(file->hlnext);
5031 archive_entry_unset_size(file->entry);
5034 return (ARCHIVE_OK);
5038 * Hardlinked files have to have the same location of extent.
5039 * We have to find out hardlink target entries for the entries
5040 * which have a hardlink target name.
5043 isofile_connect_hardlink_files(struct iso9660 *iso9660)
5045 struct archive_rb_node *n;
5046 struct hardlink *hl;
5047 struct isofile *target, *nf;
5049 ARCHIVE_RB_TREE_FOREACH(n, &(iso9660->hardlink_rbtree)) {
5050 hl = (struct hardlink *)n;
5052 /* The first entry must be a hardlink target. */
5053 target = hl->file_list.first;
5054 archive_entry_set_nlink(target->entry, hl->nlink);
5055 /* Set a hardlink target to reference entries. */
5056 for (nf = target->hlnext;
5057 nf != NULL; nf = nf->hlnext) {
5058 nf->hardlink_target = target;
5059 archive_entry_set_nlink(nf->entry, hl->nlink);
5065 isofile_hd_cmp_node(const struct archive_rb_node *n1,
5066 const struct archive_rb_node *n2)
5068 const struct hardlink *h1 = (const struct hardlink *)n1;
5069 const struct hardlink *h2 = (const struct hardlink *)n2;
5071 return (strcmp(archive_entry_pathname(h1->file_list.first->entry),
5072 archive_entry_pathname(h2->file_list.first->entry)));
5076 isofile_hd_cmp_key(const struct archive_rb_node *n, const void *key)
5078 const struct hardlink *h = (const struct hardlink *)n;
5080 return (strcmp(archive_entry_pathname(h->file_list.first->entry),
5081 (const char *)key));
5085 isofile_init_hardlinks(struct iso9660 *iso9660)
5087 static const struct archive_rb_tree_ops rb_ops = {
5088 isofile_hd_cmp_node, isofile_hd_cmp_key,
5091 __archive_rb_tree_init(&(iso9660->hardlink_rbtree), &rb_ops);
5095 isofile_free_hardlinks(struct iso9660 *iso9660)
5097 struct archive_rb_node *n, *tmp;
5099 ARCHIVE_RB_TREE_FOREACH_SAFE(n, &(iso9660->hardlink_rbtree), tmp) {
5100 __archive_rb_tree_remove_node(&(iso9660->hardlink_rbtree), n);
5105 static struct isoent *
5106 isoent_new(struct isofile *file)
5108 struct isoent *isoent;
5109 static const struct archive_rb_tree_ops rb_ops = {
5110 isoent_cmp_node, isoent_cmp_key,
5113 isoent = calloc(1, sizeof(*isoent));
5116 isoent->file = file;
5117 isoent->children.first = NULL;
5118 isoent->children.last = &(isoent->children.first);
5119 __archive_rb_tree_init(&(isoent->rbtree), &rb_ops);
5120 isoent->subdirs.first = NULL;
5121 isoent->subdirs.last = &(isoent->subdirs.first);
5122 isoent->extr_rec_list.first = NULL;
5123 isoent->extr_rec_list.last = &(isoent->extr_rec_list.first);
5124 isoent->extr_rec_list.current = NULL;
5125 if (archive_entry_filetype(file->entry) == AE_IFDIR)
5131 static inline struct isoent *
5132 isoent_clone(struct isoent *src)
5134 return (isoent_new(src->file));
5138 _isoent_free(struct isoent *isoent)
5140 struct extr_rec *er, *er_next;
5142 free(isoent->children_sorted);
5143 free(isoent->identifier);
5144 er = isoent->extr_rec_list.first;
5145 while (er != NULL) {
5154 isoent_free_all(struct isoent *isoent)
5156 struct isoent *np, *np_temp;
5163 if (np->children.first != NULL) {
5164 /* Enter to sub directories. */
5165 np = np->children.first;
5171 if (np->chnext == NULL) {
5172 /* Return to the parent directory. */
5174 _isoent_free(np_temp);
5179 _isoent_free(np_temp);
5186 static struct isoent *
5187 isoent_create_virtual_dir(struct archive_write *a, struct iso9660 *iso9660, const char *pathname)
5189 struct isofile *file;
5190 struct isoent *isoent;
5192 file = isofile_new(a, NULL);
5195 archive_entry_set_pathname(file->entry, pathname);
5196 archive_entry_unset_mtime(file->entry);
5197 archive_entry_unset_atime(file->entry);
5198 archive_entry_unset_ctime(file->entry);
5199 archive_entry_set_uid(file->entry, getuid());
5200 archive_entry_set_gid(file->entry, getgid());
5201 archive_entry_set_mode(file->entry, 0555 | AE_IFDIR);
5202 archive_entry_set_nlink(file->entry, 2);
5203 if (isofile_gen_utility_names(a, file) < ARCHIVE_WARN) {
5207 isofile_add_entry(iso9660, file);
5209 isoent = isoent_new(file);
5213 isoent->virtual = 1;
5219 isoent_cmp_node(const struct archive_rb_node *n1,
5220 const struct archive_rb_node *n2)
5222 const struct isoent *e1 = (const struct isoent *)n1;
5223 const struct isoent *e2 = (const struct isoent *)n2;
5225 return (strcmp(e1->file->basename.s, e2->file->basename.s));
5229 isoent_cmp_key(const struct archive_rb_node *n, const void *key)
5231 const struct isoent *e = (const struct isoent *)n;
5233 return (strcmp(e->file->basename.s, (const char *)key));
5237 isoent_add_child_head(struct isoent *parent, struct isoent *child)
5240 if (!__archive_rb_tree_insert_node(
5241 &(parent->rbtree), (struct archive_rb_node *)child))
5243 if ((child->chnext = parent->children.first) == NULL)
5244 parent->children.last = &(child->chnext);
5245 parent->children.first = child;
5246 parent->children.cnt++;
5247 child->parent = parent;
5249 /* Add a child to a sub-directory chain */
5251 if ((child->drnext = parent->subdirs.first) == NULL)
5252 parent->subdirs.last = &(child->drnext);
5253 parent->subdirs.first = child;
5254 parent->subdirs.cnt++;
5255 child->parent = parent;
5257 child->drnext = NULL;
5262 isoent_add_child_tail(struct isoent *parent, struct isoent *child)
5265 if (!__archive_rb_tree_insert_node(
5266 &(parent->rbtree), (struct archive_rb_node *)child))
5268 child->chnext = NULL;
5269 *parent->children.last = child;
5270 parent->children.last = &(child->chnext);
5271 parent->children.cnt++;
5272 child->parent = parent;
5274 /* Add a child to a sub-directory chain */
5275 child->drnext = NULL;
5277 *parent->subdirs.last = child;
5278 parent->subdirs.last = &(child->drnext);
5279 parent->subdirs.cnt++;
5280 child->parent = parent;
5286 isoent_remove_child(struct isoent *parent, struct isoent *child)
5290 /* Remove a child entry from children chain. */
5291 ent = parent->children.first;
5292 while (ent->chnext != child)
5294 if ((ent->chnext = ent->chnext->chnext) == NULL)
5295 parent->children.last = &(ent->chnext);
5296 parent->children.cnt--;
5299 /* Remove a child entry from sub-directory chain. */
5300 ent = parent->subdirs.first;
5301 while (ent->drnext != child)
5303 if ((ent->drnext = ent->drnext->drnext) == NULL)
5304 parent->subdirs.last = &(ent->drnext);
5305 parent->subdirs.cnt--;
5308 __archive_rb_tree_remove_node(&(parent->rbtree),
5309 (struct archive_rb_node *)child);
5313 isoent_clone_tree(struct archive_write *a, struct isoent **nroot,
5314 struct isoent *root)
5316 struct isoent *np, *xroot, *newent;
5321 newent = isoent_clone(np);
5322 if (newent == NULL) {
5323 archive_set_error(&a->archive, ENOMEM,
5324 "Can't allocate memory");
5325 return (ARCHIVE_FATAL);
5327 if (xroot == NULL) {
5328 *nroot = xroot = newent;
5329 newent->parent = xroot;
5331 isoent_add_child_tail(xroot, newent);
5332 if (np->dir && np->children.first != NULL) {
5333 /* Enter to sub directories. */
5334 np = np->children.first;
5338 while (np != np->parent) {
5339 if (np->chnext == NULL) {
5340 /* Return to the parent directory. */
5342 xroot = xroot->parent;
5348 } while (np != np->parent);
5350 return (ARCHIVE_OK);
5354 * Setup directory locations.
5357 isoent_setup_directory_location(struct iso9660 *iso9660, int location,
5363 vdd->total_dir_block = 0;
5369 np->dir_block = calculate_directory_descriptors(
5370 iso9660, vdd, np, depth);
5371 vdd->total_dir_block += np->dir_block;
5372 np->dir_location = location;
5373 location += np->dir_block;
5374 block = extra_setup_location(np, location);
5375 vdd->total_dir_block += block;
5378 if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) {
5379 /* Enter to sub directories. */
5380 np = np->subdirs.first;
5384 while (np != np->parent) {
5385 if (np->drnext == NULL) {
5386 /* Return to the parent directory. */
5394 } while (np != np->parent);
5398 _isoent_file_location(struct iso9660 *iso9660, struct isoent *isoent,
5401 struct isoent **children;
5404 if (isoent->children.cnt == 0)
5407 children = isoent->children_sorted;
5408 for (n = 0; n < isoent->children.cnt; n++) {
5410 struct isofile *file;
5415 if (np == iso9660->el_torito.boot)
5418 if (file->boot || file->hardlink_target != NULL)
5420 if (archive_entry_filetype(file->entry) == AE_IFLNK ||
5421 file->content.size == 0) {
5423 * Do not point a valid location.
5424 * Make sure entry is not hardlink file.
5426 file->content.location = (*symlocation)--;
5430 file->write_content = 1;
5435 * Setup file locations.
5438 isoent_setup_file_location(struct iso9660 *iso9660, int location)
5440 struct isoent *isoent;
5442 struct isofile *file;
5450 iso9660->total_file_block = 0;
5451 if ((isoent = iso9660->el_torito.catalog) != NULL) {
5452 isoent->file->content.location = location;
5453 block = (int)((archive_entry_size(isoent->file->entry) +
5454 LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS);
5456 iso9660->total_file_block += block;
5458 if ((isoent = iso9660->el_torito.boot) != NULL) {
5459 isoent->file->content.location = location;
5460 size = fd_boot_image_size(iso9660->el_torito.media_type);
5462 size = (size_t)archive_entry_size(isoent->file->entry);
5463 block = ((int)size + LOGICAL_BLOCK_SIZE -1)
5464 >> LOGICAL_BLOCK_BITS;
5466 iso9660->total_file_block += block;
5467 isoent->file->content.blocks = block;
5472 if (!iso9660->opt.rr && iso9660->opt.joliet) {
5474 np = iso9660->joliet.rootent;
5477 np = iso9660->primary.rootent;
5480 _isoent_file_location(iso9660, np, &symlocation);
5482 if (np->subdirs.first != NULL &&
5484 ((iso9660->opt.rr == OPT_RR_DISABLED &&
5485 depth + 2 < iso9660->primary.max_depth) ||
5487 depth + 1 < iso9660->primary.max_depth)))) {
5488 /* Enter to sub directories. */
5489 np = np->subdirs.first;
5493 while (np != np->parent) {
5494 if (np->drnext == NULL) {
5495 /* Return to the parent directory. */
5503 } while (np != np->parent);
5506 for (file = iso9660->data_file_list.first;
5507 file != NULL; file = file->datanext) {
5509 if (!file->write_content)
5512 file->cur_content = &(file->content);
5514 file->cur_content->location = location;
5515 location += file->cur_content->blocks;
5516 total_block += file->cur_content->blocks;
5518 file->cur_content = file->cur_content->next;
5519 } while (file->cur_content != NULL);
5521 iso9660->total_file_block += total_block;
5525 get_path_component(char *name, size_t n, const char *fn)
5530 p = strchr(fn, '/');
5532 if ((l = strlen(fn)) == 0)
5538 memcpy(name, fn, l);
5545 * Add a new entry into the tree.
5548 isoent_tree(struct archive_write *a, struct isoent **isoentpp)
5550 #if defined(_WIN32) && !defined(__CYGWIN__)
5551 char name[_MAX_FNAME];/* Included null terminator size. */
5552 #elif defined(NAME_MAX) && NAME_MAX >= 255
5553 char name[NAME_MAX+1];
5557 struct iso9660 *iso9660 = a->format_data;
5558 struct isoent *dent, *isoent, *np;
5559 struct isofile *f1, *f2;
5564 dent = iso9660->primary.rootent;
5565 if (isoent->file->parentdir.length > 0)
5566 fn = p = isoent->file->parentdir.s;
5571 * If the path of the parent directory of `isoent' entry is
5572 * the same as the path of `cur_dirent', add isoent to
5575 if (archive_strlen(&(iso9660->cur_dirstr))
5576 == archive_strlen(&(isoent->file->parentdir)) &&
5577 strcmp(iso9660->cur_dirstr.s, fn) == 0) {
5578 if (!isoent_add_child_tail(iso9660->cur_dirent, isoent)) {
5579 np = (struct isoent *)__archive_rb_tree_find_node(
5580 &(iso9660->cur_dirent->rbtree),
5581 isoent->file->basename.s);
5584 return (ARCHIVE_OK);
5588 l = get_path_component(name, sizeof(name), fn);
5594 archive_set_error(&a->archive,
5596 "A name buffer is too small");
5597 _isoent_free(isoent);
5598 return (ARCHIVE_FATAL);
5601 np = isoent_find_child(dent, name);
5602 if (np == NULL || fn[0] == '\0')
5605 /* Find next subdirectory. */
5607 /* NOT Directory! */
5608 archive_set_error(&a->archive,
5610 "`%s' is not directory, we cannot insert `%s' ",
5611 archive_entry_pathname(np->file->entry),
5612 archive_entry_pathname(isoent->file->entry));
5613 _isoent_free(isoent);
5615 return (ARCHIVE_FAILED);
5624 * Create virtual parent directories.
5626 while (fn[0] != '\0') {
5628 struct archive_string as;
5630 archive_string_init(&as);
5631 archive_strncat(&as, p, fn - p + l);
5632 if (as.s[as.length-1] == '/') {
5633 as.s[as.length-1] = '\0';
5636 vp = isoent_create_virtual_dir(a, iso9660, as.s);
5638 archive_string_free(&as);
5639 archive_set_error(&a->archive, ENOMEM,
5640 "Can't allocate memory");
5641 _isoent_free(isoent);
5643 return (ARCHIVE_FATAL);
5645 archive_string_free(&as);
5647 if (vp->file->dircnt > iso9660->dircnt_max)
5648 iso9660->dircnt_max = vp->file->dircnt;
5649 isoent_add_child_tail(dent, vp);
5655 l = get_path_component(name, sizeof(name), fn);
5657 archive_string_free(&as);
5658 archive_set_error(&a->archive,
5660 "A name buffer is too small");
5661 _isoent_free(isoent);
5663 return (ARCHIVE_FATAL);
5668 /* Found out the parent directory where isoent can be
5670 iso9660->cur_dirent = dent;
5671 archive_string_empty(&(iso9660->cur_dirstr));
5672 archive_string_ensure(&(iso9660->cur_dirstr),
5673 archive_strlen(&(dent->file->parentdir)) +
5674 archive_strlen(&(dent->file->basename)) + 2);
5675 if (archive_strlen(&(dent->file->parentdir)) +
5676 archive_strlen(&(dent->file->basename)) == 0)
5677 iso9660->cur_dirstr.s[0] = 0;
5679 if (archive_strlen(&(dent->file->parentdir)) > 0) {
5680 archive_string_copy(&(iso9660->cur_dirstr),
5681 &(dent->file->parentdir));
5682 archive_strappend_char(&(iso9660->cur_dirstr), '/');
5684 archive_string_concat(&(iso9660->cur_dirstr),
5685 &(dent->file->basename));
5688 if (!isoent_add_child_tail(dent, isoent)) {
5689 np = (struct isoent *)__archive_rb_tree_find_node(
5690 &(dent->rbtree), isoent->file->basename.s);
5693 return (ARCHIVE_OK);
5698 * We have already has the entry the filename of which is
5704 /* If the file type of entries is different,
5705 * we cannot handle it. */
5706 if (archive_entry_filetype(f1->entry) !=
5707 archive_entry_filetype(f2->entry)) {
5708 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
5709 "Found duplicate entries `%s' and its file type is "
5711 archive_entry_pathname(f1->entry));
5712 _isoent_free(isoent);
5714 return (ARCHIVE_FAILED);
5717 /* Swap file entries. */
5722 _isoent_free(isoent);
5724 return (ARCHIVE_OK);
5728 * Find a entry from `isoent'
5730 static struct isoent *
5731 isoent_find_child(struct isoent *isoent, const char *child_name)
5735 np = (struct isoent *)__archive_rb_tree_find_node(
5736 &(isoent->rbtree), child_name);
5741 * Find a entry full-path of which is specified by `fn' parameter,
5744 static struct isoent *
5745 isoent_find_entry(struct isoent *rootent, const char *fn)
5747 #if defined(_WIN32) && !defined(__CYGWIN__)
5748 char name[_MAX_FNAME];/* Included null terminator size. */
5749 #elif defined(NAME_MAX) && NAME_MAX >= 255
5750 char name[NAME_MAX+1];
5754 struct isoent *isoent, *np;
5760 l = get_path_component(name, sizeof(name), fn);
5767 np = isoent_find_child(isoent, name);
5771 break;/* We found out the entry */
5773 /* Try sub directory. */
5777 break;/* Not directory */
5784 * Following idr_* functions are used for resolving duplicated filenames
5785 * and unreceivable filenames to generate ISO9660/Joliet Identifiers.
5789 idr_relaxed_filenames(char *map)
5793 for (i = 0x21; i <= 0x2F; i++)
5795 for (i = 0x3A; i <= 0x41; i++)
5797 for (i = 0x5B; i <= 0x5E; i++)
5800 for (i = 0x7B; i <= 0x7E; i++)
5805 idr_init(struct iso9660 *iso9660, struct vdd *vdd, struct idr *idr)
5808 idr->idrent_pool = NULL;
5810 if (vdd->vdd_type != VDD_JOLIET) {
5811 if (iso9660->opt.iso_level <= 3) {
5812 memcpy(idr->char_map, d_characters_map,
5813 sizeof(idr->char_map));
5815 memcpy(idr->char_map, d1_characters_map,
5816 sizeof(idr->char_map));
5817 idr_relaxed_filenames(idr->char_map);
5823 idr_cleanup(struct idr *idr)
5825 free(idr->idrent_pool);
5829 idr_ensure_poolsize(struct archive_write *a, struct idr *idr,
5833 if (idr->pool_size < cnt) {
5835 const int bk = (1 << 7) - 1;
5838 psize = (cnt + bk) & ~bk;
5839 p = realloc(idr->idrent_pool, sizeof(struct idrent) * psize);
5841 archive_set_error(&a->archive, ENOMEM,
5842 "Can't allocate memory");
5843 return (ARCHIVE_FATAL);
5845 idr->idrent_pool = (struct idrent *)p;
5846 idr->pool_size = psize;
5848 return (ARCHIVE_OK);
5852 idr_start(struct archive_write *a, struct idr *idr, int cnt, int ffmax,
5853 int num_size, int null_size, const struct archive_rb_tree_ops *rbt_ops)
5857 (void)ffmax; /* UNUSED */
5859 r = idr_ensure_poolsize(a, idr, cnt);
5860 if (r != ARCHIVE_OK)
5862 __archive_rb_tree_init(&(idr->rbtree), rbt_ops);
5863 idr->wait_list.first = NULL;
5864 idr->wait_list.last = &(idr->wait_list.first);
5866 idr->num_size = num_size;
5867 idr->null_size = null_size;
5868 return (ARCHIVE_OK);
5872 idr_register(struct idr *idr, struct isoent *isoent, int weight, int noff)
5874 struct idrent *idrent, *n;
5876 idrent = &(idr->idrent_pool[idr->pool_idx++]);
5877 idrent->wnext = idrent->avail = NULL;
5878 idrent->isoent = isoent;
5879 idrent->weight = weight;
5880 idrent->noff = noff;
5881 idrent->rename_num = 0;
5883 if (!__archive_rb_tree_insert_node(&(idr->rbtree), &(idrent->rbnode))) {
5884 n = (struct idrent *)__archive_rb_tree_find_node(
5885 &(idr->rbtree), idrent->isoent);
5887 /* this `idrent' needs to rename. */
5889 *idr->wait_list.last = idrent;
5890 idr->wait_list.last = &(idrent->wnext);
5896 idr_extend_identifier(struct idrent *wnp, int numsize, int nullsize)
5901 wnp_ext_off = wnp->isoent->ext_off;
5902 if (wnp->noff + numsize != wnp_ext_off) {
5903 p = (unsigned char *)wnp->isoent->identifier;
5904 /* Extend the filename; foo.c --> foo___.c */
5905 memmove(p + wnp->noff + numsize, p + wnp_ext_off,
5906 wnp->isoent->ext_len + nullsize);
5907 wnp->isoent->ext_off = wnp_ext_off = wnp->noff + numsize;
5908 wnp->isoent->id_len = wnp_ext_off + wnp->isoent->ext_len;
5913 idr_resolve(struct idr *idr, void (*fsetnum)(unsigned char *p, int num))
5918 for (n = idr->wait_list.first; n != NULL; n = n->wnext) {
5919 idr_extend_identifier(n, idr->num_size, idr->null_size);
5920 p = (unsigned char *)n->isoent->identifier + n->noff;
5922 fsetnum(p, n->avail->rename_num++);
5923 } while (!__archive_rb_tree_insert_node(
5924 &(idr->rbtree), &(n->rbnode)));
5929 idr_set_num(unsigned char *p, int num)
5931 static const char xdig[] = {
5932 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
5933 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
5934 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
5935 'U', 'V', 'W', 'X', 'Y', 'Z'
5938 num %= sizeof(xdig) * sizeof(xdig) * sizeof(xdig);
5939 p[0] = xdig[(num / (sizeof(xdig) * sizeof(xdig)))];
5940 num %= sizeof(xdig) * sizeof(xdig);
5941 p[1] = xdig[ (num / sizeof(xdig))];
5942 num %= sizeof(xdig);
5947 idr_set_num_beutf16(unsigned char *p, int num)
5949 static const uint16_t xdig[] = {
5950 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
5951 0x0036, 0x0037, 0x0038, 0x0039,
5952 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046,
5953 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C,
5954 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052,
5955 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
5958 #define XDIG_CNT (sizeof(xdig)/sizeof(xdig[0]))
5960 num %= XDIG_CNT * XDIG_CNT * XDIG_CNT;
5961 archive_be16enc(p, xdig[(num / (XDIG_CNT * XDIG_CNT))]);
5962 num %= XDIG_CNT * XDIG_CNT;
5963 archive_be16enc(p+2, xdig[ (num / XDIG_CNT)]);
5965 archive_be16enc(p+4, xdig[num]);
5969 * Generate ISO9660 Identifier.
5972 isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent,
5975 struct iso9660 *iso9660;
5979 const char *char_map;
5980 char allow_ldots, allow_multidot, allow_period, allow_vernum;
5981 int fnmax, ffmax, dnmax;
5982 static const struct archive_rb_tree_ops rb_ops = {
5983 isoent_cmp_node_iso9660, isoent_cmp_key_iso9660
5986 if (isoent->children.cnt == 0)
5989 iso9660 = a->format_data;
5990 char_map = idr->char_map;
5991 if (iso9660->opt.iso_level <= 3) {
5995 allow_vernum = iso9660->opt.allow_vernum;
5996 if (iso9660->opt.iso_level == 1) {
5998 ffmax = 12;/* fnmax + '.' + 3 */
6006 allow_ldots = allow_multidot = 1;
6007 allow_period = allow_vernum = 0;
6008 if (iso9660->opt.rr)
6010 * MDR : The maximum size of Directory Record(254).
6011 * DRL : A Directory Record Length(33).
6012 * CE : A size of SUSP CE System Use Entry(28).
6013 * MDR - DRL - CE = 254 - 33 - 28 = 193.
6015 fnmax = ffmax = dnmax = 193;
6018 * XA : CD-ROM XA System Use Extension
6020 * MDR - DRL - XA = 254 - 33 -14 = 207.
6022 fnmax = ffmax = dnmax = 207;
6025 r = idr_start(a, idr, isoent->children.cnt, ffmax, 3, 1, &rb_ops);
6029 for (np = isoent->children.first; np != NULL; np = np->chnext) {
6031 int ext_off, noff, weight;
6033 l = (int)np->file->basename.length;
6034 p = malloc(l+31+2+1);
6036 archive_set_error(&a->archive, ENOMEM,
6037 "Can't allocate memory");
6038 return (ARCHIVE_FATAL);
6040 memcpy(p, np->file->basename.s, l);
6047 * If there is a '.' character at the first byte,
6048 * it has to be replaced by '_' character.
6058 if (char_map[(unsigned char)*p]) {
6059 /* if iso-level is '4', a character '.' is
6060 * allowed by char_map. */
6067 if (*p >= 'a' && *p <= 'z') {
6097 ext_off = (int)(dot - p);
6099 if (iso9660->opt.iso_level == 1) {
6101 if (strlen(dot) > 4) {
6102 /* A length of a file extension
6103 * must be less than 4 */
6116 } else if (np->dir) {
6120 if (ext_off > dnmax)
6123 } else if (l > ffmax) {
6124 int extlen = (int)strlen(dot);
6128 xdoff = (int)(xdot - p);
6132 if (extlen > 1 && xdoff < fnmax-1) {
6137 off = ffmax - extlen;
6139 /* A dot('.') character
6140 * doesn't place to the first
6141 * byte of identifier. */
6145 memmove(p+off, dot, extlen);
6149 #ifdef COMPAT_MKISOFS
6150 } else if (xdoff >= fnmax-1) {
6151 /* Simulate a bug(?) of mkisofs. */
6163 /* Save an offset of a file name extension to sort files. */
6164 np->ext_off = ext_off;
6165 np->ext_len = (int)strlen(&p[ext_off]);
6166 np->id_len = l = ext_off + np->ext_len;
6168 /* Make an offset of the number which is used to be set
6169 * hexadecimal number to avoid duplicate identifier. */
6170 if (iso9660->opt.iso_level == 1) {
6178 else if (l == ffmax-1)
6180 else if (l == ffmax-2)
6185 /* Register entry to the identifier resolver. */
6186 idr_register(idr, np, weight, noff);
6189 /* Resolve duplicate identifier. */
6190 idr_resolve(idr, idr_set_num);
6192 /* Add a period and a version number to identifiers. */
6193 for (np = isoent->children.first; np != NULL; np = np->chnext) {
6194 if (!np->dir && np->rr_child == NULL) {
6195 p = np->identifier + np->ext_off + np->ext_len;
6196 if (np->ext_len == 0 && allow_period) {
6200 if (np->ext_len == 1 && !allow_period) {
6204 np->id_len = np->ext_off + np->ext_len;
6212 np->id_len = np->ext_off + np->ext_len;
6213 np->mb_len = np->id_len;
6215 return (ARCHIVE_OK);
6219 * Generate Joliet Identifier.
6222 isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent,
6225 struct iso9660 *iso9660;
6230 size_t ffmax, parent_len;
6231 static const struct archive_rb_tree_ops rb_ops = {
6232 isoent_cmp_node_joliet, isoent_cmp_key_joliet
6235 if (isoent->children.cnt == 0)
6238 iso9660 = a->format_data;
6239 if (iso9660->opt.joliet == OPT_JOLIET_LONGNAME)
6244 r = idr_start(a, idr, isoent->children.cnt, (int)ffmax, 6, 2, &rb_ops);
6249 for (np = isoent; np->parent != np; np = np->parent)
6250 parent_len += np->mb_len + 1;
6252 for (np = isoent->children.first; np != NULL; np = np->chnext) {
6254 int ext_off, noff, weight;
6257 if ((l = np->file->basename_utf16.length) > ffmax)
6260 p = malloc((l+1)*2);
6262 archive_set_error(&a->archive, ENOMEM,
6263 "Can't allocate memory");
6264 return (ARCHIVE_FATAL);
6266 memcpy(p, np->file->basename_utf16.s, l);
6270 np->identifier = (char *)p;
6275 if (!joliet_allowed_char(p[0], p[1]))
6276 archive_be16enc(p, 0x005F); /* '_' */
6277 else if (p[0] == 0 && p[1] == 0x2E) /* '.' */
6282 ext_off = (int)(dot - (unsigned char *)np->identifier);
6283 np->ext_off = ext_off;
6284 np->ext_len = (int)l - ext_off;
6285 np->id_len = (int)l;
6288 * Get a length of MBS of a full-pathname.
6290 if (np->file->basename_utf16.length > ffmax) {
6291 if (archive_strncpy_l(&iso9660->mbs,
6292 (const char *)np->identifier, l,
6293 iso9660->sconv_from_utf16be) != 0 &&
6295 archive_set_error(&a->archive, errno,
6297 return (ARCHIVE_FATAL);
6299 np->mb_len = (int)iso9660->mbs.length;
6300 if (np->mb_len != (int)np->file->basename.length)
6301 weight = np->mb_len;
6303 np->mb_len = (int)np->file->basename.length;
6305 /* If a length of full-pathname is longer than 240 bytes,
6306 * it violates Joliet extensions regulation. */
6307 if (parent_len > 240
6309 || parent_len + np->mb_len > 240) {
6310 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
6311 "The regulation of Joliet extensions;"
6312 " A length of a full-pathname of `%s' is "
6313 "longer than 240 bytes, (p=%d, b=%d)",
6314 archive_entry_pathname(np->file->entry),
6315 (int)parent_len, (int)np->mb_len);
6316 return (ARCHIVE_FATAL);
6319 /* Make an offset of the number which is used to be set
6320 * hexadecimal number to avoid duplicate identifier. */
6323 else if (l == ffmax-2)
6325 else if (l == ffmax-4)
6329 /* Register entry to the identifier resolver. */
6330 idr_register(idr, np, weight, noff);
6333 /* Resolve duplicate identifier with Joliet Volume. */
6334 idr_resolve(idr, idr_set_num_beutf16);
6336 return (ARCHIVE_OK);
6340 * This comparing rule is according to ISO9660 Standard 9.3
6343 isoent_cmp_iso9660_identifier(const struct isoent *p1, const struct isoent *p2)
6345 const char *s1, *s2;
6349 s1 = p1->identifier;
6350 s2 = p2->identifier;
6352 /* Compare File Name */
6354 if (l > p2->ext_off)
6356 cmp = memcmp(s1, s2, l);
6359 if (p1->ext_off < p2->ext_off) {
6361 l = p2->ext_off - p1->ext_off;
6365 - *(const unsigned char *)(s2 - 1));
6366 } else if (p1->ext_off > p2->ext_off) {
6368 l = p1->ext_off - p2->ext_off;
6371 return (*(const unsigned char *)(s1 - 1)
6374 /* Compare File Name Extension */
6375 if (p1->ext_len == 0 && p2->ext_len == 0)
6377 if (p1->ext_len == 1 && p2->ext_len == 1)
6379 if (p1->ext_len <= 1)
6381 if (p2->ext_len <= 1)
6384 if (l > p2->ext_len)
6386 s1 = p1->identifier + p1->ext_off;
6387 s2 = p2->identifier + p2->ext_off;
6389 cmp = memcmp(s1, s2, l);
6393 if (p1->ext_len < p2->ext_len) {
6395 l = p2->ext_len - p1->ext_len;
6399 - *(const unsigned char *)(s2 - 1));
6400 } else if (p1->ext_len > p2->ext_len) {
6402 l = p1->ext_len - p2->ext_len;
6405 return (*(const unsigned char *)(s1 - 1)
6408 /* Compare File Version Number */
6409 /* No operation. The File Version Number is always one. */
6415 isoent_cmp_node_iso9660(const struct archive_rb_node *n1,
6416 const struct archive_rb_node *n2)
6418 const struct idrent *e1 = (const struct idrent *)n1;
6419 const struct idrent *e2 = (const struct idrent *)n2;
6421 return (isoent_cmp_iso9660_identifier(e2->isoent, e1->isoent));
6425 isoent_cmp_key_iso9660(const struct archive_rb_node *node, const void *key)
6427 const struct isoent *isoent = (const struct isoent *)key;
6428 const struct idrent *idrent = (const struct idrent *)node;
6430 return (isoent_cmp_iso9660_identifier(isoent, idrent->isoent));
6434 isoent_cmp_joliet_identifier(const struct isoent *p1, const struct isoent *p2)
6436 const unsigned char *s1, *s2;
6440 s1 = (const unsigned char *)p1->identifier;
6441 s2 = (const unsigned char *)p2->identifier;
6443 /* Compare File Name */
6445 if (l > p2->ext_off)
6447 cmp = memcmp(s1, s2, l);
6450 if (p1->ext_off < p2->ext_off) {
6452 l = p2->ext_off - p1->ext_off;
6455 return (- *(const unsigned char *)(s2 - 1));
6456 } else if (p1->ext_off > p2->ext_off) {
6458 l = p1->ext_off - p2->ext_off;
6461 return (*(const unsigned char *)(s1 - 1));
6463 /* Compare File Name Extension */
6464 if (p1->ext_len == 0 && p2->ext_len == 0)
6466 if (p1->ext_len == 2 && p2->ext_len == 2)
6468 if (p1->ext_len <= 2)
6470 if (p2->ext_len <= 2)
6473 if (l > p2->ext_len)
6475 s1 = (unsigned char *)(p1->identifier + p1->ext_off);
6476 s2 = (unsigned char *)(p2->identifier + p2->ext_off);
6478 cmp = memcmp(s1, s2, l);
6482 if (p1->ext_len < p2->ext_len) {
6484 l = p2->ext_len - p1->ext_len;
6487 return (- *(const unsigned char *)(s2 - 1));
6488 } else if (p1->ext_len > p2->ext_len) {
6490 l = p1->ext_len - p2->ext_len;
6493 return (*(const unsigned char *)(s1 - 1));
6495 /* Compare File Version Number */
6496 /* No operation. The File Version Number is always one. */
6502 isoent_cmp_node_joliet(const struct archive_rb_node *n1,
6503 const struct archive_rb_node *n2)
6505 const struct idrent *e1 = (const struct idrent *)n1;
6506 const struct idrent *e2 = (const struct idrent *)n2;
6508 return (isoent_cmp_joliet_identifier(e2->isoent, e1->isoent));
6512 isoent_cmp_key_joliet(const struct archive_rb_node *node, const void *key)
6514 const struct isoent *isoent = (const struct isoent *)key;
6515 const struct idrent *idrent = (const struct idrent *)node;
6517 return (isoent_cmp_joliet_identifier(isoent, idrent->isoent));
6521 isoent_make_sorted_files(struct archive_write *a, struct isoent *isoent,
6524 struct archive_rb_node *rn;
6525 struct isoent **children;
6527 children = malloc(isoent->children.cnt * sizeof(struct isoent *));
6528 if (children == NULL) {
6529 archive_set_error(&a->archive, ENOMEM,
6530 "Can't allocate memory");
6531 return (ARCHIVE_FATAL);
6533 isoent->children_sorted = children;
6535 ARCHIVE_RB_TREE_FOREACH(rn, &(idr->rbtree)) {
6536 struct idrent *idrent = (struct idrent *)rn;
6537 *children ++ = idrent->isoent;
6539 return (ARCHIVE_OK);
6543 * - Generate ISO9660 and Joliet identifiers from basenames.
6544 * - Sort files by each directory.
6547 isoent_traverse_tree(struct archive_write *a, struct vdd* vdd)
6549 struct iso9660 *iso9660 = a->format_data;
6554 int (*genid)(struct archive_write *, struct isoent *, struct idr *);
6556 idr_init(iso9660, vdd, &idr);
6559 if (vdd->vdd_type == VDD_JOLIET)
6560 genid = isoent_gen_joliet_identifier;
6562 genid = isoent_gen_iso9660_identifier;
6565 !archive_entry_mtime_is_set(np->file->entry)) {
6566 /* Set properly times to virtual directory */
6567 archive_entry_set_mtime(np->file->entry,
6568 iso9660->birth_time, 0);
6569 archive_entry_set_atime(np->file->entry,
6570 iso9660->birth_time, 0);
6571 archive_entry_set_ctime(np->file->entry,
6572 iso9660->birth_time, 0);
6574 if (np->children.first != NULL) {
6575 if (vdd->vdd_type != VDD_JOLIET &&
6576 !iso9660->opt.rr && depth + 1 >= vdd->max_depth) {
6577 if (np->children.cnt > 0)
6578 iso9660->directories_too_deep = np;
6580 /* Generate Identifier */
6581 r = genid(a, np, &idr);
6583 goto exit_traverse_tree;
6584 r = isoent_make_sorted_files(a, np, &idr);
6586 goto exit_traverse_tree;
6588 if (np->subdirs.first != NULL &&
6589 depth + 1 < vdd->max_depth) {
6590 /* Enter to sub directories. */
6591 np = np->subdirs.first;
6597 while (np != np->parent) {
6598 if (np->drnext == NULL) {
6599 /* Return to the parent directory. */
6607 } while (np != np->parent);
6617 * Collect directory entries into path_table by a directory depth.
6620 isoent_collect_dirs(struct vdd *vdd, struct isoent *rootent, int depth)
6624 if (rootent == NULL)
6625 rootent = vdd->rootent;
6628 /* Register current directory to pathtable. */
6629 path_table_add_entry(&(vdd->pathtbl[depth]), np);
6631 if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) {
6632 /* Enter to sub directories. */
6633 np = np->subdirs.first;
6637 while (np != rootent) {
6638 if (np->drnext == NULL) {
6639 /* Return to the parent directory. */
6647 } while (np != rootent);
6649 return (ARCHIVE_OK);
6653 * The entry whose number of levels in a directory hierarchy is
6654 * large than eight relocate to rr_move directory.
6657 isoent_rr_move_dir(struct archive_write *a, struct isoent **rr_moved,
6658 struct isoent *curent, struct isoent **newent)
6660 struct iso9660 *iso9660 = a->format_data;
6661 struct isoent *rrmoved, *mvent, *np;
6663 if ((rrmoved = *rr_moved) == NULL) {
6664 struct isoent *rootent = iso9660->primary.rootent;
6665 /* There isn't rr_move entry.
6666 * Create rr_move entry and insert it into the root entry.
6668 rrmoved = isoent_create_virtual_dir(a, iso9660, "rr_moved");
6669 if (rrmoved == NULL) {
6670 archive_set_error(&a->archive, ENOMEM,
6671 "Can't allocate memory");
6672 return (ARCHIVE_FATAL);
6674 /* Add "rr_moved" entry to the root entry. */
6675 isoent_add_child_head(rootent, rrmoved);
6676 archive_entry_set_nlink(rootent->file->entry,
6677 archive_entry_nlink(rootent->file->entry) + 1);
6678 /* Register "rr_moved" entry to second level pathtable. */
6679 path_table_add_entry(&(iso9660->primary.pathtbl[1]), rrmoved);
6680 /* Save rr_moved. */
6681 *rr_moved = rrmoved;
6684 * Make a clone of curent which is going to be relocated
6687 mvent = isoent_clone(curent);
6688 if (mvent == NULL) {
6689 archive_set_error(&a->archive, ENOMEM,
6690 "Can't allocate memory");
6691 return (ARCHIVE_FATAL);
6693 /* linking.. and use for creating "CL", "PL" and "RE" */
6694 mvent->rr_parent = curent->parent;
6695 curent->rr_child = mvent;
6697 * Move subdirectories from the curent to mvent
6699 if (curent->children.first != NULL) {
6700 *mvent->children.last = curent->children.first;
6701 mvent->children.last = curent->children.last;
6703 for (np = mvent->children.first; np != NULL; np = np->chnext)
6705 mvent->children.cnt = curent->children.cnt;
6706 curent->children.cnt = 0;
6707 curent->children.first = NULL;
6708 curent->children.last = &curent->children.first;
6710 if (curent->subdirs.first != NULL) {
6711 *mvent->subdirs.last = curent->subdirs.first;
6712 mvent->subdirs.last = curent->subdirs.last;
6714 mvent->subdirs.cnt = curent->subdirs.cnt;
6715 curent->subdirs.cnt = 0;
6716 curent->subdirs.first = NULL;
6717 curent->subdirs.last = &curent->subdirs.first;
6720 * The mvent becomes a child of the rr_moved entry.
6722 isoent_add_child_tail(rrmoved, mvent);
6723 archive_entry_set_nlink(rrmoved->file->entry,
6724 archive_entry_nlink(rrmoved->file->entry) + 1);
6726 * This entry which relocated to the rr_moved directory
6727 * has to set the flag as a file.
6728 * See also RRIP 4.1.5.1 Description of the "CL" System Use Entry.
6734 return (ARCHIVE_OK);
6738 isoent_rr_move(struct archive_write *a)
6740 struct iso9660 *iso9660 = a->format_data;
6741 struct path_table *pt;
6742 struct isoent *rootent, *rr_moved;
6743 struct isoent *np, *last;
6746 pt = &(iso9660->primary.pathtbl[MAX_DEPTH-1]);
6747 /* There aren't level 8 directories reaching a deeper level. */
6749 return (ARCHIVE_OK);
6751 rootent = iso9660->primary.rootent;
6752 /* If "rr_moved" directory is already existing,
6753 * we have to use it. */
6754 rr_moved = isoent_find_child(rootent, "rr_moved");
6755 if (rr_moved != NULL &&
6756 rr_moved != rootent->children.first) {
6758 * It's necessary that rr_move is the first entry
6761 /* Remove "rr_moved" entry from children chain. */
6762 isoent_remove_child(rootent, rr_moved);
6764 /* Add "rr_moved" entry into the head of children chain. */
6765 isoent_add_child_head(rootent, rr_moved);
6769 * Check level 8 path_table.
6770 * If find out sub directory entries, that entries move to rr_move.
6773 while (np != NULL) {
6774 last = path_table_last_entry(pt);
6775 for (; np != NULL; np = np->ptnext) {
6776 struct isoent *mvent;
6777 struct isoent *newent;
6781 for (mvent = np->subdirs.first;
6782 mvent != NULL; mvent = mvent->drnext) {
6783 r = isoent_rr_move_dir(a, &rr_moved,
6787 isoent_collect_dirs(&(iso9660->primary),
6791 /* If new entries are added to level 8 path_talbe,
6792 * its sub directory entries move to rr_move too.
6797 return (ARCHIVE_OK);
6801 * This comparing rule is according to ISO9660 Standard 6.9.1
6804 _compare_path_table(const void *v1, const void *v2)
6806 const struct isoent *p1, *p2;
6807 const char *s1, *s2;
6810 p1 = *((const struct isoent **)(uintptr_t)v1);
6811 p2 = *((const struct isoent **)(uintptr_t)v2);
6813 /* Compare parent directory number */
6814 cmp = p1->parent->dir_number - p2->parent->dir_number;
6818 /* Compare identifier */
6819 s1 = p1->identifier;
6820 s2 = p2->identifier;
6822 if (l > p2->ext_off)
6824 cmp = strncmp(s1, s2, l);
6827 if (p1->ext_off < p2->ext_off) {
6829 l = p2->ext_off - p1->ext_off;
6833 - *(const unsigned char *)(s2 - 1));
6834 } else if (p1->ext_off > p2->ext_off) {
6836 l = p1->ext_off - p2->ext_off;
6839 return (*(const unsigned char *)(s1 - 1)
6846 _compare_path_table_joliet(const void *v1, const void *v2)
6848 const struct isoent *p1, *p2;
6849 const unsigned char *s1, *s2;
6852 p1 = *((const struct isoent **)(uintptr_t)v1);
6853 p2 = *((const struct isoent **)(uintptr_t)v2);
6855 /* Compare parent directory number */
6856 cmp = p1->parent->dir_number - p2->parent->dir_number;
6860 /* Compare identifier */
6861 s1 = (const unsigned char *)p1->identifier;
6862 s2 = (const unsigned char *)p2->identifier;
6864 if (l > p2->ext_off)
6866 cmp = memcmp(s1, s2, l);
6869 if (p1->ext_off < p2->ext_off) {
6871 l = p2->ext_off - p1->ext_off;
6874 return (- *(const unsigned char *)(s2 - 1));
6875 } else if (p1->ext_off > p2->ext_off) {
6877 l = p1->ext_off - p2->ext_off;
6880 return (*(const unsigned char *)(s1 - 1));
6886 path_table_add_entry(struct path_table *pathtbl, struct isoent *ent)
6889 *pathtbl->last = ent;
6890 pathtbl->last = &(ent->ptnext);
6894 static inline struct isoent *
6895 path_table_last_entry(struct path_table *pathtbl)
6897 if (pathtbl->first == NULL)
6899 return (((struct isoent *)(void *)
6900 ((char *)(pathtbl->last) - offsetof(struct isoent, ptnext))));
6904 * Sort directory entries in path_table
6905 * and assign directory number to each entries.
6908 isoent_make_path_table_2(struct archive_write *a, struct vdd *vdd,
6909 int depth, int *dir_number)
6912 struct isoent **enttbl;
6913 struct path_table *pt;
6916 pt = &vdd->pathtbl[depth];
6919 return (ARCHIVE_OK);
6921 enttbl = malloc(pt->cnt * sizeof(struct isoent *));
6922 if (enttbl == NULL) {
6923 archive_set_error(&a->archive, ENOMEM,
6924 "Can't allocate memory");
6925 return (ARCHIVE_FATAL);
6927 pt->sorted = enttbl;
6928 for (np = pt->first; np != NULL; np = np->ptnext)
6930 enttbl = pt->sorted;
6932 switch (vdd->vdd_type) {
6935 #ifdef __COMPAR_FN_T
6936 qsort(enttbl, pt->cnt, sizeof(struct isoent *),
6937 (__compar_fn_t)_compare_path_table);
6939 qsort(enttbl, pt->cnt, sizeof(struct isoent *),
6940 _compare_path_table);
6944 #ifdef __COMPAR_FN_T
6945 qsort(enttbl, pt->cnt, sizeof(struct isoent *),
6946 (__compar_fn_t)_compare_path_table_joliet);
6948 qsort(enttbl, pt->cnt, sizeof(struct isoent *),
6949 _compare_path_table_joliet);
6953 for (i = 0; i < pt->cnt; i++)
6954 enttbl[i]->dir_number = (*dir_number)++;
6956 return (ARCHIVE_OK);
6960 isoent_alloc_path_table(struct archive_write *a, struct vdd *vdd,
6965 vdd->max_depth = max_depth;
6966 vdd->pathtbl = malloc(sizeof(*vdd->pathtbl) * vdd->max_depth);
6967 if (vdd->pathtbl == NULL) {
6968 archive_set_error(&a->archive, ENOMEM,
6969 "Can't allocate memory");
6970 return (ARCHIVE_FATAL);
6972 for (i = 0; i < vdd->max_depth; i++) {
6973 vdd->pathtbl[i].first = NULL;
6974 vdd->pathtbl[i].last = &(vdd->pathtbl[i].first);
6975 vdd->pathtbl[i].sorted = NULL;
6976 vdd->pathtbl[i].cnt = 0;
6978 return (ARCHIVE_OK);
6985 isoent_make_path_table(struct archive_write *a)
6987 struct iso9660 *iso9660 = a->format_data;
6994 if (iso9660->dircnt_max >= MAX_DEPTH &&
6995 (!iso9660->opt.limit_depth || iso9660->opt.iso_level == 4))
6996 r = isoent_alloc_path_table(a, &(iso9660->primary),
6997 iso9660->dircnt_max + 1);
6999 /* The number of levels in the hierarchy cannot exceed
7001 r = isoent_alloc_path_table(a, &(iso9660->primary),
7005 if (iso9660->opt.joliet) {
7006 r = isoent_alloc_path_table(a, &(iso9660->joliet),
7007 iso9660->dircnt_max + 1);
7013 * - Collect directories for primary and joliet.
7015 isoent_collect_dirs(&(iso9660->primary), NULL, 0);
7016 if (iso9660->opt.joliet)
7017 isoent_collect_dirs(&(iso9660->joliet), NULL, 0);
7019 * Rockridge; move deeper depth directories to rr_moved.
7021 if (iso9660->opt.rr) {
7022 r = isoent_rr_move(a);
7028 isofile_connect_hardlink_files(iso9660);
7031 * - Renew a value of the depth of that directories.
7032 * - Resolve hardlinks.
7033 * - Convert pathnames to ISO9660 name or UCS2(joliet).
7034 * - Sort files by each directory.
7036 r = isoent_traverse_tree(a, &(iso9660->primary));
7039 if (iso9660->opt.joliet) {
7040 r = isoent_traverse_tree(a, &(iso9660->joliet));
7046 * - Sort directories.
7047 * - Assign all directory number.
7050 for (depth = 0; depth < iso9660->primary.max_depth; depth++) {
7051 r = isoent_make_path_table_2(a, &(iso9660->primary),
7052 depth, &dir_number);
7056 if (iso9660->opt.joliet) {
7058 for (depth = 0; depth < iso9660->joliet.max_depth; depth++) {
7059 r = isoent_make_path_table_2(a, &(iso9660->joliet),
7060 depth, &dir_number);
7065 if (iso9660->opt.limit_dirs && dir_number > 0xffff) {
7067 * Maximum number of directories is 65535(0xffff)
7068 * doe to size(16bit) of Parent Directory Number of
7070 * See also ISO9660 Standard 9.4.
7072 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7073 "Too many directories(%d) over 65535.", dir_number);
7074 return (ARCHIVE_FATAL);
7077 /* Get the size of the Path Table. */
7078 calculate_path_table_size(&(iso9660->primary));
7079 if (iso9660->opt.joliet)
7080 calculate_path_table_size(&(iso9660->joliet));
7082 return (ARCHIVE_OK);
7086 isoent_find_out_boot_file(struct archive_write *a, struct isoent *rootent)
7088 struct iso9660 *iso9660 = a->format_data;
7090 /* Find a isoent of the boot file. */
7091 iso9660->el_torito.boot = isoent_find_entry(rootent,
7092 iso9660->el_torito.boot_filename.s);
7093 if (iso9660->el_torito.boot == NULL) {
7094 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7095 "Can't find the boot image file ``%s''",
7096 iso9660->el_torito.boot_filename.s);
7097 return (ARCHIVE_FATAL);
7099 iso9660->el_torito.boot->file->boot = BOOT_IMAGE;
7100 return (ARCHIVE_OK);
7104 isoent_create_boot_catalog(struct archive_write *a, struct isoent *rootent)
7106 struct iso9660 *iso9660 = a->format_data;
7107 struct isofile *file;
7108 struct isoent *isoent;
7109 struct archive_entry *entry;
7111 (void)rootent; /* UNUSED */
7113 * Create the entry which is the "boot.catalog" file.
7115 file = isofile_new(a, NULL);
7117 archive_set_error(&a->archive, ENOMEM,
7118 "Can't allocate memory");
7119 return (ARCHIVE_FATAL);
7121 archive_entry_set_pathname(file->entry,
7122 iso9660->el_torito.catalog_filename.s);
7123 archive_entry_set_size(file->entry, LOGICAL_BLOCK_SIZE);
7124 archive_entry_set_mtime(file->entry, iso9660->birth_time, 0);
7125 archive_entry_set_atime(file->entry, iso9660->birth_time, 0);
7126 archive_entry_set_ctime(file->entry, iso9660->birth_time, 0);
7127 archive_entry_set_uid(file->entry, getuid());
7128 archive_entry_set_gid(file->entry, getgid());
7129 archive_entry_set_mode(file->entry, AE_IFREG | 0444);
7130 archive_entry_set_nlink(file->entry, 1);
7132 if (isofile_gen_utility_names(a, file) < ARCHIVE_WARN) {
7134 return (ARCHIVE_FATAL);
7136 file->boot = BOOT_CATALOG;
7137 file->content.size = LOGICAL_BLOCK_SIZE;
7138 isofile_add_entry(iso9660, file);
7140 isoent = isoent_new(file);
7141 if (isoent == NULL) {
7142 archive_set_error(&a->archive, ENOMEM,
7143 "Can't allocate memory");
7144 return (ARCHIVE_FATAL);
7146 isoent->virtual = 1;
7148 /* Add the "boot.catalog" entry into tree */
7149 if (isoent_tree(a, &isoent) != ARCHIVE_OK)
7150 return (ARCHIVE_FATAL);
7152 iso9660->el_torito.catalog = isoent;
7154 * Get a boot media type.
7156 switch (iso9660->opt.boot_type) {
7158 case OPT_BOOT_TYPE_AUTO:
7159 /* Try detecting a media type of the boot image. */
7160 entry = iso9660->el_torito.boot->file->entry;
7161 if (archive_entry_size(entry) == FD_1_2M_SIZE)
7162 iso9660->el_torito.media_type =
7163 BOOT_MEDIA_1_2M_DISKETTE;
7164 else if (archive_entry_size(entry) == FD_1_44M_SIZE)
7165 iso9660->el_torito.media_type =
7166 BOOT_MEDIA_1_44M_DISKETTE;
7167 else if (archive_entry_size(entry) == FD_2_88M_SIZE)
7168 iso9660->el_torito.media_type =
7169 BOOT_MEDIA_2_88M_DISKETTE;
7171 /* We cannot decide whether the boot image is
7173 iso9660->el_torito.media_type =
7174 BOOT_MEDIA_NO_EMULATION;
7176 case OPT_BOOT_TYPE_NO_EMU:
7177 iso9660->el_torito.media_type = BOOT_MEDIA_NO_EMULATION;
7179 case OPT_BOOT_TYPE_HARD_DISK:
7180 iso9660->el_torito.media_type = BOOT_MEDIA_HARD_DISK;
7182 case OPT_BOOT_TYPE_FD:
7183 entry = iso9660->el_torito.boot->file->entry;
7184 if (archive_entry_size(entry) <= FD_1_2M_SIZE)
7185 iso9660->el_torito.media_type =
7186 BOOT_MEDIA_1_2M_DISKETTE;
7187 else if (archive_entry_size(entry) <= FD_1_44M_SIZE)
7188 iso9660->el_torito.media_type =
7189 BOOT_MEDIA_1_44M_DISKETTE;
7190 else if (archive_entry_size(entry) <= FD_2_88M_SIZE)
7191 iso9660->el_torito.media_type =
7192 BOOT_MEDIA_2_88M_DISKETTE;
7194 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7195 "Boot image file(``%s'') size is too big "
7197 iso9660->el_torito.boot_filename.s);
7198 return (ARCHIVE_FATAL);
7204 * Get a system type.
7205 * TODO: `El Torito' specification says "A copy of byte 5 from the
7206 * Partition Table found in the boot image".
7208 iso9660->el_torito.system_type = 0;
7213 if (iso9660->opt.publisher)
7214 archive_string_copy(&(iso9660->el_torito.id),
7215 &(iso9660->publisher_identifier));
7218 return (ARCHIVE_OK);
7222 * If a media type is floppy, return its image size.
7223 * otherwise return 0.
7226 fd_boot_image_size(int media_type)
7228 switch (media_type) {
7229 case BOOT_MEDIA_1_2M_DISKETTE:
7230 return (FD_1_2M_SIZE);
7231 case BOOT_MEDIA_1_44M_DISKETTE:
7232 return (FD_1_44M_SIZE);
7233 case BOOT_MEDIA_2_88M_DISKETTE:
7234 return (FD_2_88M_SIZE);
7241 * Make a boot catalog image data.
7244 make_boot_catalog(struct archive_write *a)
7246 struct iso9660 *iso9660 = a->format_data;
7247 unsigned char *block;
7251 block = wb_buffptr(a);
7252 memset(block, 0, LOGICAL_BLOCK_SIZE);
7260 p[1] = iso9660->el_torito.platform_id;
7264 if (archive_strlen(&(iso9660->el_torito.id)) > 0)
7265 strncpy((char *)p+4, iso9660->el_torito.id.s, 23);
7274 wp = (uint16_t *)block;
7275 while (wp < (uint16_t *)&block[32])
7276 sum += archive_le16dec(wp++);
7277 set_num_721(&block[28], (~sum) + 1);
7280 * Initial/Default Entry
7283 /* Boot Indicator */
7285 /* Boot media type */
7286 p[1] = iso9660->el_torito.media_type;
7288 if (iso9660->el_torito.media_type == BOOT_MEDIA_NO_EMULATION)
7289 set_num_721(&p[2], iso9660->el_torito.boot_load_seg);
7291 set_num_721(&p[2], 0);
7293 p[4] = iso9660->el_torito.system_type;
7297 if (iso9660->el_torito.media_type == BOOT_MEDIA_NO_EMULATION)
7298 set_num_721(&p[6], iso9660->el_torito.boot_load_size);
7300 set_num_721(&p[6], 1);
7303 iso9660->el_torito.boot->file->content.location);
7305 memset(&p[12], 0, 20);
7307 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
7311 setup_boot_information(struct archive_write *a)
7313 struct iso9660 *iso9660 = a->format_data;
7317 unsigned char buff[4096];
7319 np = iso9660->el_torito.boot;
7320 lseek(iso9660->temp_fd,
7321 np->file->content.offset_of_temp + 64, SEEK_SET);
7322 size = archive_entry_size(np->file->entry) - 64;
7324 archive_set_error(&a->archive, errno,
7325 "Boot file(%jd) is too small", (intmax_t)size + 64);
7326 return (ARCHIVE_FATAL);
7333 if (size > (int64_t)sizeof(buff))
7334 rsize = sizeof(buff);
7336 rsize = (size_t)size;
7338 rs = read(iso9660->temp_fd, buff, rsize);
7340 archive_set_error(&a->archive, errno,
7341 "Can't read temporary file(%jd)",
7343 return (ARCHIVE_FATAL);
7345 for (i = 0; i < rs; i += 4)
7346 sum += archive_le32dec(buff + i);
7349 /* Set the location of Primary Volume Descriptor. */
7350 set_num_731(buff, SYSTEM_AREA_BLOCK);
7351 /* Set the location of the boot file. */
7352 set_num_731(buff+4, np->file->content.location);
7353 /* Set the size of the boot file. */
7354 size = fd_boot_image_size(iso9660->el_torito.media_type);
7356 size = archive_entry_size(np->file->entry);
7357 set_num_731(buff+8, (uint32_t)size);
7358 /* Set the sum of the boot file. */
7359 set_num_731(buff+12, sum);
7360 /* Clear reserved bytes. */
7361 memset(buff+16, 0, 40);
7363 /* Overwrite the boot file. */
7364 lseek(iso9660->temp_fd,
7365 np->file->content.offset_of_temp + 8, SEEK_SET);
7366 return (write_to_temp(a, buff, 56));
7372 zisofs_init_zstream(struct archive_write *a)
7374 struct iso9660 *iso9660 = a->format_data;
7377 iso9660->zisofs.stream.next_in = NULL;
7378 iso9660->zisofs.stream.avail_in = 0;
7379 iso9660->zisofs.stream.total_in = 0;
7380 iso9660->zisofs.stream.total_out = 0;
7381 if (iso9660->zisofs.stream_valid)
7382 r = deflateReset(&(iso9660->zisofs.stream));
7384 r = deflateInit(&(iso9660->zisofs.stream),
7385 iso9660->zisofs.compression_level);
7386 iso9660->zisofs.stream_valid = 1;
7392 case Z_STREAM_ERROR:
7393 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7394 "Internal error initializing "
7395 "compression library: invalid setup parameter");
7396 return (ARCHIVE_FATAL);
7398 archive_set_error(&a->archive, ENOMEM,
7399 "Internal error initializing "
7400 "compression library");
7401 return (ARCHIVE_FATAL);
7402 case Z_VERSION_ERROR:
7403 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7404 "Internal error initializing "
7405 "compression library: invalid library version");
7406 return (ARCHIVE_FATAL);
7408 return (ARCHIVE_OK);
7411 #endif /* HAVE_ZLIB_H */
7414 zisofs_init(struct archive_write *a, struct isofile *file)
7416 struct iso9660 *iso9660 = a->format_data;
7419 size_t _ceil, bpsize;
7423 iso9660->zisofs.detect_magic = 0;
7424 iso9660->zisofs.making = 0;
7426 if (!iso9660->opt.rr || !iso9660->opt.zisofs)
7427 return (ARCHIVE_OK);
7429 if (archive_entry_size(file->entry) >= 24 &&
7430 archive_entry_size(file->entry) < MULTI_EXTENT_SIZE) {
7431 /* Acceptable file size for zisofs. */
7432 iso9660->zisofs.detect_magic = 1;
7433 iso9660->zisofs.magic_cnt = 0;
7435 if (!iso9660->zisofs.detect_magic)
7436 return (ARCHIVE_OK);
7439 /* The number of Logical Blocks which uncompressed data
7440 * will use in iso-image file is the same as the number of
7441 * Logical Blocks which zisofs(compressed) data will use
7442 * in ISO-image file. It won't reduce iso-image file size. */
7443 if (archive_entry_size(file->entry) <= LOGICAL_BLOCK_SIZE)
7444 return (ARCHIVE_OK);
7446 /* Initialize compression library */
7447 r = zisofs_init_zstream(a);
7448 if (r != ARCHIVE_OK)
7449 return (ARCHIVE_FATAL);
7451 /* Mark file->zisofs to create RRIP 'ZF' Use Entry. */
7452 file->zisofs.header_size = ZF_HEADER_SIZE >> 2;
7453 file->zisofs.log2_bs = ZF_LOG2_BS;
7454 file->zisofs.uncompressed_size =
7455 (uint32_t)archive_entry_size(file->entry);
7457 /* Calculate a size of Block Pointers of zisofs. */
7458 _ceil = (file->zisofs.uncompressed_size + ZF_BLOCK_SIZE -1)
7459 >> file->zisofs.log2_bs;
7460 iso9660->zisofs.block_pointers_cnt = (int)_ceil + 1;
7461 iso9660->zisofs.block_pointers_idx = 0;
7463 /* Ensure a buffer size used for Block Pointers */
7464 bpsize = iso9660->zisofs.block_pointers_cnt *
7465 sizeof(iso9660->zisofs.block_pointers[0]);
7466 if (iso9660->zisofs.block_pointers_allocated < bpsize) {
7467 free(iso9660->zisofs.block_pointers);
7468 iso9660->zisofs.block_pointers = malloc(bpsize);
7469 if (iso9660->zisofs.block_pointers == NULL) {
7470 archive_set_error(&a->archive, ENOMEM,
7471 "Can't allocate data");
7472 return (ARCHIVE_FATAL);
7474 iso9660->zisofs.block_pointers_allocated = bpsize;
7478 * Skip zisofs header and Block Pointers, which we will write
7479 * after all compressed data of a file written to the temporary
7482 tsize = ZF_HEADER_SIZE + bpsize;
7483 if (write_null(a, (size_t)tsize) != ARCHIVE_OK)
7484 return (ARCHIVE_FATAL);
7487 * Initialize some variables to make zisofs.
7489 archive_le32enc(&(iso9660->zisofs.block_pointers[0]),
7491 iso9660->zisofs.remaining = file->zisofs.uncompressed_size;
7492 iso9660->zisofs.making = 1;
7493 iso9660->zisofs.allzero = 1;
7494 iso9660->zisofs.block_offset = tsize;
7495 iso9660->zisofs.total_size = tsize;
7496 iso9660->cur_file->cur_content->size = tsize;
7499 return (ARCHIVE_OK);
7503 zisofs_detect_magic(struct archive_write *a, const void *buff, size_t s)
7505 struct iso9660 *iso9660 = a->format_data;
7506 struct isofile *file = iso9660->cur_file;
7507 const unsigned char *p, *endp;
7508 const unsigned char *magic_buff;
7509 uint32_t uncompressed_size;
7510 unsigned char header_size;
7511 unsigned char log2_bs;
7517 entry_size = archive_entry_size(file->entry);
7518 if ((int64_t)sizeof(iso9660->zisofs.magic_buffer) > entry_size)
7519 magic_max = (int)entry_size;
7521 magic_max = sizeof(iso9660->zisofs.magic_buffer);
7523 if (iso9660->zisofs.magic_cnt == 0 && s >= (size_t)magic_max)
7524 /* It's unnecessary we copy buffer. */
7527 if (iso9660->zisofs.magic_cnt < magic_max) {
7530 l = sizeof(iso9660->zisofs.magic_buffer)
7531 - iso9660->zisofs.magic_cnt;
7534 memcpy(iso9660->zisofs.magic_buffer
7535 + iso9660->zisofs.magic_cnt, buff, l);
7536 iso9660->zisofs.magic_cnt += (int)l;
7537 if (iso9660->zisofs.magic_cnt < magic_max)
7540 magic_buff = iso9660->zisofs.magic_buffer;
7542 iso9660->zisofs.detect_magic = 0;
7545 /* Check the magic code of zisofs. */
7546 if (memcmp(p, zisofs_magic, sizeof(zisofs_magic)) != 0)
7547 /* This is not zisofs file which made by mkzftree. */
7549 p += sizeof(zisofs_magic);
7551 /* Read a zisofs header. */
7552 uncompressed_size = archive_le32dec(p);
7555 if (uncompressed_size < 24 || header_size != 4 ||
7556 log2_bs > 30 || log2_bs < 7)
7557 return;/* Invalid or not supported header. */
7559 /* Calculate a size of Block Pointers of zisofs. */
7560 _ceil = (uncompressed_size +
7561 (ARCHIVE_LITERAL_LL(1) << log2_bs) -1) >> log2_bs;
7562 doff = (_ceil + 1) * 4 + 16;
7563 if (entry_size < (int64_t)doff)
7564 return;/* Invalid data. */
7566 /* Check every Block Pointer has valid value. */
7567 p = magic_buff + 16;
7568 endp = magic_buff + magic_max;
7569 while (_ceil && p + 8 <= endp) {
7570 bst = archive_le32dec(p);
7572 return;/* Invalid data. */
7574 bed = archive_le32dec(p);
7575 if (bed < bst || bed > entry_size)
7576 return;/* Invalid data. */
7581 file->zisofs.uncompressed_size = uncompressed_size;
7582 file->zisofs.header_size = header_size;
7583 file->zisofs.log2_bs = log2_bs;
7585 /* Disable making a zisofs image. */
7586 iso9660->zisofs.making = 0;
7592 * Compress data and write it to a temporary file.
7595 zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s)
7597 struct iso9660 *iso9660 = a->format_data;
7598 struct isofile *file = iso9660->cur_file;
7599 const unsigned char *b;
7601 size_t avail, csize;
7604 zstrm = &(iso9660->zisofs.stream);
7605 zstrm->next_out = wb_buffptr(a);
7606 zstrm->avail_out = (uInt)wb_remaining(a);
7607 b = (const unsigned char *)buff;
7609 avail = ZF_BLOCK_SIZE - zstrm->total_in;
7615 iso9660->zisofs.remaining -= avail;
7616 if (iso9660->zisofs.remaining <= 0)
7619 zstrm->next_in = (Bytef *)(uintptr_t)(const void *)b;
7620 zstrm->avail_in = (uInt)avail;
7623 * Check if current data block are all zero.
7625 if (iso9660->zisofs.allzero) {
7626 const unsigned char *nonzero = b;
7627 const unsigned char *nonzeroend = b + avail;
7629 while (nonzero < nonzeroend)
7631 iso9660->zisofs.allzero = 0;
7639 * If current data block are all zero, we do not use
7642 if (flush == Z_FINISH && iso9660->zisofs.allzero &&
7643 avail + zstrm->total_in == ZF_BLOCK_SIZE) {
7644 if (iso9660->zisofs.block_offset !=
7645 file->cur_content->size) {
7648 r = wb_set_offset(a,
7649 file->cur_content->offset_of_temp +
7650 iso9660->zisofs.block_offset);
7651 if (r != ARCHIVE_OK)
7653 diff = file->cur_content->size -
7654 iso9660->zisofs.block_offset;
7655 file->cur_content->size -= diff;
7656 iso9660->zisofs.total_size -= diff;
7658 zstrm->avail_in = 0;
7662 * Compress file data.
7664 while (zstrm->avail_in > 0) {
7665 csize = zstrm->total_out;
7666 r = deflate(zstrm, flush);
7670 csize = zstrm->total_out - csize;
7671 if (wb_consume(a, csize) != ARCHIVE_OK)
7672 return (ARCHIVE_FATAL);
7673 iso9660->zisofs.total_size += csize;
7674 iso9660->cur_file->cur_content->size += csize;
7675 zstrm->next_out = wb_buffptr(a);
7676 zstrm->avail_out = (uInt)wb_remaining(a);
7679 archive_set_error(&a->archive,
7681 "Compression failed:"
7682 " deflate() call returned status %d",
7684 return (ARCHIVE_FATAL);
7688 if (flush == Z_FINISH) {
7690 * Save the information of one zisofs block.
7692 iso9660->zisofs.block_pointers_idx ++;
7693 archive_le32enc(&(iso9660->zisofs.block_pointers[
7694 iso9660->zisofs.block_pointers_idx]),
7695 (uint32_t)iso9660->zisofs.total_size);
7696 r = zisofs_init_zstream(a);
7697 if (r != ARCHIVE_OK)
7698 return (ARCHIVE_FATAL);
7699 iso9660->zisofs.allzero = 1;
7700 iso9660->zisofs.block_offset = file->cur_content->size;
7704 return (ARCHIVE_OK);
7708 zisofs_finish_entry(struct archive_write *a)
7710 struct iso9660 *iso9660 = a->format_data;
7711 struct isofile *file = iso9660->cur_file;
7712 unsigned char buff[16];
7716 /* Direct temp file stream to zisofs temp file stream. */
7717 archive_entry_set_size(file->entry, iso9660->zisofs.total_size);
7720 * Save a file pointer which points the end of current zisofs data.
7722 tail = wb_offset(a);
7727 * +-----------------+----------------+-----------------+
7728 * | Header 16 bytes | Block Pointers | Compressed data |
7729 * +-----------------+----------------+-----------------+
7732 * 4 * (((Uncompressed file size + block_size -1) / block_size) + 1)
7734 * Write zisofs header.
7736 * +----+----+----+----+----+----+----+----+
7737 * | 37 | E4 | 53 | 96 | C9 | DB | D6 | 07 |
7738 * +----+----+----+----+----+----+----+----+
7741 * +------------------------+------------------+
7742 * | Uncompressed file size | header_size >> 2 |
7743 * +------------------------+------------------+
7746 * +-----------------+----------------+
7747 * | log2 block_size | Reserved(0000) |
7748 * +-----------------+----------------+
7751 memcpy(buff, zisofs_magic, 8);
7752 set_num_731(buff+8, file->zisofs.uncompressed_size);
7753 buff[12] = file->zisofs.header_size;
7754 buff[13] = file->zisofs.log2_bs;
7755 buff[14] = buff[15] = 0;/* Reserved */
7757 /* Move to the right position to write the header. */
7758 wb_set_offset(a, file->content.offset_of_temp);
7760 /* Write the header. */
7761 if (wb_write_to_temp(a, buff, 16) != ARCHIVE_OK)
7762 return (ARCHIVE_FATAL);
7765 * Write zisofs Block Pointers.
7767 s = iso9660->zisofs.block_pointers_cnt *
7768 sizeof(iso9660->zisofs.block_pointers[0]);
7769 if (wb_write_to_temp(a, iso9660->zisofs.block_pointers, s)
7771 return (ARCHIVE_FATAL);
7773 /* Set a file pointer back to the end of the temporary file. */
7774 wb_set_offset(a, tail);
7776 return (ARCHIVE_OK);
7780 zisofs_free(struct archive_write *a)
7782 struct iso9660 *iso9660 = a->format_data;
7783 int ret = ARCHIVE_OK;
7785 free(iso9660->zisofs.block_pointers);
7786 if (iso9660->zisofs.stream_valid &&
7787 deflateEnd(&(iso9660->zisofs.stream)) != Z_OK) {
7788 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7789 "Failed to clean up compressor");
7790 ret = ARCHIVE_FATAL;
7792 iso9660->zisofs.block_pointers = NULL;
7793 iso9660->zisofs.stream_valid = 0;
7797 struct zisofs_extract {
7798 int pz_log2_bs; /* Log2 of block size */
7799 uint64_t pz_uncompressed_size;
7800 size_t uncompressed_buffer_size;
7802 signed int initialized:1;
7803 signed int header_passed:1;
7806 unsigned char *block_pointers;
7807 size_t block_pointers_size;
7808 size_t block_pointers_avail;
7810 uint32_t block_avail;
7817 zisofs_extract_init(struct archive_write *a, struct zisofs_extract *zisofs,
7818 const unsigned char *p, size_t bytes)
7820 size_t avail = bytes;
7821 size_t _ceil, xsize;
7823 /* Allocate block pointers buffer. */
7824 _ceil = (size_t)((zisofs->pz_uncompressed_size +
7825 (((int64_t)1) << zisofs->pz_log2_bs) - 1)
7826 >> zisofs->pz_log2_bs);
7827 xsize = (_ceil + 1) * 4;
7828 if (zisofs->block_pointers == NULL) {
7829 size_t alloc = ((xsize >> 10) + 1) << 10;
7830 zisofs->block_pointers = malloc(alloc);
7831 if (zisofs->block_pointers == NULL) {
7832 archive_set_error(&a->archive, ENOMEM,
7833 "No memory for zisofs decompression");
7834 return (ARCHIVE_FATAL);
7837 zisofs->block_pointers_size = xsize;
7839 /* Allocate uncompressed data buffer. */
7840 zisofs->uncompressed_buffer_size = (size_t)1UL << zisofs->pz_log2_bs;
7843 * Read the file header, and check the magic code of zisofs.
7845 if (!zisofs->header_passed) {
7848 archive_set_error(&a->archive,
7849 ARCHIVE_ERRNO_FILE_FORMAT,
7850 "Illegal zisofs file body");
7851 return (ARCHIVE_FATAL);
7854 if (memcmp(p, zisofs_magic, sizeof(zisofs_magic)) != 0)
7856 else if (archive_le32dec(p + 8) != zisofs->pz_uncompressed_size)
7858 else if (p[12] != 4 || p[13] != zisofs->pz_log2_bs)
7861 archive_set_error(&a->archive,
7862 ARCHIVE_ERRNO_FILE_FORMAT,
7863 "Illegal zisofs file body");
7864 return (ARCHIVE_FATAL);
7868 zisofs->header_passed = 1;
7872 * Read block pointers.
7874 if (zisofs->header_passed &&
7875 zisofs->block_pointers_avail < zisofs->block_pointers_size) {
7876 xsize = zisofs->block_pointers_size
7877 - zisofs->block_pointers_avail;
7880 memcpy(zisofs->block_pointers
7881 + zisofs->block_pointers_avail, p, xsize);
7882 zisofs->block_pointers_avail += xsize;
7884 if (zisofs->block_pointers_avail
7885 == zisofs->block_pointers_size) {
7886 /* We've got all block pointers and initialize
7887 * related variables. */
7888 zisofs->block_off = 0;
7889 zisofs->block_avail = 0;
7890 /* Complete a initialization */
7891 zisofs->initialized = 1;
7894 return ((ssize_t)avail);
7898 zisofs_extract(struct archive_write *a, struct zisofs_extract *zisofs,
7899 const unsigned char *p, size_t bytes)
7904 if (!zisofs->initialized) {
7905 ssize_t rs = zisofs_extract_init(a, zisofs, p, bytes);
7908 if (!zisofs->initialized) {
7909 /* We need more data. */
7910 zisofs->pz_offset += (uint32_t)bytes;
7919 * Get block offsets from block pointers.
7921 if (zisofs->block_avail == 0) {
7924 if (zisofs->block_off + 4 >= zisofs->block_pointers_size) {
7925 /* There isn't a pair of offsets. */
7926 archive_set_error(&a->archive,
7927 ARCHIVE_ERRNO_FILE_FORMAT,
7928 "Illegal zisofs block pointers");
7929 return (ARCHIVE_FATAL);
7931 bst = archive_le32dec(
7932 zisofs->block_pointers + zisofs->block_off);
7933 if (bst != zisofs->pz_offset + (bytes - avail)) {
7934 archive_set_error(&a->archive,
7935 ARCHIVE_ERRNO_FILE_FORMAT,
7936 "Illegal zisofs block pointers(cannot seek)");
7937 return (ARCHIVE_FATAL);
7939 bed = archive_le32dec(
7940 zisofs->block_pointers + zisofs->block_off + 4);
7942 archive_set_error(&a->archive,
7943 ARCHIVE_ERRNO_FILE_FORMAT,
7944 "Illegal zisofs block pointers");
7945 return (ARCHIVE_FATAL);
7947 zisofs->block_avail = bed - bst;
7948 zisofs->block_off += 4;
7950 /* Initialize compression library for new block. */
7951 if (zisofs->stream_valid)
7952 r = inflateReset(&zisofs->stream);
7954 r = inflateInit(&zisofs->stream);
7956 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7957 "Can't initialize zisofs decompression.");
7958 return (ARCHIVE_FATAL);
7960 zisofs->stream_valid = 1;
7961 zisofs->stream.total_in = 0;
7962 zisofs->stream.total_out = 0;
7966 * Make uncompressed data.
7968 if (zisofs->block_avail == 0) {
7970 * It's basically 32K bytes NUL data.
7975 size = zisofs->uncompressed_buffer_size;
7978 if (size > wb_remaining(a))
7979 wsize = wb_remaining(a);
7982 memset(wb, 0, wsize);
7983 r = wb_consume(a, wsize);
7989 zisofs->stream.next_in = (Bytef *)(uintptr_t)(const void *)p;
7990 if (avail > zisofs->block_avail)
7991 zisofs->stream.avail_in = zisofs->block_avail;
7993 zisofs->stream.avail_in = (uInt)avail;
7994 zisofs->stream.next_out = wb_buffptr(a);
7995 zisofs->stream.avail_out = (uInt)wb_remaining(a);
7997 r = inflate(&zisofs->stream, 0);
7999 case Z_OK: /* Decompressor made some progress.*/
8000 case Z_STREAM_END: /* Found end of stream. */
8003 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
8004 "zisofs decompression failed (%d)", r);
8005 return (ARCHIVE_FATAL);
8007 avail -= zisofs->stream.next_in - p;
8008 zisofs->block_avail -= (uint32_t)(zisofs->stream.next_in - p);
8009 r = wb_consume(a, wb_remaining(a) - zisofs->stream.avail_out);
8013 zisofs->pz_offset += (uint32_t)bytes;
8014 return (bytes - avail);
8018 zisofs_rewind_boot_file(struct archive_write *a)
8020 struct iso9660 *iso9660 = a->format_data;
8021 struct isofile *file;
8022 unsigned char *rbuff;
8024 size_t remaining, rbuff_size;
8025 struct zisofs_extract zext;
8026 int64_t read_offset, write_offset, new_offset;
8027 int fd, ret = ARCHIVE_OK;
8029 file = iso9660->el_torito.boot->file;
8031 * There is nothing to do if this boot file does not have
8034 if (file->zisofs.header_size == 0)
8035 return (ARCHIVE_OK);
8038 * Uncompress the zisofs'ed file contents.
8040 memset(&zext, 0, sizeof(zext));
8041 zext.pz_uncompressed_size = file->zisofs.uncompressed_size;
8042 zext.pz_log2_bs = file->zisofs.log2_bs;
8044 fd = iso9660->temp_fd;
8045 new_offset = wb_offset(a);
8046 read_offset = file->content.offset_of_temp;
8047 remaining = (size_t)file->content.size;
8048 if (remaining > 1024 * 32)
8049 rbuff_size = 1024 * 32;
8051 rbuff_size = remaining;
8053 rbuff = malloc(rbuff_size);
8054 if (rbuff == NULL) {
8055 archive_set_error(&a->archive, ENOMEM, "Can't allocate memory");
8056 return (ARCHIVE_FATAL);
8062 /* Get the current file pointer. */
8063 write_offset = lseek(fd, 0, SEEK_CUR);
8065 /* Change the file pointer to read. */
8066 lseek(fd, read_offset, SEEK_SET);
8069 if (rsize > remaining)
8071 rs = read(iso9660->temp_fd, rbuff, rsize);
8073 archive_set_error(&a->archive, errno,
8074 "Can't read temporary file(%jd)", (intmax_t)rs);
8075 ret = ARCHIVE_FATAL;
8081 /* Put the file pointer back to write. */
8082 lseek(fd, write_offset, SEEK_SET);
8084 r = zisofs_extract(a, &zext, rbuff, rs);
8091 if (ret == ARCHIVE_OK) {
8093 * Change the boot file content from zisofs'ed data
8096 file->content.offset_of_temp = new_offset;
8097 file->content.size = file->zisofs.uncompressed_size;
8098 archive_entry_set_size(file->entry, file->content.size);
8099 /* Set to be no zisofs. */
8100 file->zisofs.header_size = 0;
8101 file->zisofs.log2_bs = 0;
8102 file->zisofs.uncompressed_size = 0;
8103 r = wb_write_padding_to_temp(a, file->content.size);
8105 ret = ARCHIVE_FATAL;
8109 * Free the resource we used in this function only.
8112 free(zext.block_pointers);
8113 if (zext.stream_valid && inflateEnd(&(zext.stream)) != Z_OK) {
8114 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
8115 "Failed to clean up compressor");
8116 ret = ARCHIVE_FATAL;
8125 zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s)
8127 (void)buff; /* UNUSED */
8128 (void)s; /* UNUSED */
8129 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Programming error");
8130 return (ARCHIVE_FATAL);
8134 zisofs_rewind_boot_file(struct archive_write *a)
8136 struct iso9660 *iso9660 = a->format_data;
8138 if (iso9660->el_torito.boot->file->zisofs.header_size != 0) {
8139 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
8140 "We cannot extract the zisofs imaged boot file;"
8141 " this may not boot in being zisofs imaged");
8142 return (ARCHIVE_FAILED);
8144 return (ARCHIVE_OK);
8148 zisofs_finish_entry(struct archive_write *a)
8150 (void)a; /* UNUSED */
8151 return (ARCHIVE_OK);
8155 zisofs_free(struct archive_write *a)
8157 (void)a; /* UNUSED */
8158 return (ARCHIVE_OK);
8161 #endif /* HAVE_ZLIB_H */