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 strncpy(system_id, "Unknown", size-1);
2182 system_id[size-1] = '\0';
2187 set_str(unsigned char *p, const char *s, size_t l, char f, const char *map)
2193 while ((c = *s++) != 0 && l > 0) {
2194 if (c >= 0x80 || map[c] == 0)
2196 /* illegal character */
2197 if (c >= 'a' && c <= 'z') {
2198 /* convert c from a-z to A-Z */
2206 /* If l isn't zero, fill p buffer by the character
2207 * which indicated by f. */
2213 joliet_allowed_char(unsigned char high, unsigned char low)
2215 int utf16 = (high << 8) | low;
2217 if (utf16 <= 0x001F)
2221 case 0x002A: /* '*' */
2222 case 0x002F: /* '/' */
2223 case 0x003A: /* ':' */
2224 case 0x003B: /* ';' */
2225 case 0x003F: /* '?' */
2226 case 0x005C: /* '\' */
2227 return (0);/* Not allowed. */
2233 set_str_utf16be(struct archive_write *a, unsigned char *p, const char *s,
2234 size_t l, uint16_t uf, enum vdc vdc)
2246 if (vdc == VDC_UCS2) {
2247 struct iso9660 *iso9660 = a->format_data;
2248 if (archive_strncpy_l(&iso9660->utf16be, s, strlen(s),
2249 iso9660->sconv_to_utf16be) != 0 && errno == ENOMEM) {
2250 archive_set_error(&a->archive, ENOMEM,
2251 "Can't allocate memory for UTF-16BE");
2252 return (ARCHIVE_FATAL);
2254 size = iso9660->utf16be.length;
2257 memcpy(p, iso9660->utf16be.s, size);
2259 const uint16_t *u16 = (const uint16_t *)s;
2268 for (i = 0; i < size; i += 2, p += 2) {
2269 if (!joliet_allowed_char(p[0], p[1]))
2270 archive_be16enc(p, 0x005F);/* '_' */
2274 archive_be16enc(p, uf);
2280 return (ARCHIVE_OK);
2283 static const char a_characters_map[0x80] = {
2284 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
2285 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
2286 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
2287 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20-2F */
2288 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30-3F */
2289 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
2290 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
2291 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 60-6F */
2292 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 70-7F */
2295 static const char a1_characters_map[0x80] = {
2296 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
2297 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
2298 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
2299 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20-2F */
2300 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30-3F */
2301 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
2302 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
2303 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60-6F */
2304 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,/* 70-7F */
2307 static const char d_characters_map[0x80] = {
2308 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
2309 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
2310 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
2311 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 20-2F */
2312 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,/* 30-3F */
2313 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
2314 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
2315 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 60-6F */
2316 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 70-7F */
2319 static const char d1_characters_map[0x80] = {
2320 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
2321 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
2322 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
2323 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 20-2F */
2324 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,/* 30-3F */
2325 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
2326 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
2327 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60-6F */
2328 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,/* 70-7F */
2332 set_str_a_characters_bp(struct archive_write *a, unsigned char *bp,
2333 int from, int to, const char *s, enum vdc vdc)
2339 set_str(bp+from, s, to - from + 1, 0x20,
2344 set_str(bp+from, s, to - from + 1, 0x20,
2349 case VDC_UCS2_DIRECT:
2350 r = set_str_utf16be(a, bp+from, s, to - from + 1,
2360 set_str_d_characters_bp(struct archive_write *a, unsigned char *bp,
2361 int from, int to, const char *s, enum vdc vdc)
2367 set_str(bp+from, s, to - from + 1, 0x20,
2372 set_str(bp+from, s, to - from + 1, 0x20,
2377 case VDC_UCS2_DIRECT:
2378 r = set_str_utf16be(a, bp+from, s, to - from + 1,
2388 set_VD_bp(unsigned char *bp, enum VD_type type, unsigned char ver)
2391 /* Volume Descriptor Type */
2392 bp[1] = (unsigned char)type;
2393 /* Standard Identifier */
2394 memcpy(bp + 2, "CD001", 5);
2395 /* Volume Descriptor Version */
2400 set_unused_field_bp(unsigned char *bp, int from, int to)
2402 memset(bp + from, 0, to - from + 1);
2406 * 8-bit unsigned numerical values.
2407 * ISO9660 Standard 7.1.1
2410 set_num_711(unsigned char *p, unsigned char value)
2416 * 8-bit signed numerical values.
2417 * ISO9660 Standard 7.1.2
2420 set_num_712(unsigned char *p, char value)
2422 *((char *)p) = value;
2426 * Least significant byte first.
2427 * ISO9660 Standard 7.2.1
2430 set_num_721(unsigned char *p, uint16_t value)
2432 archive_le16enc(p, value);
2436 * Most significant byte first.
2437 * ISO9660 Standard 7.2.2
2440 set_num_722(unsigned char *p, uint16_t value)
2442 archive_be16enc(p, value);
2447 * ISO9660 Standard 7.2.3
2450 set_num_723(unsigned char *p, uint16_t value)
2452 archive_le16enc(p, value);
2453 archive_be16enc(p+2, value);
2457 * Least significant byte first.
2458 * ISO9660 Standard 7.3.1
2461 set_num_731(unsigned char *p, uint32_t value)
2463 archive_le32enc(p, value);
2467 * Most significant byte first.
2468 * ISO9660 Standard 7.3.2
2471 set_num_732(unsigned char *p, uint32_t value)
2473 archive_be32enc(p, value);
2478 * ISO9660 Standard 7.3.3
2481 set_num_733(unsigned char *p, uint32_t value)
2483 archive_le32enc(p, value);
2484 archive_be32enc(p+4, value);
2488 set_digit(unsigned char *p, size_t s, int value)
2492 p[s] = '0' + (value % 10);
2497 #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
2498 #define get_gmoffset(tm) ((tm)->tm_gmtoff)
2499 #elif defined(HAVE_STRUCT_TM___TM_GMTOFF)
2500 #define get_gmoffset(tm) ((tm)->__tm_gmtoff)
2503 get_gmoffset(struct tm *tm)
2507 #if defined(HAVE__GET_TIMEZONE)
2508 _get_timezone(&offset);
2509 #elif defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
2522 get_tmfromtime(struct tm *tm, time_t *t)
2524 #if HAVE_LOCALTIME_R
2527 #elif HAVE__LOCALTIME64_S
2528 __time64_t tmp_t = (__time64_t) *t; //time_t may be shorter than 64 bits
2529 _localtime64_s(tm, &tmp_t);
2531 memcpy(tm, localtime(t), sizeof(*tm));
2536 * Date and Time Format.
2537 * ISO9660 Standard 8.4.26.1
2540 set_date_time(unsigned char *p, time_t t)
2544 get_tmfromtime(&tm, &t);
2545 set_digit(p, 4, tm.tm_year + 1900);
2546 set_digit(p+4, 2, tm.tm_mon + 1);
2547 set_digit(p+6, 2, tm.tm_mday);
2548 set_digit(p+8, 2, tm.tm_hour);
2549 set_digit(p+10, 2, tm.tm_min);
2550 set_digit(p+12, 2, tm.tm_sec);
2551 set_digit(p+14, 2, 0);
2552 set_num_712(p+16, (char)(get_gmoffset(&tm)/(60*15)));
2556 set_date_time_null(unsigned char *p)
2558 memset(p, (int)'0', 16);
2563 set_time_915(unsigned char *p, time_t t)
2567 get_tmfromtime(&tm, &t);
2568 set_num_711(p+0, tm.tm_year);
2569 set_num_711(p+1, tm.tm_mon+1);
2570 set_num_711(p+2, tm.tm_mday);
2571 set_num_711(p+3, tm.tm_hour);
2572 set_num_711(p+4, tm.tm_min);
2573 set_num_711(p+5, tm.tm_sec);
2574 set_num_712(p+6, (char)(get_gmoffset(&tm)/(60*15)));
2579 * Write SUSP "CE" System Use Entry.
2582 set_SUSP_CE(unsigned char *p, int location, int offset, int size)
2584 unsigned char *bp = p -1;
2585 /* Extend the System Use Area
2588 * +----+----+----+----+-----------+-----------+
2589 * | 'C'| 'E'| 1C | 01 | LOCATION1 | LOCATION2 |
2590 * +----+----+----+----+-----------+-----------+
2596 * LOCATION1 : Location of Continuation of System Use Area.
2597 * LOCATION2 : Offset to Start of Continuation.
2598 * LOCATION3 : Length of the Continuation.
2603 bp[3] = RR_CE_SIZE; /* length */
2604 bp[4] = 1; /* version */
2605 set_num_733(bp+5, location);
2606 set_num_733(bp+13, offset);
2607 set_num_733(bp+21, size);
2608 return (RR_CE_SIZE);
2612 * The functions, which names are beginning with extra_, are used to
2613 * control extra records.
2614 * The maximum size of a Directory Record is 254. When a filename is
2615 * very long, all of RRIP data of a file won't stored to the Directory
2616 * Record and so remaining RRIP data store to an extra record instead.
2618 static unsigned char *
2619 extra_open_record(unsigned char *bp, int dr_len, struct isoent *isoent,
2620 struct ctl_extr_rec *ctl)
2626 ctl->isoent = isoent;
2628 ctl->cur_len = ctl->dr_len = dr_len;
2629 ctl->limit = DR_LIMIT;
2635 extra_close_record(struct ctl_extr_rec *ctl, int ce_size)
2640 extra_tell_used_size(ctl, ce_size);
2642 if (ctl->cur_len & 0x01) {
2644 if (ctl->bp != NULL)
2645 ctl->bp[ctl->cur_len] = 0;
2648 if (ctl->use_extr) {
2649 if (ctl->ce_ptr != NULL)
2650 set_SUSP_CE(ctl->ce_ptr, ctl->extr_loc,
2651 ctl->extr_off, ctl->cur_len - padding);
2653 ctl->dr_len = ctl->cur_len;
2656 #define extra_space(ctl) ((ctl)->limit - (ctl)->cur_len)
2658 static unsigned char *
2659 extra_next_record(struct ctl_extr_rec *ctl, int length)
2661 int cur_len = ctl->cur_len;/* save cur_len */
2663 /* Close the current extra record or Directory Record. */
2664 extra_close_record(ctl, RR_CE_SIZE);
2666 /* Get a next extra record. */
2668 if (ctl->bp != NULL) {
2669 /* Storing data into an extra record. */
2672 /* Save the pointer where a CE extension will be
2674 ctl->ce_ptr = &ctl->bp[cur_len+1];
2675 p = extra_get_record(ctl->isoent,
2676 &ctl->limit, &ctl->extr_off, &ctl->extr_loc);
2677 ctl->bp = p - 1;/* the base of bp offset is 1. */
2679 /* Calculating the size of an extra record. */
2680 (void)extra_get_record(ctl->isoent,
2681 &ctl->limit, NULL, NULL);
2683 /* Check if an extra record is almost full.
2684 * If so, get a next one. */
2685 if (extra_space(ctl) < length)
2686 (void)extra_next_record(ctl, length);
2691 static inline struct extr_rec *
2692 extra_last_record(struct isoent *isoent)
2694 if (isoent->extr_rec_list.first == NULL)
2696 return ((struct extr_rec *)(void *)
2697 ((char *)(isoent->extr_rec_list.last)
2698 - offsetof(struct extr_rec, next)));
2701 static unsigned char *
2702 extra_get_record(struct isoent *isoent, int *space, int *off, int *loc)
2704 struct extr_rec *rec;
2706 isoent = isoent->parent;
2708 /* Storing data into an extra record. */
2709 rec = isoent->extr_rec_list.current;
2710 if (DR_SAFETY > LOGICAL_BLOCK_SIZE - rec->offset)
2713 /* Calculating the size of an extra record. */
2714 rec = extra_last_record(isoent);
2716 DR_SAFETY > LOGICAL_BLOCK_SIZE - rec->offset) {
2717 rec = malloc(sizeof(*rec));
2722 /* Insert `rec` into the tail of isoent->extr_rec_list */
2725 * Note: testing isoent->extr_rec_list.last == NULL
2726 * here is really unneeded since it has been already
2727 * initialized at isoent_new function but Clang Static
2728 * Analyzer claims that it is dereference of null
2731 if (isoent->extr_rec_list.last == NULL)
2732 isoent->extr_rec_list.last =
2733 &(isoent->extr_rec_list.first);
2734 *isoent->extr_rec_list.last = rec;
2735 isoent->extr_rec_list.last = &(rec->next);
2738 *space = LOGICAL_BLOCK_SIZE - rec->offset - DR_SAFETY;
2740 *space -= 1;/* Keep padding space. */
2744 *loc = rec->location;
2745 isoent->extr_rec_list.current = rec;
2747 return (&rec->buf[rec->offset]);
2751 extra_tell_used_size(struct ctl_extr_rec *ctl, int size)
2753 struct isoent *isoent;
2754 struct extr_rec *rec;
2756 if (ctl->use_extr) {
2757 isoent = ctl->isoent->parent;
2758 rec = isoent->extr_rec_list.current;
2760 rec->offset += size;
2762 ctl->cur_len += size;
2766 extra_setup_location(struct isoent *isoent, int location)
2768 struct extr_rec *rec;
2772 rec = isoent->extr_rec_list.first;
2773 isoent->extr_rec_list.current = rec;
2776 rec->location = location++;
2784 * Create the RRIP entries.
2787 set_directory_record_rr(unsigned char *bp, int dr_len,
2788 struct isoent *isoent, struct iso9660 *iso9660, enum dir_rec_type t)
2790 /* Flags(BP 5) of the Rockridge "RR" System Use Field */
2791 unsigned char rr_flag;
2792 #define RR_USE_PX 0x01
2793 #define RR_USE_PN 0x02
2794 #define RR_USE_SL 0x04
2795 #define RR_USE_NM 0x08
2796 #define RR_USE_CL 0x10
2797 #define RR_USE_PL 0x20
2798 #define RR_USE_RE 0x40
2799 #define RR_USE_TF 0x80
2801 struct ctl_extr_rec ctl;
2802 struct isoent *rr_parent, *pxent;
2803 struct isofile *file;
2805 bp = extra_open_record(bp, dr_len, isoent, &ctl);
2807 if (t == DIR_REC_PARENT) {
2808 rr_parent = isoent->rr_parent;
2809 pxent = isoent->parent;
2810 if (rr_parent != NULL)
2813 isoent = isoent->parent;
2818 file = isoent->file;
2820 if (t != DIR_REC_NORMAL) {
2821 rr_flag = RR_USE_PX | RR_USE_TF;
2822 if (rr_parent != NULL)
2823 rr_flag |= RR_USE_PL;
2825 rr_flag = RR_USE_PX | RR_USE_NM | RR_USE_TF;
2826 if (archive_entry_filetype(file->entry) == AE_IFLNK)
2827 rr_flag |= RR_USE_SL;
2828 if (isoent->rr_parent != NULL)
2829 rr_flag |= RR_USE_RE;
2830 if (isoent->rr_child != NULL)
2831 rr_flag |= RR_USE_CL;
2832 if (archive_entry_filetype(file->entry) == AE_IFCHR ||
2833 archive_entry_filetype(file->entry) == AE_IFBLK)
2834 rr_flag |= RR_USE_PN;
2835 #ifdef COMPAT_MKISOFS
2837 * mkisofs 2.01.01a63 records "RE" extension to
2838 * the entry of "rr_moved" directory.
2839 * I don't understand this behavior.
2841 if (isoent->virtual &&
2842 isoent->parent == iso9660->primary.rootent &&
2843 strcmp(isoent->file->basename.s, "rr_moved") == 0)
2844 rr_flag |= RR_USE_RE;
2848 /* Write "SP" System Use Entry. */
2849 if (t == DIR_REC_SELF && isoent == isoent->parent) {
2855 bp[4] = 1; /* version */
2856 bp[5] = 0xBE; /* Check Byte */
2857 bp[6] = 0xEF; /* Check Byte */
2861 extra_tell_used_size(&ctl, length);
2864 /* Write "RR" System Use Entry. */
2866 if (extra_space(&ctl) < length)
2867 bp = extra_next_record(&ctl, length);
2872 bp[4] = 1; /* version */
2876 extra_tell_used_size(&ctl, length);
2878 /* Write "NM" System Use Entry. */
2879 if (rr_flag & RR_USE_NM) {
2882 * e.g. a basename is 'foo'
2884 * +----+----+----+----+----+----+----+----+
2885 * | 'N'| 'M'| 08 | 01 | 00 | 'f'| 'o'| 'o'|
2886 * +----+----+----+----+----+----+----+----+
2887 * <----------------- len ----------------->
2889 size_t nmlen = file->basename.length;
2890 const char *nm = file->basename.s;
2893 if (extra_space(&ctl) < 6)
2894 bp = extra_next_record(&ctl, 6);
2898 bp[4] = 1; /* version */
2900 nmmax = extra_space(&ctl);
2903 while (nmlen + 5 > nmmax) {
2904 length = (int)nmmax;
2907 bp[5] = 0x01;/* Alternate Name continues
2908 * in next "NM" field */
2909 memcpy(bp+6, nm, length - 5);
2912 nmlen -= length - 5;
2914 extra_tell_used_size(&ctl, length);
2915 if (extra_space(&ctl) < 6) {
2916 bp = extra_next_record(&ctl, 6);
2917 nmmax = extra_space(&ctl);
2924 bp[4] = 1; /* version */
2927 length = 5 + (int)nmlen;
2931 memcpy(bp+6, nm, nmlen);
2934 extra_tell_used_size(&ctl, length);
2937 /* Write "PX" System Use Entry. */
2938 if (rr_flag & RR_USE_PX) {
2942 * +----+----+----+----+-----------+-----------+
2943 * | 'P'| 'X'| 2C | 01 | FILE MODE | LINKS |
2944 * +----+----+----+----+-----------+-----------+
2946 * +-----------+-----------+------------------+
2947 * | USER ID | GROUP ID |FILE SERIAL NUMBER|
2948 * +-----------+-----------+------------------+
2952 if (extra_space(&ctl) < length)
2953 bp = extra_next_record(&ctl, length);
2959 mode = archive_entry_mode(file->entry);
2960 uid = archive_entry_uid(file->entry);
2961 gid = archive_entry_gid(file->entry);
2962 if (iso9660->opt.rr == OPT_RR_USEFUL) {
2964 * This action is similar to mkisofs -r option
2965 * but our rockridge=useful option does not
2966 * set a zero to uid and gid.
2968 /* set all read bit ON */
2970 #if !defined(_WIN32) && !defined(__CYGWIN__)
2973 /* set all exec bit ON */
2975 /* clear all write bits. */
2977 /* clear setuid,setgid,sticky bits. */
2984 bp[4] = 1; /* version */
2986 set_num_733(bp+5, mode);
2987 /* file links (stat.st_nlink) */
2989 archive_entry_nlink(file->entry));
2990 set_num_733(bp+21, (uint32_t)uid);
2991 set_num_733(bp+29, (uint32_t)gid);
2992 /* File Serial Number */
2994 set_num_733(bp+37, pxent->dir_location);
2995 else if (file->hardlink_target != NULL)
2997 file->hardlink_target->cur_content->location);
3000 file->cur_content->location);
3003 extra_tell_used_size(&ctl, length);
3006 /* Write "SL" System Use Entry. */
3007 if (rr_flag & RR_USE_SL) {
3010 * e.g. a symbolic name is 'foo/bar'
3012 * +----+----+----+----+----+------------+
3013 * | 'S'| 'L'| 0F | 01 | 00 | components |
3014 * +----+----+----+----+----+-----+------+
3015 * 0 1 2 3 4 5 ...|... 15
3016 * <----------------- len --------+------>
3019 * +----+----+----+----+----+ |
3020 * | 00 | 03 | 'f'| 'o'| 'o'| <---+
3021 * +----+----+----+----+----+ |
3024 * +----+----+----+----+----+ |
3025 * | 00 | 03 | 'b'| 'a'| 'r'| <---+
3026 * +----+----+----+----+----+
3029 * - cflg : flag of component
3030 * - clen : length of component
3035 if (extra_space(&ctl) < 7)
3036 bp = extra_next_record(&ctl, 7);
3037 sl = file->symlink.s;
3042 bp[4] = 1; /* version */
3045 unsigned char *nc, *cf, *cl, cldmy = 0;
3048 slmax = extra_space(&ctl);
3057 while (*sl && sllen + 11 < slmax) {
3058 if (sl_last == '\0' && sl[0] == '/') {
3062 * | 08 | 00 | ROOT component.
3065 * Root component has to appear
3066 * at the first component only.
3070 *cf = 0x08; /* ROOT */
3079 if (((sl_last == '\0' || sl_last == '/') &&
3080 sl[0] == '.' && sl[1] == '.' &&
3081 (sl[2] == '/' || sl[2] == '\0')) ||
3083 sl[1] == '.' && sl[2] == '.' &&
3084 (sl[3] == '/' || sl[3] == '\0'))) {
3088 * | 04 | 00 | PARENT component.
3089 * +----+----+ ("..")
3093 *cf = 0x04; /* PARENT */
3098 sl += 3;/* skip "/.." */
3100 sl += 2;/* skip ".." */
3105 if (((sl_last == '\0' || sl_last == '/') &&
3107 (sl[1] == '/' || sl[1] == '\0')) ||
3108 (sl[0] == '/' && sl[1] == '.' &&
3109 (sl[2] == '/' || sl[2] == '\0'))) {
3113 * | 02 | 00 | CURRENT component.
3118 *cf = 0x02; /* CURRENT */
3123 sl += 2;/* skip "/." */
3125 sl ++; /* skip "." */
3130 if (sl[0] == '/' || cl == NULL) {
3155 * Mark flg as CONTINUE component.
3160 * +----+----+----+----+----+-
3161 * | 'S'| 'L'| XX | 01 | 01 |
3162 * +----+----+----+----+----+-
3164 * continues in next "SL"
3167 bp[5] = 0x01;/* This Symbolic Link
3172 extra_tell_used_size(&ctl, length);
3173 if (extra_space(&ctl) < 11)
3174 bp = extra_next_record(&ctl, 11);
3179 bp[4] = 1; /* version */
3188 extra_tell_used_size(&ctl, length);
3194 /* Write "TF" System Use Entry. */
3195 if (rr_flag & RR_USE_TF) {
3199 * +----+----+----+----+-----+-------------+
3200 * | 'T'| 'F'| XX | 01 |FLAGS| TIME STAMPS |
3201 * +----+----+----+----+-----+-------------+
3203 * TIME STAMPS : ISO 9660 Standard 9.1.5.
3204 * If TF_LONG_FORM FLAGS is set,
3205 * use ISO9660 Standard 8.4.26.1.
3207 #define TF_CREATION 0x01 /* Creation time recorded */
3208 #define TF_MODIFY 0x02 /* Modification time recorded */
3209 #define TF_ACCESS 0x04 /* Last Access time recorded */
3210 #define TF_ATTRIBUTES 0x08 /* Last Attribute Change time recorded */
3211 #define TF_BACKUP 0x10 /* Last Backup time recorded */
3212 #define TF_EXPIRATION 0x20 /* Expiration time recorded */
3213 #define TF_EFFECTIVE 0x40 /* Effective time recorded */
3214 #define TF_LONG_FORM 0x80 /* ISO 9660 17-byte time format used */
3215 unsigned char tf_flags;
3219 #ifndef COMPAT_MKISOFS
3220 if (archive_entry_birthtime_is_set(file->entry) &&
3221 archive_entry_birthtime(file->entry) <=
3222 archive_entry_mtime(file->entry)) {
3224 tf_flags |= TF_CREATION;
3227 if (archive_entry_mtime_is_set(file->entry)) {
3229 tf_flags |= TF_MODIFY;
3231 if (archive_entry_atime_is_set(file->entry)) {
3233 tf_flags |= TF_ACCESS;
3235 if (archive_entry_ctime_is_set(file->entry)) {
3237 tf_flags |= TF_ATTRIBUTES;
3239 if (extra_space(&ctl) < length)
3240 bp = extra_next_record(&ctl, length);
3245 bp[4] = 1; /* version */
3249 if (tf_flags & TF_CREATION) {
3251 archive_entry_birthtime(file->entry));
3254 /* Modification time */
3255 if (tf_flags & TF_MODIFY) {
3257 archive_entry_mtime(file->entry));
3260 /* Last Access time */
3261 if (tf_flags & TF_ACCESS) {
3263 archive_entry_atime(file->entry));
3266 /* Last Attribute Change time */
3267 if (tf_flags & TF_ATTRIBUTES) {
3269 archive_entry_ctime(file->entry));
3273 extra_tell_used_size(&ctl, length);
3276 /* Write "RE" System Use Entry. */
3277 if (rr_flag & RR_USE_RE) {
3281 * +----+----+----+----+
3282 * | 'R'| 'E'| 04 | 01 |
3283 * +----+----+----+----+
3287 if (extra_space(&ctl) < length)
3288 bp = extra_next_record(&ctl, length);
3293 bp[4] = 1; /* version */
3296 extra_tell_used_size(&ctl, length);
3299 /* Write "PL" System Use Entry. */
3300 if (rr_flag & RR_USE_PL) {
3304 * +----+----+----+----+------------+
3305 * | 'P'| 'L'| 0C | 01 | *LOCATION |
3306 * +----+----+----+----+------------+
3308 * *LOCATION: location of parent directory
3311 if (extra_space(&ctl) < length)
3312 bp = extra_next_record(&ctl, length);
3317 bp[4] = 1; /* version */
3319 rr_parent->dir_location);
3322 extra_tell_used_size(&ctl, length);
3325 /* Write "CL" System Use Entry. */
3326 if (rr_flag & RR_USE_CL) {
3330 * +----+----+----+----+------------+
3331 * | 'C'| 'L'| 0C | 01 | *LOCATION |
3332 * +----+----+----+----+------------+
3334 * *LOCATION: location of child directory
3337 if (extra_space(&ctl) < length)
3338 bp = extra_next_record(&ctl, length);
3343 bp[4] = 1; /* version */
3345 isoent->rr_child->dir_location);
3348 extra_tell_used_size(&ctl, length);
3351 /* Write "PN" System Use Entry. */
3352 if (rr_flag & RR_USE_PN) {
3356 * +----+----+----+----+------------+------------+
3357 * | 'P'| 'N'| 14 | 01 | dev_t high | dev_t low |
3358 * +----+----+----+----+------------+------------+
3362 if (extra_space(&ctl) < length)
3363 bp = extra_next_record(&ctl, length);
3370 bp[4] = 1; /* version */
3371 dev = (uint64_t)archive_entry_rdev(file->entry);
3372 set_num_733(bp + 5, (uint32_t)(dev >> 32));
3373 set_num_733(bp + 13, (uint32_t)(dev & 0xFFFFFFFF));
3376 extra_tell_used_size(&ctl, length);
3379 /* Write "ZF" System Use Entry. */
3380 if (file->zisofs.header_size) {
3384 * +----+----+----+----+----+----+-------------+
3385 * | 'Z'| 'F'| 10 | 01 | 'p'| 'z'| Header Size |
3386 * +----+----+----+----+----+----+-------------+
3388 * +--------------------+-------------------+
3389 * | Log2 of block Size | Uncompressed Size |
3390 * +--------------------+-------------------+
3394 if (extra_space(&ctl) < length)
3395 bp = extra_next_record(&ctl, length);
3400 bp[4] = 1; /* version */
3403 bp[7] = file->zisofs.header_size;
3404 bp[8] = file->zisofs.log2_bs;
3405 set_num_733(bp + 9, file->zisofs.uncompressed_size);
3408 extra_tell_used_size(&ctl, length);
3411 /* Write "CE" System Use Entry. */
3412 if (t == DIR_REC_SELF && isoent == isoent->parent) {
3413 length = RR_CE_SIZE;
3415 set_SUSP_CE(bp+1, iso9660->location_rrip_er,
3417 extra_tell_used_size(&ctl, length);
3420 extra_close_record(&ctl, 0);
3422 return (ctl.dr_len);
3426 * Write data of a Directory Record or calculate writing bytes itself.
3427 * If parameter `p' is NULL, calculates the size of writing data, which
3428 * a Directory Record needs to write, then it saved and return
3429 * the calculated size.
3430 * Parameter `n' is a remaining size of buffer. when parameter `p' is
3431 * not NULL, check whether that `n' is not less than the saved size.
3432 * if that `n' is small, return zero.
3434 * This format of the Directory Record is according to
3435 * ISO9660 Standard 9.1
3438 set_directory_record(unsigned char *p, size_t n, struct isoent *isoent,
3439 struct iso9660 *iso9660, enum dir_rec_type t,
3440 enum vdd_type vdd_type)
3448 * Check whether a write buffer size is less than the
3449 * saved size which is needed to write this Directory
3454 dr_len = isoent->dr_len.vd; break;
3456 dr_len = isoent->dr_len.self; break;
3457 case DIR_REC_PARENT:
3458 dr_len = isoent->dr_len.parent; break;
3459 case DIR_REC_NORMAL:
3461 dr_len = isoent->dr_len.normal; break;
3464 return (0);/* Needs more buffer size. */
3467 if (t == DIR_REC_NORMAL && isoent->identifier != NULL)
3468 fi_len = isoent->id_len;
3473 struct isoent *xisoent;
3474 struct isofile *file;
3477 if (t == DIR_REC_PARENT)
3478 xisoent = isoent->parent;
3481 file = isoent->file;
3482 if (file->hardlink_target != NULL)
3483 file = file->hardlink_target;
3484 /* Make a file flag. */
3486 flag = FILE_FLAG_DIRECTORY;
3488 if (file->cur_content->next != NULL)
3489 flag = FILE_FLAG_MULTI_EXTENT;
3495 /* Extended Attribute Record Length */
3496 set_num_711(bp+2, 0);
3497 /* Location of Extent */
3499 set_num_733(bp+3, xisoent->dir_location);
3501 set_num_733(bp+3, file->cur_content->location);
3505 xisoent->dir_block * LOGICAL_BLOCK_SIZE);
3507 set_num_733(bp+11, (uint32_t)file->cur_content->size);
3508 /* Recording Date and Time */
3510 * If a file type is symbolic link, you are seeing this
3511 * field value is different from a value mkisofs makes.
3512 * libarchive uses lstat to get this one, but it
3513 * seems mkisofs uses stat to get.
3516 archive_entry_mtime(xisoent->file->entry));
3519 /* File Unit Size */
3520 set_num_711(bp+27, 0);
3521 /* Interleave Gap Size */
3522 set_num_711(bp+28, 0);
3523 /* Volume Sequence Number */
3524 set_num_723(bp+29, iso9660->volume_sequence_number);
3525 /* Length of File Identifier */
3526 set_num_711(bp+33, (unsigned char)fi_len);
3527 /* File Identifier */
3531 set_num_711(bp+34, 0);
3533 case DIR_REC_PARENT:
3534 set_num_711(bp+34, 1);
3536 case DIR_REC_NORMAL:
3537 if (isoent->identifier != NULL)
3538 memcpy(bp+34, isoent->identifier, fi_len);
3540 set_num_711(bp+34, 0);
3545 dr_len = 33 + fi_len;
3547 if (dr_len & 0x01) {
3553 /* Volume Descriptor does not record extension. */
3554 if (t == DIR_REC_VD) {
3556 /* Length of Directory Record */
3557 set_num_711(p, (unsigned char)dr_len);
3559 isoent->dr_len.vd = (int)dr_len;
3560 return ((int)dr_len);
3564 if (iso9660->opt.rr && vdd_type != VDD_JOLIET)
3565 dr_len = set_directory_record_rr(bp, (int)dr_len,
3566 isoent, iso9660, t);
3569 /* Length of Directory Record */
3570 set_num_711(p, (unsigned char)dr_len);
3573 * Save the size which is needed to write this
3578 /* This case does not come, but compiler
3579 * complains that DIR_REC_VD not handled
3583 isoent->dr_len.self = (int)dr_len; break;
3584 case DIR_REC_PARENT:
3585 isoent->dr_len.parent = (int)dr_len; break;
3586 case DIR_REC_NORMAL:
3587 isoent->dr_len.normal = (int)dr_len; break;
3591 return ((int)dr_len);
3595 * Calculate the size of a directory record.
3598 get_dir_rec_size(struct iso9660 *iso9660, struct isoent *isoent,
3599 enum dir_rec_type t, enum vdd_type vdd_type)
3602 return (set_directory_record(NULL, SIZE_MAX,
3603 isoent, iso9660, t, vdd_type));
3607 * Manage to write ISO-image data with wbuff to reduce calling
3608 * __archive_write_output() for performance.
3612 static inline unsigned char *
3613 wb_buffptr(struct archive_write *a)
3615 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3617 return (&(iso9660->wbuff[sizeof(iso9660->wbuff)
3618 - iso9660->wbuff_remaining]));
3622 wb_write_out(struct archive_write *a)
3624 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3628 wsize = sizeof(iso9660->wbuff) - iso9660->wbuff_remaining;
3629 nw = wsize % LOGICAL_BLOCK_SIZE;
3630 if (iso9660->wbuff_type == WB_TO_STREAM)
3631 r = __archive_write_output(a, iso9660->wbuff, wsize - nw);
3633 r = write_to_temp(a, iso9660->wbuff, wsize - nw);
3634 /* Increase the offset. */
3635 iso9660->wbuff_offset += wsize - nw;
3636 if (iso9660->wbuff_offset > iso9660->wbuff_written)
3637 iso9660->wbuff_written = iso9660->wbuff_offset;
3638 iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
3640 iso9660->wbuff_remaining -= nw;
3641 memmove(iso9660->wbuff, iso9660->wbuff + wsize - nw, nw);
3647 wb_consume(struct archive_write *a, size_t size)
3649 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3651 if (size > iso9660->wbuff_remaining ||
3652 iso9660->wbuff_remaining == 0) {
3653 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
3654 "Internal Programming error: iso9660:wb_consume()"
3655 " size=%jd, wbuff_remaining=%jd",
3656 (intmax_t)size, (intmax_t)iso9660->wbuff_remaining);
3657 return (ARCHIVE_FATAL);
3659 iso9660->wbuff_remaining -= size;
3660 if (iso9660->wbuff_remaining < LOGICAL_BLOCK_SIZE)
3661 return (wb_write_out(a));
3662 return (ARCHIVE_OK);
3668 wb_set_offset(struct archive_write *a, int64_t off)
3670 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3671 int64_t used, ext_bytes;
3673 if (iso9660->wbuff_type != WB_TO_TEMP) {
3674 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
3675 "Internal Programming error: iso9660:wb_set_offset()");
3676 return (ARCHIVE_FATAL);
3679 used = sizeof(iso9660->wbuff) - iso9660->wbuff_remaining;
3680 if (iso9660->wbuff_offset + used > iso9660->wbuff_tail)
3681 iso9660->wbuff_tail = iso9660->wbuff_offset + used;
3682 if (iso9660->wbuff_offset < iso9660->wbuff_written) {
3684 write_to_temp(a, iso9660->wbuff, (size_t)used) != ARCHIVE_OK)
3685 return (ARCHIVE_FATAL);
3686 iso9660->wbuff_offset = iso9660->wbuff_written;
3687 lseek(iso9660->temp_fd, iso9660->wbuff_offset, SEEK_SET);
3688 iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
3691 if (off < iso9660->wbuff_offset) {
3693 * Write out waiting data.
3696 if (wb_write_out(a) != ARCHIVE_OK)
3697 return (ARCHIVE_FATAL);
3699 lseek(iso9660->temp_fd, off, SEEK_SET);
3700 iso9660->wbuff_offset = off;
3701 iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
3702 } else if (off <= iso9660->wbuff_tail) {
3703 iso9660->wbuff_remaining = (size_t)
3704 (sizeof(iso9660->wbuff) - (off - iso9660->wbuff_offset));
3706 ext_bytes = off - iso9660->wbuff_tail;
3707 iso9660->wbuff_remaining = (size_t)(sizeof(iso9660->wbuff)
3708 - (iso9660->wbuff_tail - iso9660->wbuff_offset));
3709 while (ext_bytes >= (int64_t)iso9660->wbuff_remaining) {
3710 if (write_null(a, (size_t)iso9660->wbuff_remaining)
3712 return (ARCHIVE_FATAL);
3713 ext_bytes -= iso9660->wbuff_remaining;
3715 if (ext_bytes > 0) {
3716 if (write_null(a, (size_t)ext_bytes) != ARCHIVE_OK)
3717 return (ARCHIVE_FATAL);
3720 return (ARCHIVE_OK);
3723 #endif /* HAVE_ZLIB_H */
3726 write_null(struct archive_write *a, size_t size)
3729 unsigned char *p, *old;
3732 remaining = wb_remaining(a);
3734 if (size <= remaining) {
3736 return (wb_consume(a, size));
3738 memset(p, 0, remaining);
3739 r = wb_consume(a, remaining);
3740 if (r != ARCHIVE_OK)
3745 memset(p, 0, old - p);
3746 remaining = wb_remaining(a);
3748 size_t wsize = size;
3750 if (wsize > remaining)
3752 r = wb_consume(a, wsize);
3753 if (r != ARCHIVE_OK)
3757 return (ARCHIVE_OK);
3761 * Write Volume Descriptor Set Terminator
3764 write_VD_terminator(struct archive_write *a)
3768 bp = wb_buffptr(a) -1;
3769 set_VD_bp(bp, VDT_TERMINATOR, 1);
3770 set_unused_field_bp(bp, 8, LOGICAL_BLOCK_SIZE);
3772 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
3776 set_file_identifier(unsigned char *bp, int from, int to, enum vdc vdc,
3777 struct archive_write *a, struct vdd *vdd, struct archive_string *id,
3778 const char *label, int leading_under, enum char_type char_type)
3780 char identifier[256];
3781 struct isoent *isoent;
3786 if (id->length > 0 && leading_under && id->s[0] != '_') {
3787 if (char_type == A_CHAR)
3788 r = set_str_a_characters_bp(a, bp, from, to, id->s, vdc);
3790 r = set_str_d_characters_bp(a, bp, from, to, id->s, vdc);
3791 } else if (id->length > 0) {
3795 isoent = isoent_find_entry(vdd->rootent, ids);
3796 if (isoent == NULL) {
3797 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
3798 "Not Found %s `%s'.",
3800 return (ARCHIVE_FATAL);
3802 len = isoent->ext_off + isoent->ext_len;
3803 if (vdd->vdd_type == VDD_JOLIET) {
3804 if (len > sizeof(identifier)-2)
3805 len = sizeof(identifier)-2;
3807 if (len > sizeof(identifier)-1)
3808 len = sizeof(identifier)-1;
3810 memcpy(identifier, isoent->identifier, len);
3811 identifier[len] = '\0';
3812 if (vdd->vdd_type == VDD_JOLIET) {
3813 identifier[len+1] = 0;
3814 vdc = VDC_UCS2_DIRECT;
3816 if (char_type == A_CHAR)
3817 r = set_str_a_characters_bp(a, bp, from, to,
3820 r = set_str_d_characters_bp(a, bp, from, to,
3823 if (char_type == A_CHAR)
3824 r = set_str_a_characters_bp(a, bp, from, to, NULL, vdc);
3826 r = set_str_d_characters_bp(a, bp, from, to, NULL, vdc);
3832 * Write Primary/Supplementary Volume Descriptor
3835 write_VD(struct archive_write *a, struct vdd *vdd)
3837 struct iso9660 *iso9660;
3839 uint16_t volume_set_size = 1;
3840 char identifier[256];
3843 unsigned char vd_ver, fst_ver;
3846 iso9660 = a->format_data;
3847 switch (vdd->vdd_type) {
3849 vdt = VDT_SUPPLEMENTARY;
3850 vd_ver = fst_ver = 1;
3854 vdt = VDT_SUPPLEMENTARY;
3855 vd_ver = fst_ver = 2;
3856 vdc = VDC_LOWERCASE;
3861 vd_ver = fst_ver = 1;
3862 #ifdef COMPAT_MKISOFS
3863 vdc = VDC_LOWERCASE;
3870 bp = wb_buffptr(a) -1;
3871 /* Volume Descriptor Type */
3872 set_VD_bp(bp, vdt, vd_ver);
3874 set_unused_field_bp(bp, 8, 8);
3875 /* System Identifier */
3876 get_system_identitier(identifier, sizeof(identifier));
3877 r = set_str_a_characters_bp(a, bp, 9, 40, identifier, vdc);
3878 if (r != ARCHIVE_OK)
3880 /* Volume Identifier */
3881 r = set_str_d_characters_bp(a, bp, 41, 72,
3882 iso9660->volume_identifier.s, vdc);
3883 if (r != ARCHIVE_OK)
3886 set_unused_field_bp(bp, 73, 80);
3887 /* Volume Space Size */
3888 set_num_733(bp+81, iso9660->volume_space_size);
3889 if (vdd->vdd_type == VDD_JOLIET) {
3890 /* Escape Sequences */
3891 bp[89] = 0x25;/* UCS-2 Level 3 */
3894 memset(bp + 92, 0, 120 - 92 + 1);
3897 set_unused_field_bp(bp, 89, 120);
3899 /* Volume Set Size */
3900 set_num_723(bp+121, volume_set_size);
3901 /* Volume Sequence Number */
3902 set_num_723(bp+125, iso9660->volume_sequence_number);
3903 /* Logical Block Size */
3904 set_num_723(bp+129, LOGICAL_BLOCK_SIZE);
3905 /* Path Table Size */
3906 set_num_733(bp+133, vdd->path_table_size);
3907 /* Location of Occurrence of Type L Path Table */
3908 set_num_731(bp+141, vdd->location_type_L_path_table);
3909 /* Location of Optional Occurrence of Type L Path Table */
3910 set_num_731(bp+145, 0);
3911 /* Location of Occurrence of Type M Path Table */
3912 set_num_732(bp+149, vdd->location_type_M_path_table);
3913 /* Location of Optional Occurrence of Type M Path Table */
3914 set_num_732(bp+153, 0);
3915 /* Directory Record for Root Directory(BP 157 to 190) */
3916 set_directory_record(bp+157, 190-157+1, vdd->rootent,
3917 iso9660, DIR_REC_VD, vdd->vdd_type);
3918 /* Volume Set Identifier */
3919 r = set_str_d_characters_bp(a, bp, 191, 318, "", vdc);
3920 if (r != ARCHIVE_OK)
3922 /* Publisher Identifier */
3923 r = set_file_identifier(bp, 319, 446, vdc, a, vdd,
3924 &(iso9660->publisher_identifier),
3925 "Publisher File", 1, A_CHAR);
3926 if (r != ARCHIVE_OK)
3928 /* Data Preparer Identifier */
3929 r = set_file_identifier(bp, 447, 574, vdc, a, vdd,
3930 &(iso9660->data_preparer_identifier),
3931 "Data Preparer File", 1, A_CHAR);
3932 if (r != ARCHIVE_OK)
3934 /* Application Identifier */
3935 r = set_file_identifier(bp, 575, 702, vdc, a, vdd,
3936 &(iso9660->application_identifier),
3937 "Application File", 1, A_CHAR);
3938 if (r != ARCHIVE_OK)
3940 /* Copyright File Identifier */
3941 r = set_file_identifier(bp, 703, 739, vdc, a, vdd,
3942 &(iso9660->copyright_file_identifier),
3943 "Copyright File", 0, D_CHAR);
3944 if (r != ARCHIVE_OK)
3946 /* Abstract File Identifier */
3947 r = set_file_identifier(bp, 740, 776, vdc, a, vdd,
3948 &(iso9660->abstract_file_identifier),
3949 "Abstract File", 0, D_CHAR);
3950 if (r != ARCHIVE_OK)
3952 /* Bibliographic File Identifier */
3953 r = set_file_identifier(bp, 777, 813, vdc, a, vdd,
3954 &(iso9660->bibliographic_file_identifier),
3955 "Bibliongraphic File", 0, D_CHAR);
3956 if (r != ARCHIVE_OK)
3958 /* Volume Creation Date and Time */
3959 set_date_time(bp+814, iso9660->birth_time);
3960 /* Volume Modification Date and Time */
3961 set_date_time(bp+831, iso9660->birth_time);
3962 /* Volume Expiration Date and Time(obsolete) */
3963 set_date_time_null(bp+848);
3964 /* Volume Effective Date and Time */
3965 set_date_time(bp+865, iso9660->birth_time);
3966 /* File Structure Version */
3970 /* Application Use */
3971 memset(bp + 884, 0x20, 1395 - 884 + 1);
3973 set_unused_field_bp(bp, 1396, LOGICAL_BLOCK_SIZE);
3975 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
3979 * Write Boot Record Volume Descriptor
3982 write_VD_boot_record(struct archive_write *a)
3984 struct iso9660 *iso9660;
3987 iso9660 = a->format_data;
3988 bp = wb_buffptr(a) -1;
3989 /* Volume Descriptor Type */
3990 set_VD_bp(bp, VDT_BOOT_RECORD, 1);
3991 /* Boot System Identifier */
3992 memcpy(bp+8, "EL TORITO SPECIFICATION", 23);
3993 set_unused_field_bp(bp, 8+23, 39);
3995 set_unused_field_bp(bp, 40, 71);
3996 /* Absolute pointer to first sector of Boot Catalog */
3998 iso9660->el_torito.catalog->file->content.location);
4000 set_unused_field_bp(bp, 76, LOGICAL_BLOCK_SIZE);
4002 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4012 set_option_info(struct archive_string *info, int *opt, const char *key,
4013 enum keytype type, ...)
4020 prefix = (*opt==0)? ' ':',';
4024 d = va_arg(ap, int);
4025 archive_string_sprintf(info, "%c%s%s",
4026 prefix, (d == 0)?"!":"", key);
4029 s = va_arg(ap, const char *);
4030 archive_string_sprintf(info, "%c%s=%s",
4034 d = va_arg(ap, int);
4035 archive_string_sprintf(info, "%c%s=%d",
4039 d = va_arg(ap, int);
4040 archive_string_sprintf(info, "%c%s=%x",
4050 * Make Non-ISO File System Information
4053 write_information_block(struct archive_write *a)
4055 struct iso9660 *iso9660;
4059 struct archive_string info;
4060 size_t info_size = LOGICAL_BLOCK_SIZE *
4061 NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK;
4063 iso9660 = (struct iso9660 *)a->format_data;
4064 if (info_size > wb_remaining(a)) {
4065 r = wb_write_out(a);
4066 if (r != ARCHIVE_OK)
4069 archive_string_init(&info);
4070 if (archive_string_ensure(&info, info_size) == NULL) {
4071 archive_set_error(&a->archive, ENOMEM,
4072 "Can't allocate memory");
4073 return (ARCHIVE_FATAL);
4075 memset(info.s, 0, info_size);
4077 #if defined(HAVE__CTIME64_S)
4079 __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits
4080 _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp));
4082 #elif defined(HAVE_CTIME_R)
4083 ctime_r(&(iso9660->birth_time), buf);
4085 strncpy(buf, ctime(&(iso9660->birth_time)), sizeof(buf)-1);
4086 buf[sizeof(buf)-1] = '\0';
4088 archive_string_sprintf(&info,
4089 "INFO %s%s", buf, archive_version_string());
4090 if (iso9660->opt.abstract_file != OPT_ABSTRACT_FILE_DEFAULT)
4091 set_option_info(&info, &opt, "abstract-file",
4092 KEY_STR, iso9660->abstract_file_identifier.s);
4093 if (iso9660->opt.application_id != OPT_APPLICATION_ID_DEFAULT)
4094 set_option_info(&info, &opt, "application-id",
4095 KEY_STR, iso9660->application_identifier.s);
4096 if (iso9660->opt.allow_vernum != OPT_ALLOW_VERNUM_DEFAULT)
4097 set_option_info(&info, &opt, "allow-vernum",
4098 KEY_FLG, iso9660->opt.allow_vernum);
4099 if (iso9660->opt.biblio_file != OPT_BIBLIO_FILE_DEFAULT)
4100 set_option_info(&info, &opt, "biblio-file",
4101 KEY_STR, iso9660->bibliographic_file_identifier.s);
4102 if (iso9660->opt.boot != OPT_BOOT_DEFAULT)
4103 set_option_info(&info, &opt, "boot",
4104 KEY_STR, iso9660->el_torito.boot_filename.s);
4105 if (iso9660->opt.boot_catalog != OPT_BOOT_CATALOG_DEFAULT)
4106 set_option_info(&info, &opt, "boot-catalog",
4107 KEY_STR, iso9660->el_torito.catalog_filename.s);
4108 if (iso9660->opt.boot_info_table != OPT_BOOT_INFO_TABLE_DEFAULT)
4109 set_option_info(&info, &opt, "boot-info-table",
4110 KEY_FLG, iso9660->opt.boot_info_table);
4111 if (iso9660->opt.boot_load_seg != OPT_BOOT_LOAD_SEG_DEFAULT)
4112 set_option_info(&info, &opt, "boot-load-seg",
4113 KEY_HEX, iso9660->el_torito.boot_load_seg);
4114 if (iso9660->opt.boot_load_size != OPT_BOOT_LOAD_SIZE_DEFAULT)
4115 set_option_info(&info, &opt, "boot-load-size",
4116 KEY_INT, iso9660->el_torito.boot_load_size);
4117 if (iso9660->opt.boot_type != OPT_BOOT_TYPE_DEFAULT) {
4119 if (iso9660->opt.boot_type == OPT_BOOT_TYPE_FD)
4121 if (iso9660->opt.boot_type == OPT_BOOT_TYPE_HARD_DISK)
4123 set_option_info(&info, &opt, "boot-type",
4127 if (iso9660->opt.compression_level != OPT_COMPRESSION_LEVEL_DEFAULT)
4128 set_option_info(&info, &opt, "compression-level",
4129 KEY_INT, iso9660->zisofs.compression_level);
4131 if (iso9660->opt.copyright_file != OPT_COPYRIGHT_FILE_DEFAULT)
4132 set_option_info(&info, &opt, "copyright-file",
4133 KEY_STR, iso9660->copyright_file_identifier.s);
4134 if (iso9660->opt.iso_level != OPT_ISO_LEVEL_DEFAULT)
4135 set_option_info(&info, &opt, "iso-level",
4136 KEY_INT, iso9660->opt.iso_level);
4137 if (iso9660->opt.joliet != OPT_JOLIET_DEFAULT) {
4138 if (iso9660->opt.joliet == OPT_JOLIET_LONGNAME)
4139 set_option_info(&info, &opt, "joliet",
4142 set_option_info(&info, &opt, "joliet",
4143 KEY_FLG, iso9660->opt.joliet);
4145 if (iso9660->opt.limit_depth != OPT_LIMIT_DEPTH_DEFAULT)
4146 set_option_info(&info, &opt, "limit-depth",
4147 KEY_FLG, iso9660->opt.limit_depth);
4148 if (iso9660->opt.limit_dirs != OPT_LIMIT_DIRS_DEFAULT)
4149 set_option_info(&info, &opt, "limit-dirs",
4150 KEY_FLG, iso9660->opt.limit_dirs);
4151 if (iso9660->opt.pad != OPT_PAD_DEFAULT)
4152 set_option_info(&info, &opt, "pad",
4153 KEY_FLG, iso9660->opt.pad);
4154 if (iso9660->opt.publisher != OPT_PUBLISHER_DEFAULT)
4155 set_option_info(&info, &opt, "publisher",
4156 KEY_STR, iso9660->publisher_identifier.s);
4157 if (iso9660->opt.rr != OPT_RR_DEFAULT) {
4158 if (iso9660->opt.rr == OPT_RR_DISABLED)
4159 set_option_info(&info, &opt, "rockridge",
4160 KEY_FLG, iso9660->opt.rr);
4161 else if (iso9660->opt.rr == OPT_RR_STRICT)
4162 set_option_info(&info, &opt, "rockridge",
4164 else if (iso9660->opt.rr == OPT_RR_USEFUL)
4165 set_option_info(&info, &opt, "rockridge",
4168 if (iso9660->opt.volume_id != OPT_VOLUME_ID_DEFAULT)
4169 set_option_info(&info, &opt, "volume-id",
4170 KEY_STR, iso9660->volume_identifier.s);
4171 if (iso9660->opt.zisofs != OPT_ZISOFS_DEFAULT)
4172 set_option_info(&info, &opt, "zisofs",
4173 KEY_FLG, iso9660->opt.zisofs);
4175 memcpy(wb_buffptr(a), info.s, info_size);
4176 archive_string_free(&info);
4177 return (wb_consume(a, info_size));
4181 write_rr_ER(struct archive_write *a)
4187 memset(p, 0, LOGICAL_BLOCK_SIZE);
4191 p[2] = RRIP_ER_SIZE;
4192 p[4] = RRIP_ER_ID_SIZE;
4193 p[5] = RRIP_ER_DSC_SIZE;
4194 p[6] = RRIP_ER_SRC_SIZE;
4196 memcpy(&p[8], rrip_identifier, p[4]);
4197 memcpy(&p[8+p[4]], rrip_descriptor, p[5]);
4198 memcpy(&p[8+p[4]+p[5]], rrip_source, p[6]);
4200 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4204 calculate_path_table_size(struct vdd *vdd)
4207 struct path_table *pt;
4211 for (depth = 0; depth < vdd->max_depth; depth++) {
4212 struct isoent **ptbl;
4215 if ((cnt = pt[depth].cnt) == 0)
4218 ptbl = pt[depth].sorted;
4219 for (i = 0; i < cnt; i++) {
4222 if (ptbl[i]->identifier == NULL)
4223 len = 1; /* root directory */
4225 len = ptbl[i]->id_len;
4227 len++; /* Padding Field */
4231 vdd->path_table_size = size;
4232 vdd->path_table_block =
4233 ((size + PATH_TABLE_BLOCK_SIZE -1) /
4234 PATH_TABLE_BLOCK_SIZE) *
4235 (PATH_TABLE_BLOCK_SIZE / LOGICAL_BLOCK_SIZE);
4239 _write_path_table(struct archive_write *a, int type_m, int depth,
4242 unsigned char *bp, *wb;
4243 struct isoent **ptbl;
4247 if (vdd->pathtbl[depth].cnt == 0)
4252 wbremaining = wb_remaining(a);
4254 ptbl = vdd->pathtbl[depth].sorted;
4255 for (i = 0; i < vdd->pathtbl[depth].cnt; i++) {
4260 if (np->identifier == NULL)
4261 len = 1; /* root directory */
4264 if (wbremaining - ((bp+1) - wb) < (len + 1 + 8)) {
4265 r = wb_consume(a, (bp+1) - wb);
4269 wbremaining = wb_remaining(a);
4272 /* Length of Directory Identifier */
4273 set_num_711(bp+1, (unsigned char)len);
4274 /* Extended Attribute Record Length */
4275 set_num_711(bp+2, 0);
4276 /* Location of Extent */
4278 set_num_732(bp+3, np->dir_location);
4280 set_num_731(bp+3, np->dir_location);
4281 /* Parent Directory Number */
4283 set_num_722(bp+7, np->parent->dir_number);
4285 set_num_721(bp+7, np->parent->dir_number);
4286 /* Directory Identifier */
4287 if (np->identifier == NULL)
4290 memcpy(&bp[9], np->identifier, len);
4296 wsize += 8 + (int)len;
4299 if ((bp + 1) > wb) {
4300 r = wb_consume(a, (bp+1)-wb);
4308 write_path_table(struct archive_write *a, int type_m, struct vdd *vdd)
4311 size_t path_table_size;
4314 path_table_size = 0;
4315 for (depth = 0; depth < vdd->max_depth; depth++) {
4316 r = _write_path_table(a, type_m, depth, vdd);
4319 path_table_size += r;
4322 /* Write padding data. */
4323 path_table_size = path_table_size % PATH_TABLE_BLOCK_SIZE;
4324 if (path_table_size > 0)
4325 r = write_null(a, PATH_TABLE_BLOCK_SIZE - path_table_size);
4330 calculate_directory_descriptors(struct iso9660 *iso9660, struct vdd *vdd,
4331 struct isoent *isoent, int depth)
4333 struct isoent **enttbl;
4337 bs = get_dir_rec_size(iso9660, isoent, DIR_REC_SELF, vdd->vdd_type);
4338 bs += get_dir_rec_size(iso9660, isoent, DIR_REC_PARENT, vdd->vdd_type);
4340 if (isoent->children.cnt <= 0 || (vdd->vdd_type != VDD_JOLIET &&
4341 !iso9660->opt.rr && depth + 1 >= vdd->max_depth))
4344 enttbl = isoent->children_sorted;
4345 for (i = 0; i < isoent->children.cnt; i++) {
4346 struct isoent *np = enttbl[i];
4347 struct isofile *file;
4350 if (file->hardlink_target != NULL)
4351 file = file->hardlink_target;
4352 file->cur_content = &(file->content);
4356 dr_l = get_dir_rec_size(iso9660, np, DIR_REC_NORMAL,
4358 if ((bs + dr_l) > LOGICAL_BLOCK_SIZE) {
4363 file->cur_content = file->cur_content->next;
4364 } while (file->cur_content != NULL);
4370 _write_directory_descriptors(struct archive_write *a, struct vdd *vdd,
4371 struct isoent *isoent, int depth)
4373 struct iso9660 *iso9660 = a->format_data;
4374 struct isoent **enttbl;
4375 unsigned char *p, *wb;
4379 p = wb = wb_buffptr(a);
4380 #define WD_REMAINING (LOGICAL_BLOCK_SIZE - (p - wb))
4381 p += set_directory_record(p, WD_REMAINING, isoent,
4382 iso9660, DIR_REC_SELF, vdd->vdd_type);
4383 p += set_directory_record(p, WD_REMAINING, isoent,
4384 iso9660, DIR_REC_PARENT, vdd->vdd_type);
4386 if (isoent->children.cnt <= 0 || (vdd->vdd_type != VDD_JOLIET &&
4387 !iso9660->opt.rr && depth + 1 >= vdd->max_depth)) {
4388 memset(p, 0, WD_REMAINING);
4389 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4392 enttbl = isoent->children_sorted;
4393 for (i = 0; i < isoent->children.cnt; i++) {
4394 struct isoent *np = enttbl[i];
4395 struct isofile *file = np->file;
4397 if (file->hardlink_target != NULL)
4398 file = file->hardlink_target;
4399 file->cur_content = &(file->content);
4401 dr_l = set_directory_record(p, WD_REMAINING,
4402 np, iso9660, DIR_REC_NORMAL,
4405 memset(p, 0, WD_REMAINING);
4406 r = wb_consume(a, LOGICAL_BLOCK_SIZE);
4409 p = wb = wb_buffptr(a);
4410 dr_l = set_directory_record(p,
4411 WD_REMAINING, np, iso9660,
4412 DIR_REC_NORMAL, vdd->vdd_type);
4415 file->cur_content = file->cur_content->next;
4416 } while (file->cur_content != NULL);
4418 memset(p, 0, WD_REMAINING);
4419 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4423 write_directory_descriptors(struct archive_write *a, struct vdd *vdd)
4431 struct extr_rec *extr;
4433 r = _write_directory_descriptors(a, vdd, np, depth);
4436 if (vdd->vdd_type != VDD_JOLIET) {
4438 * This extract record is used by SUSP,RRIP.
4441 for (extr = np->extr_rec_list.first;
4443 extr = extr->next) {
4447 memcpy(wb, extr->buf, extr->offset);
4448 memset(wb + extr->offset, 0,
4449 LOGICAL_BLOCK_SIZE - extr->offset);
4450 r = wb_consume(a, LOGICAL_BLOCK_SIZE);
4456 if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) {
4457 /* Enter to sub directories. */
4458 np = np->subdirs.first;
4462 while (np != np->parent) {
4463 if (np->drnext == NULL) {
4464 /* Return to the parent directory. */
4472 } while (np != np->parent);
4474 return (ARCHIVE_OK);
4478 * Read file contents from the temporary file, and write it.
4481 write_file_contents(struct archive_write *a, int64_t offset, int64_t size)
4483 struct iso9660 *iso9660 = a->format_data;
4486 lseek(iso9660->temp_fd, offset, SEEK_SET);
4494 rsize = wb_remaining(a);
4495 if (rsize > (size_t)size)
4496 rsize = (size_t)size;
4497 rs = read(iso9660->temp_fd, wb, rsize);
4499 archive_set_error(&a->archive, errno,
4500 "Can't read temporary file(%jd)", (intmax_t)rs);
4501 return (ARCHIVE_FATAL);
4504 r = wb_consume(a, rs);
4508 return (ARCHIVE_OK);
4512 write_file_descriptors(struct archive_write *a)
4514 struct iso9660 *iso9660 = a->format_data;
4515 struct isofile *file;
4516 int64_t blocks, offset;
4522 /* Make the boot catalog contents, and write it. */
4523 if (iso9660->el_torito.catalog != NULL) {
4524 r = make_boot_catalog(a);
4529 /* Write the boot file contents. */
4530 if (iso9660->el_torito.boot != NULL) {
4531 file = iso9660->el_torito.boot->file;
4532 blocks = file->content.blocks;
4533 offset = file->content.offset_of_temp;
4535 r = write_file_contents(a, offset,
4536 blocks << LOGICAL_BLOCK_BITS);
4544 /* Write out all file contents. */
4545 for (file = iso9660->data_file_list.first;
4546 file != NULL; file = file->datanext) {
4548 if (!file->write_content)
4551 if ((offset + (blocks << LOGICAL_BLOCK_BITS)) <
4552 file->content.offset_of_temp) {
4554 r = write_file_contents(a, offset,
4555 blocks << LOGICAL_BLOCK_BITS);
4560 offset = file->content.offset_of_temp;
4563 file->cur_content = &(file->content);
4565 blocks += file->cur_content->blocks;
4567 file->cur_content = file->cur_content->next;
4568 } while (file->cur_content != NULL);
4571 /* Flush out remaining blocks. */
4573 r = write_file_contents(a, offset,
4574 blocks << LOGICAL_BLOCK_BITS);
4579 return (ARCHIVE_OK);
4583 isofile_init_entry_list(struct iso9660 *iso9660)
4585 iso9660->all_file_list.first = NULL;
4586 iso9660->all_file_list.last = &(iso9660->all_file_list.first);
4590 isofile_add_entry(struct iso9660 *iso9660, struct isofile *file)
4592 file->allnext = NULL;
4593 *iso9660->all_file_list.last = file;
4594 iso9660->all_file_list.last = &(file->allnext);
4598 isofile_free_all_entries(struct iso9660 *iso9660)
4600 struct isofile *file, *file_next;
4602 file = iso9660->all_file_list.first;
4603 while (file != NULL) {
4604 file_next = file->allnext;
4611 isofile_init_entry_data_file_list(struct iso9660 *iso9660)
4613 iso9660->data_file_list.first = NULL;
4614 iso9660->data_file_list.last = &(iso9660->data_file_list.first);
4618 isofile_add_data_file(struct iso9660 *iso9660, struct isofile *file)
4620 file->datanext = NULL;
4621 *iso9660->data_file_list.last = file;
4622 iso9660->data_file_list.last = &(file->datanext);
4626 static struct isofile *
4627 isofile_new(struct archive_write *a, struct archive_entry *entry)
4629 struct isofile *file;
4631 file = calloc(1, sizeof(*file));
4636 file->entry = archive_entry_clone(entry);
4638 file->entry = archive_entry_new2(&a->archive);
4639 if (file->entry == NULL) {
4643 archive_string_init(&(file->parentdir));
4644 archive_string_init(&(file->basename));
4645 archive_string_init(&(file->basename_utf16));
4646 archive_string_init(&(file->symlink));
4647 file->cur_content = &(file->content);
4653 isofile_free(struct isofile *file)
4655 struct content *con, *tmp;
4657 con = file->content.next;
4658 while (con != NULL) {
4663 archive_entry_free(file->entry);
4664 archive_string_free(&(file->parentdir));
4665 archive_string_free(&(file->basename));
4666 archive_string_free(&(file->basename_utf16));
4667 archive_string_free(&(file->symlink));
4671 #if defined(_WIN32) || defined(__CYGWIN__)
4673 cleanup_backslash_1(char *p)
4679 if (*(unsigned char *)p > 127)
4682 /* If we have not met any multi-byte characters,
4683 * we can replace '\' with '/'. */
4696 cleanup_backslash_2(wchar_t *p)
4699 /* Convert a path-separator from '\' to '/' */
4700 while (*p != L'\0') {
4709 * Generate a parent directory name and a base name from a pathname.
4712 isofile_gen_utility_names(struct archive_write *a, struct isofile *file)
4714 struct iso9660 *iso9660;
4715 const char *pathname;
4716 char *p, *dirname, *slash;
4718 int ret = ARCHIVE_OK;
4720 iso9660 = a->format_data;
4722 archive_string_empty(&(file->parentdir));
4723 archive_string_empty(&(file->basename));
4724 archive_string_empty(&(file->basename_utf16));
4725 archive_string_empty(&(file->symlink));
4727 pathname = archive_entry_pathname(file->entry);
4728 if (pathname == NULL || pathname[0] == '\0') {/* virtual root */
4734 * Make a UTF-16BE basename if Joliet extension enabled.
4736 if (iso9660->opt.joliet) {
4737 const char *u16, *ulast;
4738 size_t u16len, ulen_last;
4740 if (iso9660->sconv_to_utf16be == NULL) {
4741 iso9660->sconv_to_utf16be =
4742 archive_string_conversion_to_charset(
4743 &(a->archive), "UTF-16BE", 1);
4744 if (iso9660->sconv_to_utf16be == NULL)
4745 /* Couldn't allocate memory */
4746 return (ARCHIVE_FATAL);
4747 iso9660->sconv_from_utf16be =
4748 archive_string_conversion_from_charset(
4749 &(a->archive), "UTF-16BE", 1);
4750 if (iso9660->sconv_from_utf16be == NULL)
4751 /* Couldn't allocate memory */
4752 return (ARCHIVE_FATAL);
4756 * Convert a filename to UTF-16BE.
4758 if (0 > archive_entry_pathname_l(file->entry, &u16, &u16len,
4759 iso9660->sconv_to_utf16be)) {
4760 if (errno == ENOMEM) {
4761 archive_set_error(&a->archive, ENOMEM,
4762 "Can't allocate memory for UTF-16BE");
4763 return (ARCHIVE_FATAL);
4765 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
4766 "A filename cannot be converted to UTF-16BE;"
4767 "You should disable making Joliet extension");
4772 * Make sure a path separator is not in the last;
4773 * Remove trailing '/'.
4775 while (u16len >= 2) {
4776 #if defined(_WIN32) || defined(__CYGWIN__)
4777 if (u16[u16len-2] == 0 &&
4778 (u16[u16len-1] == '/' || u16[u16len-1] == '\\'))
4780 if (u16[u16len-2] == 0 && u16[u16len-1] == '/')
4789 * Find a basename in UTF-16BE.
4794 while (u16len > 0) {
4795 #if defined(_WIN32) || defined(__CYGWIN__)
4796 if (u16[0] == 0 && (u16[1] == '/' || u16[1] == '\\'))
4798 if (u16[0] == 0 && u16[1] == '/')
4802 ulen_last = u16len -1;
4808 if (archive_string_ensure(&(file->basename_utf16),
4809 ulen_last) == NULL) {
4810 archive_set_error(&a->archive, ENOMEM,
4811 "Can't allocate memory for UTF-16BE");
4812 return (ARCHIVE_FATAL);
4816 * Set UTF-16BE basename.
4818 memcpy(file->basename_utf16.s, ulast, ulen_last);
4819 file->basename_utf16.length = ulen_last;
4822 archive_strcpy(&(file->parentdir), pathname);
4823 #if defined(_WIN32) || defined(__CYGWIN__)
4825 * Convert a path-separator from '\' to '/'
4827 if (cleanup_backslash_1(file->parentdir.s) != 0) {
4828 const wchar_t *wp = archive_entry_pathname_w(file->entry);
4829 struct archive_wstring ws;
4833 archive_string_init(&ws);
4834 archive_wstrcpy(&ws, wp);
4835 cleanup_backslash_2(ws.s);
4836 archive_string_empty(&(file->parentdir));
4837 r = archive_string_append_from_wcs(&(file->parentdir),
4839 archive_wstring_free(&ws);
4840 if (r < 0 && errno == ENOMEM) {
4841 archive_set_error(&a->archive, ENOMEM,
4842 "Can't allocate memory");
4843 return (ARCHIVE_FATAL);
4849 len = file->parentdir.length;
4850 p = dirname = file->parentdir.s;
4853 * Remove leading '/', '../' and './' elements
4859 } else if (p[0] != '.')
4861 else if (p[1] == '.' && p[2] == '/') {
4864 } else if (p[1] == '/' || (p[1] == '.' && p[2] == '\0')) {
4867 } else if (p[1] == '\0') {
4874 memmove(dirname, p, len+1);
4878 * Remove "/","/." and "/.." elements from tail.
4883 if (len > 0 && p[len-1] == '/') {
4887 if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
4891 if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
4902 /* Convert '//' --> '/' */
4903 memmove(p, p+1, strlen(p+1) + 1);
4904 else if (p[1] == '.' && p[2] == '/')
4905 /* Convert '/./' --> '/' */
4906 memmove(p, p+2, strlen(p+2) + 1);
4907 else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
4908 /* Convert 'dir/dir1/../dir2/'
4912 while (rp >= dirname) {
4921 strcpy(dirname, p+4);
4932 if (archive_entry_filetype(file->entry) == AE_IFLNK) {
4933 /* Convert symlink name too. */
4934 pathname = archive_entry_symlink(file->entry);
4935 archive_strcpy(&(file->symlink), pathname);
4936 #if defined(_WIN32) || defined(__CYGWIN__)
4938 * Convert a path-separator from '\' to '/'
4940 if (archive_strlen(&(file->symlink)) > 0 &&
4941 cleanup_backslash_1(file->symlink.s) != 0) {
4943 archive_entry_symlink_w(file->entry);
4944 struct archive_wstring ws;
4948 archive_string_init(&ws);
4949 archive_wstrcpy(&ws, wp);
4950 cleanup_backslash_2(ws.s);
4951 archive_string_empty(&(file->symlink));
4952 r = archive_string_append_from_wcs(
4955 archive_wstring_free(&ws);
4956 if (r < 0 && errno == ENOMEM) {
4957 archive_set_error(&a->archive, ENOMEM,
4958 "Can't allocate memory");
4959 return (ARCHIVE_FATAL);
4966 * - Count up directory elements.
4967 * - Find out the position which points the last position of
4968 * path separator('/').
4972 for (; *p != '\0'; p++)
4977 if (slash == NULL) {
4978 /* The pathname doesn't have a parent directory. */
4979 file->parentdir.length = len;
4980 archive_string_copy(&(file->basename), &(file->parentdir));
4981 archive_string_empty(&(file->parentdir));
4982 *file->parentdir.s = '\0';
4986 /* Make a basename from dirname and slash */
4988 file->parentdir.length = slash - dirname;
4989 archive_strcpy(&(file->basename), slash + 1);
4990 if (archive_entry_filetype(file->entry) == AE_IFDIR)
4996 * Register a entry to get a hardlink target.
4999 isofile_register_hardlink(struct archive_write *a, struct isofile *file)
5001 struct iso9660 *iso9660 = a->format_data;
5002 struct hardlink *hl;
5003 const char *pathname;
5005 archive_entry_set_nlink(file->entry, 1);
5006 pathname = archive_entry_hardlink(file->entry);
5007 if (pathname == NULL) {
5008 /* This `file` is a hardlink target. */
5009 hl = malloc(sizeof(*hl));
5011 archive_set_error(&a->archive, ENOMEM,
5012 "Can't allocate memory");
5013 return (ARCHIVE_FATAL);
5016 /* A hardlink target must be the first position. */
5017 file->hlnext = NULL;
5018 hl->file_list.first = file;
5019 hl->file_list.last = &(file->hlnext);
5020 __archive_rb_tree_insert_node(&(iso9660->hardlink_rbtree),
5021 (struct archive_rb_node *)hl);
5023 hl = (struct hardlink *)__archive_rb_tree_find_node(
5024 &(iso9660->hardlink_rbtree), pathname);
5026 /* Insert `file` entry into the tail. */
5027 file->hlnext = NULL;
5028 *hl->file_list.last = file;
5029 hl->file_list.last = &(file->hlnext);
5032 archive_entry_unset_size(file->entry);
5035 return (ARCHIVE_OK);
5039 * Hardlinked files have to have the same location of extent.
5040 * We have to find out hardlink target entries for the entries
5041 * which have a hardlink target name.
5044 isofile_connect_hardlink_files(struct iso9660 *iso9660)
5046 struct archive_rb_node *n;
5047 struct hardlink *hl;
5048 struct isofile *target, *nf;
5050 ARCHIVE_RB_TREE_FOREACH(n, &(iso9660->hardlink_rbtree)) {
5051 hl = (struct hardlink *)n;
5053 /* The first entry must be a hardlink target. */
5054 target = hl->file_list.first;
5055 archive_entry_set_nlink(target->entry, hl->nlink);
5056 /* Set a hardlink target to reference entries. */
5057 for (nf = target->hlnext;
5058 nf != NULL; nf = nf->hlnext) {
5059 nf->hardlink_target = target;
5060 archive_entry_set_nlink(nf->entry, hl->nlink);
5066 isofile_hd_cmp_node(const struct archive_rb_node *n1,
5067 const struct archive_rb_node *n2)
5069 const struct hardlink *h1 = (const struct hardlink *)n1;
5070 const struct hardlink *h2 = (const struct hardlink *)n2;
5072 return (strcmp(archive_entry_pathname(h1->file_list.first->entry),
5073 archive_entry_pathname(h2->file_list.first->entry)));
5077 isofile_hd_cmp_key(const struct archive_rb_node *n, const void *key)
5079 const struct hardlink *h = (const struct hardlink *)n;
5081 return (strcmp(archive_entry_pathname(h->file_list.first->entry),
5082 (const char *)key));
5086 isofile_init_hardlinks(struct iso9660 *iso9660)
5088 static const struct archive_rb_tree_ops rb_ops = {
5089 isofile_hd_cmp_node, isofile_hd_cmp_key,
5092 __archive_rb_tree_init(&(iso9660->hardlink_rbtree), &rb_ops);
5096 isofile_free_hardlinks(struct iso9660 *iso9660)
5098 struct archive_rb_node *n, *tmp;
5100 ARCHIVE_RB_TREE_FOREACH_SAFE(n, &(iso9660->hardlink_rbtree), tmp) {
5101 __archive_rb_tree_remove_node(&(iso9660->hardlink_rbtree), n);
5106 static struct isoent *
5107 isoent_new(struct isofile *file)
5109 struct isoent *isoent;
5110 static const struct archive_rb_tree_ops rb_ops = {
5111 isoent_cmp_node, isoent_cmp_key,
5114 isoent = calloc(1, sizeof(*isoent));
5117 isoent->file = file;
5118 isoent->children.first = NULL;
5119 isoent->children.last = &(isoent->children.first);
5120 __archive_rb_tree_init(&(isoent->rbtree), &rb_ops);
5121 isoent->subdirs.first = NULL;
5122 isoent->subdirs.last = &(isoent->subdirs.first);
5123 isoent->extr_rec_list.first = NULL;
5124 isoent->extr_rec_list.last = &(isoent->extr_rec_list.first);
5125 isoent->extr_rec_list.current = NULL;
5126 if (archive_entry_filetype(file->entry) == AE_IFDIR)
5132 static inline struct isoent *
5133 isoent_clone(struct isoent *src)
5135 return (isoent_new(src->file));
5139 _isoent_free(struct isoent *isoent)
5141 struct extr_rec *er, *er_next;
5143 free(isoent->children_sorted);
5144 free(isoent->identifier);
5145 er = isoent->extr_rec_list.first;
5146 while (er != NULL) {
5155 isoent_free_all(struct isoent *isoent)
5157 struct isoent *np, *np_temp;
5164 if (np->children.first != NULL) {
5165 /* Enter to sub directories. */
5166 np = np->children.first;
5172 if (np->chnext == NULL) {
5173 /* Return to the parent directory. */
5175 _isoent_free(np_temp);
5180 _isoent_free(np_temp);
5187 static struct isoent *
5188 isoent_create_virtual_dir(struct archive_write *a, struct iso9660 *iso9660, const char *pathname)
5190 struct isofile *file;
5191 struct isoent *isoent;
5193 file = isofile_new(a, NULL);
5196 archive_entry_set_pathname(file->entry, pathname);
5197 archive_entry_unset_mtime(file->entry);
5198 archive_entry_unset_atime(file->entry);
5199 archive_entry_unset_ctime(file->entry);
5200 archive_entry_set_uid(file->entry, getuid());
5201 archive_entry_set_gid(file->entry, getgid());
5202 archive_entry_set_mode(file->entry, 0555 | AE_IFDIR);
5203 archive_entry_set_nlink(file->entry, 2);
5204 if (isofile_gen_utility_names(a, file) < ARCHIVE_WARN) {
5208 isofile_add_entry(iso9660, file);
5210 isoent = isoent_new(file);
5214 isoent->virtual = 1;
5220 isoent_cmp_node(const struct archive_rb_node *n1,
5221 const struct archive_rb_node *n2)
5223 const struct isoent *e1 = (const struct isoent *)n1;
5224 const struct isoent *e2 = (const struct isoent *)n2;
5226 return (strcmp(e1->file->basename.s, e2->file->basename.s));
5230 isoent_cmp_key(const struct archive_rb_node *n, const void *key)
5232 const struct isoent *e = (const struct isoent *)n;
5234 return (strcmp(e->file->basename.s, (const char *)key));
5238 isoent_add_child_head(struct isoent *parent, struct isoent *child)
5241 if (!__archive_rb_tree_insert_node(
5242 &(parent->rbtree), (struct archive_rb_node *)child))
5244 if ((child->chnext = parent->children.first) == NULL)
5245 parent->children.last = &(child->chnext);
5246 parent->children.first = child;
5247 parent->children.cnt++;
5248 child->parent = parent;
5250 /* Add a child to a sub-directory chain */
5252 if ((child->drnext = parent->subdirs.first) == NULL)
5253 parent->subdirs.last = &(child->drnext);
5254 parent->subdirs.first = child;
5255 parent->subdirs.cnt++;
5256 child->parent = parent;
5258 child->drnext = NULL;
5263 isoent_add_child_tail(struct isoent *parent, struct isoent *child)
5266 if (!__archive_rb_tree_insert_node(
5267 &(parent->rbtree), (struct archive_rb_node *)child))
5269 child->chnext = NULL;
5270 *parent->children.last = child;
5271 parent->children.last = &(child->chnext);
5272 parent->children.cnt++;
5273 child->parent = parent;
5275 /* Add a child to a sub-directory chain */
5276 child->drnext = NULL;
5278 *parent->subdirs.last = child;
5279 parent->subdirs.last = &(child->drnext);
5280 parent->subdirs.cnt++;
5281 child->parent = parent;
5287 isoent_remove_child(struct isoent *parent, struct isoent *child)
5291 /* Remove a child entry from children chain. */
5292 ent = parent->children.first;
5293 while (ent->chnext != child)
5295 if ((ent->chnext = ent->chnext->chnext) == NULL)
5296 parent->children.last = &(ent->chnext);
5297 parent->children.cnt--;
5300 /* Remove a child entry from sub-directory chain. */
5301 ent = parent->subdirs.first;
5302 while (ent->drnext != child)
5304 if ((ent->drnext = ent->drnext->drnext) == NULL)
5305 parent->subdirs.last = &(ent->drnext);
5306 parent->subdirs.cnt--;
5309 __archive_rb_tree_remove_node(&(parent->rbtree),
5310 (struct archive_rb_node *)child);
5314 isoent_clone_tree(struct archive_write *a, struct isoent **nroot,
5315 struct isoent *root)
5317 struct isoent *np, *xroot, *newent;
5322 newent = isoent_clone(np);
5323 if (newent == NULL) {
5324 archive_set_error(&a->archive, ENOMEM,
5325 "Can't allocate memory");
5326 return (ARCHIVE_FATAL);
5328 if (xroot == NULL) {
5329 *nroot = xroot = newent;
5330 newent->parent = xroot;
5332 isoent_add_child_tail(xroot, newent);
5333 if (np->dir && np->children.first != NULL) {
5334 /* Enter to sub directories. */
5335 np = np->children.first;
5339 while (np != np->parent) {
5340 if (np->chnext == NULL) {
5341 /* Return to the parent directory. */
5343 xroot = xroot->parent;
5349 } while (np != np->parent);
5351 return (ARCHIVE_OK);
5355 * Setup directory locations.
5358 isoent_setup_directory_location(struct iso9660 *iso9660, int location,
5364 vdd->total_dir_block = 0;
5370 np->dir_block = calculate_directory_descriptors(
5371 iso9660, vdd, np, depth);
5372 vdd->total_dir_block += np->dir_block;
5373 np->dir_location = location;
5374 location += np->dir_block;
5375 block = extra_setup_location(np, location);
5376 vdd->total_dir_block += block;
5379 if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) {
5380 /* Enter to sub directories. */
5381 np = np->subdirs.first;
5385 while (np != np->parent) {
5386 if (np->drnext == NULL) {
5387 /* Return to the parent directory. */
5395 } while (np != np->parent);
5399 _isoent_file_location(struct iso9660 *iso9660, struct isoent *isoent,
5402 struct isoent **children;
5405 if (isoent->children.cnt == 0)
5408 children = isoent->children_sorted;
5409 for (n = 0; n < isoent->children.cnt; n++) {
5411 struct isofile *file;
5416 if (np == iso9660->el_torito.boot)
5419 if (file->boot || file->hardlink_target != NULL)
5421 if (archive_entry_filetype(file->entry) == AE_IFLNK ||
5422 file->content.size == 0) {
5424 * Do not point a valid location.
5425 * Make sure entry is not hardlink file.
5427 file->content.location = (*symlocation)--;
5431 file->write_content = 1;
5436 * Setup file locations.
5439 isoent_setup_file_location(struct iso9660 *iso9660, int location)
5441 struct isoent *isoent;
5443 struct isofile *file;
5451 iso9660->total_file_block = 0;
5452 if ((isoent = iso9660->el_torito.catalog) != NULL) {
5453 isoent->file->content.location = location;
5454 block = (int)((archive_entry_size(isoent->file->entry) +
5455 LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS);
5457 iso9660->total_file_block += block;
5459 if ((isoent = iso9660->el_torito.boot) != NULL) {
5460 isoent->file->content.location = location;
5461 size = fd_boot_image_size(iso9660->el_torito.media_type);
5463 size = (size_t)archive_entry_size(isoent->file->entry);
5464 block = ((int)size + LOGICAL_BLOCK_SIZE -1)
5465 >> LOGICAL_BLOCK_BITS;
5467 iso9660->total_file_block += block;
5468 isoent->file->content.blocks = block;
5473 if (!iso9660->opt.rr && iso9660->opt.joliet) {
5475 np = iso9660->joliet.rootent;
5478 np = iso9660->primary.rootent;
5481 _isoent_file_location(iso9660, np, &symlocation);
5483 if (np->subdirs.first != NULL &&
5485 ((iso9660->opt.rr == OPT_RR_DISABLED &&
5486 depth + 2 < iso9660->primary.max_depth) ||
5488 depth + 1 < iso9660->primary.max_depth)))) {
5489 /* Enter to sub directories. */
5490 np = np->subdirs.first;
5494 while (np != np->parent) {
5495 if (np->drnext == NULL) {
5496 /* Return to the parent directory. */
5504 } while (np != np->parent);
5507 for (file = iso9660->data_file_list.first;
5508 file != NULL; file = file->datanext) {
5510 if (!file->write_content)
5513 file->cur_content = &(file->content);
5515 file->cur_content->location = location;
5516 location += file->cur_content->blocks;
5517 total_block += file->cur_content->blocks;
5519 file->cur_content = file->cur_content->next;
5520 } while (file->cur_content != NULL);
5522 iso9660->total_file_block += total_block;
5526 get_path_component(char *name, size_t n, const char *fn)
5531 p = strchr(fn, '/');
5533 if ((l = strlen(fn)) == 0)
5539 memcpy(name, fn, l);
5546 * Add a new entry into the tree.
5549 isoent_tree(struct archive_write *a, struct isoent **isoentpp)
5551 #if defined(_WIN32) && !defined(__CYGWIN__)
5552 char name[_MAX_FNAME];/* Included null terminator size. */
5553 #elif defined(NAME_MAX) && NAME_MAX >= 255
5554 char name[NAME_MAX+1];
5558 struct iso9660 *iso9660 = a->format_data;
5559 struct isoent *dent, *isoent, *np;
5560 struct isofile *f1, *f2;
5565 dent = iso9660->primary.rootent;
5566 if (isoent->file->parentdir.length > 0)
5567 fn = p = isoent->file->parentdir.s;
5572 * If the path of the parent directory of `isoent' entry is
5573 * the same as the path of `cur_dirent', add isoent to
5576 if (archive_strlen(&(iso9660->cur_dirstr))
5577 == archive_strlen(&(isoent->file->parentdir)) &&
5578 strcmp(iso9660->cur_dirstr.s, fn) == 0) {
5579 if (!isoent_add_child_tail(iso9660->cur_dirent, isoent)) {
5580 np = (struct isoent *)__archive_rb_tree_find_node(
5581 &(iso9660->cur_dirent->rbtree),
5582 isoent->file->basename.s);
5585 return (ARCHIVE_OK);
5589 l = get_path_component(name, sizeof(name), fn);
5595 archive_set_error(&a->archive,
5597 "A name buffer is too small");
5598 _isoent_free(isoent);
5599 return (ARCHIVE_FATAL);
5602 np = isoent_find_child(dent, name);
5603 if (np == NULL || fn[0] == '\0')
5606 /* Find next subdirectory. */
5608 /* NOT Directory! */
5609 archive_set_error(&a->archive,
5611 "`%s' is not directory, we cannot insert `%s' ",
5612 archive_entry_pathname(np->file->entry),
5613 archive_entry_pathname(isoent->file->entry));
5614 _isoent_free(isoent);
5616 return (ARCHIVE_FAILED);
5625 * Create virtual parent directories.
5627 while (fn[0] != '\0') {
5629 struct archive_string as;
5631 archive_string_init(&as);
5632 archive_strncat(&as, p, fn - p + l);
5633 if (as.s[as.length-1] == '/') {
5634 as.s[as.length-1] = '\0';
5637 vp = isoent_create_virtual_dir(a, iso9660, as.s);
5639 archive_string_free(&as);
5640 archive_set_error(&a->archive, ENOMEM,
5641 "Can't allocate memory");
5642 _isoent_free(isoent);
5644 return (ARCHIVE_FATAL);
5646 archive_string_free(&as);
5648 if (vp->file->dircnt > iso9660->dircnt_max)
5649 iso9660->dircnt_max = vp->file->dircnt;
5650 isoent_add_child_tail(dent, vp);
5656 l = get_path_component(name, sizeof(name), fn);
5658 archive_string_free(&as);
5659 archive_set_error(&a->archive,
5661 "A name buffer is too small");
5662 _isoent_free(isoent);
5664 return (ARCHIVE_FATAL);
5669 /* Found out the parent directory where isoent can be
5671 iso9660->cur_dirent = dent;
5672 archive_string_empty(&(iso9660->cur_dirstr));
5673 archive_string_ensure(&(iso9660->cur_dirstr),
5674 archive_strlen(&(dent->file->parentdir)) +
5675 archive_strlen(&(dent->file->basename)) + 2);
5676 if (archive_strlen(&(dent->file->parentdir)) +
5677 archive_strlen(&(dent->file->basename)) == 0)
5678 iso9660->cur_dirstr.s[0] = 0;
5680 if (archive_strlen(&(dent->file->parentdir)) > 0) {
5681 archive_string_copy(&(iso9660->cur_dirstr),
5682 &(dent->file->parentdir));
5683 archive_strappend_char(&(iso9660->cur_dirstr), '/');
5685 archive_string_concat(&(iso9660->cur_dirstr),
5686 &(dent->file->basename));
5689 if (!isoent_add_child_tail(dent, isoent)) {
5690 np = (struct isoent *)__archive_rb_tree_find_node(
5691 &(dent->rbtree), isoent->file->basename.s);
5694 return (ARCHIVE_OK);
5699 * We have already has the entry the filename of which is
5705 /* If the file type of entries is different,
5706 * we cannot handle it. */
5707 if (archive_entry_filetype(f1->entry) !=
5708 archive_entry_filetype(f2->entry)) {
5709 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
5710 "Found duplicate entries `%s' and its file type is "
5712 archive_entry_pathname(f1->entry));
5713 _isoent_free(isoent);
5715 return (ARCHIVE_FAILED);
5718 /* Swap file entries. */
5723 _isoent_free(isoent);
5725 return (ARCHIVE_OK);
5729 * Find a entry from `isoent'
5731 static struct isoent *
5732 isoent_find_child(struct isoent *isoent, const char *child_name)
5736 np = (struct isoent *)__archive_rb_tree_find_node(
5737 &(isoent->rbtree), child_name);
5742 * Find a entry full-path of which is specified by `fn' parameter,
5745 static struct isoent *
5746 isoent_find_entry(struct isoent *rootent, const char *fn)
5748 #if defined(_WIN32) && !defined(__CYGWIN__)
5749 char name[_MAX_FNAME];/* Included null terminator size. */
5750 #elif defined(NAME_MAX) && NAME_MAX >= 255
5751 char name[NAME_MAX+1];
5755 struct isoent *isoent, *np;
5761 l = get_path_component(name, sizeof(name), fn);
5768 np = isoent_find_child(isoent, name);
5772 break;/* We found out the entry */
5774 /* Try sub directory. */
5778 break;/* Not directory */
5785 * Following idr_* functions are used for resolving duplicated filenames
5786 * and unreceivable filenames to generate ISO9660/Joliet Identifiers.
5790 idr_relaxed_filenames(char *map)
5794 for (i = 0x21; i <= 0x2F; i++)
5796 for (i = 0x3A; i <= 0x41; i++)
5798 for (i = 0x5B; i <= 0x5E; i++)
5801 for (i = 0x7B; i <= 0x7E; i++)
5806 idr_init(struct iso9660 *iso9660, struct vdd *vdd, struct idr *idr)
5809 idr->idrent_pool = NULL;
5811 if (vdd->vdd_type != VDD_JOLIET) {
5812 if (iso9660->opt.iso_level <= 3) {
5813 memcpy(idr->char_map, d_characters_map,
5814 sizeof(idr->char_map));
5816 memcpy(idr->char_map, d1_characters_map,
5817 sizeof(idr->char_map));
5818 idr_relaxed_filenames(idr->char_map);
5824 idr_cleanup(struct idr *idr)
5826 free(idr->idrent_pool);
5830 idr_ensure_poolsize(struct archive_write *a, struct idr *idr,
5834 if (idr->pool_size < cnt) {
5836 const int bk = (1 << 7) - 1;
5839 psize = (cnt + bk) & ~bk;
5840 p = realloc(idr->idrent_pool, sizeof(struct idrent) * psize);
5842 archive_set_error(&a->archive, ENOMEM,
5843 "Can't allocate memory");
5844 return (ARCHIVE_FATAL);
5846 idr->idrent_pool = (struct idrent *)p;
5847 idr->pool_size = psize;
5849 return (ARCHIVE_OK);
5853 idr_start(struct archive_write *a, struct idr *idr, int cnt, int ffmax,
5854 int num_size, int null_size, const struct archive_rb_tree_ops *rbt_ops)
5858 (void)ffmax; /* UNUSED */
5860 r = idr_ensure_poolsize(a, idr, cnt);
5861 if (r != ARCHIVE_OK)
5863 __archive_rb_tree_init(&(idr->rbtree), rbt_ops);
5864 idr->wait_list.first = NULL;
5865 idr->wait_list.last = &(idr->wait_list.first);
5867 idr->num_size = num_size;
5868 idr->null_size = null_size;
5869 return (ARCHIVE_OK);
5873 idr_register(struct idr *idr, struct isoent *isoent, int weight, int noff)
5875 struct idrent *idrent, *n;
5877 idrent = &(idr->idrent_pool[idr->pool_idx++]);
5878 idrent->wnext = idrent->avail = NULL;
5879 idrent->isoent = isoent;
5880 idrent->weight = weight;
5881 idrent->noff = noff;
5882 idrent->rename_num = 0;
5884 if (!__archive_rb_tree_insert_node(&(idr->rbtree), &(idrent->rbnode))) {
5885 n = (struct idrent *)__archive_rb_tree_find_node(
5886 &(idr->rbtree), idrent->isoent);
5888 /* this `idrent' needs to rename. */
5890 *idr->wait_list.last = idrent;
5891 idr->wait_list.last = &(idrent->wnext);
5897 idr_extend_identifier(struct idrent *wnp, int numsize, int nullsize)
5902 wnp_ext_off = wnp->isoent->ext_off;
5903 if (wnp->noff + numsize != wnp_ext_off) {
5904 p = (unsigned char *)wnp->isoent->identifier;
5905 /* Extend the filename; foo.c --> foo___.c */
5906 memmove(p + wnp->noff + numsize, p + wnp_ext_off,
5907 wnp->isoent->ext_len + nullsize);
5908 wnp->isoent->ext_off = wnp_ext_off = wnp->noff + numsize;
5909 wnp->isoent->id_len = wnp_ext_off + wnp->isoent->ext_len;
5914 idr_resolve(struct idr *idr, void (*fsetnum)(unsigned char *p, int num))
5919 for (n = idr->wait_list.first; n != NULL; n = n->wnext) {
5920 idr_extend_identifier(n, idr->num_size, idr->null_size);
5921 p = (unsigned char *)n->isoent->identifier + n->noff;
5923 fsetnum(p, n->avail->rename_num++);
5924 } while (!__archive_rb_tree_insert_node(
5925 &(idr->rbtree), &(n->rbnode)));
5930 idr_set_num(unsigned char *p, int num)
5932 static const char xdig[] = {
5933 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
5934 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
5935 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
5936 'U', 'V', 'W', 'X', 'Y', 'Z'
5939 num %= sizeof(xdig) * sizeof(xdig) * sizeof(xdig);
5940 p[0] = xdig[(num / (sizeof(xdig) * sizeof(xdig)))];
5941 num %= sizeof(xdig) * sizeof(xdig);
5942 p[1] = xdig[ (num / sizeof(xdig))];
5943 num %= sizeof(xdig);
5948 idr_set_num_beutf16(unsigned char *p, int num)
5950 static const uint16_t xdig[] = {
5951 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
5952 0x0036, 0x0037, 0x0038, 0x0039,
5953 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046,
5954 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C,
5955 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052,
5956 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
5959 #define XDIG_CNT (sizeof(xdig)/sizeof(xdig[0]))
5961 num %= XDIG_CNT * XDIG_CNT * XDIG_CNT;
5962 archive_be16enc(p, xdig[(num / (XDIG_CNT * XDIG_CNT))]);
5963 num %= XDIG_CNT * XDIG_CNT;
5964 archive_be16enc(p+2, xdig[ (num / XDIG_CNT)]);
5966 archive_be16enc(p+4, xdig[num]);
5970 * Generate ISO9660 Identifier.
5973 isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent,
5976 struct iso9660 *iso9660;
5980 const char *char_map;
5981 char allow_ldots, allow_multidot, allow_period, allow_vernum;
5982 int fnmax, ffmax, dnmax;
5983 static const struct archive_rb_tree_ops rb_ops = {
5984 isoent_cmp_node_iso9660, isoent_cmp_key_iso9660
5987 if (isoent->children.cnt == 0)
5990 iso9660 = a->format_data;
5991 char_map = idr->char_map;
5992 if (iso9660->opt.iso_level <= 3) {
5996 allow_vernum = iso9660->opt.allow_vernum;
5997 if (iso9660->opt.iso_level == 1) {
5999 ffmax = 12;/* fnmax + '.' + 3 */
6007 allow_ldots = allow_multidot = 1;
6008 allow_period = allow_vernum = 0;
6009 if (iso9660->opt.rr)
6011 * MDR : The maximum size of Directory Record(254).
6012 * DRL : A Directory Record Length(33).
6013 * CE : A size of SUSP CE System Use Entry(28).
6014 * MDR - DRL - CE = 254 - 33 - 28 = 193.
6016 fnmax = ffmax = dnmax = 193;
6019 * XA : CD-ROM XA System Use Extension
6021 * MDR - DRL - XA = 254 - 33 -14 = 207.
6023 fnmax = ffmax = dnmax = 207;
6026 r = idr_start(a, idr, isoent->children.cnt, ffmax, 3, 1, &rb_ops);
6030 for (np = isoent->children.first; np != NULL; np = np->chnext) {
6032 int ext_off, noff, weight;
6034 l = (int)np->file->basename.length;
6035 p = malloc(l+31+2+1);
6037 archive_set_error(&a->archive, ENOMEM,
6038 "Can't allocate memory");
6039 return (ARCHIVE_FATAL);
6041 memcpy(p, np->file->basename.s, l);
6048 * If there is a '.' character at the first byte,
6049 * it has to be replaced by '_' character.
6059 if (char_map[(unsigned char)*p]) {
6060 /* if iso-level is '4', a character '.' is
6061 * allowed by char_map. */
6068 if (*p >= 'a' && *p <= 'z') {
6098 ext_off = (int)(dot - p);
6100 if (iso9660->opt.iso_level == 1) {
6102 if (strlen(dot) > 4) {
6103 /* A length of a file extension
6104 * must be less than 4 */
6117 } else if (np->dir) {
6121 if (ext_off > dnmax)
6124 } else if (l > ffmax) {
6125 int extlen = (int)strlen(dot);
6129 xdoff = (int)(xdot - p);
6133 if (extlen > 1 && xdoff < fnmax-1) {
6138 off = ffmax - extlen;
6140 /* A dot('.') character
6141 * doesn't place to the first
6142 * byte of identifier. */
6146 memmove(p+off, dot, extlen);
6150 #ifdef COMPAT_MKISOFS
6151 } else if (xdoff >= fnmax-1) {
6152 /* Simulate a bug(?) of mkisofs. */
6164 /* Save an offset of a file name extension to sort files. */
6165 np->ext_off = ext_off;
6166 np->ext_len = (int)strlen(&p[ext_off]);
6167 np->id_len = l = ext_off + np->ext_len;
6169 /* Make an offset of the number which is used to be set
6170 * hexadecimal number to avoid duplicate identifier. */
6171 if (iso9660->opt.iso_level == 1) {
6179 else if (l == ffmax-1)
6181 else if (l == ffmax-2)
6186 /* Register entry to the identifier resolver. */
6187 idr_register(idr, np, weight, noff);
6190 /* Resolve duplicate identifier. */
6191 idr_resolve(idr, idr_set_num);
6193 /* Add a period and a version number to identifiers. */
6194 for (np = isoent->children.first; np != NULL; np = np->chnext) {
6195 if (!np->dir && np->rr_child == NULL) {
6196 p = np->identifier + np->ext_off + np->ext_len;
6197 if (np->ext_len == 0 && allow_period) {
6201 if (np->ext_len == 1 && !allow_period) {
6205 np->id_len = np->ext_off + np->ext_len;
6213 np->id_len = np->ext_off + np->ext_len;
6214 np->mb_len = np->id_len;
6216 return (ARCHIVE_OK);
6220 * Generate Joliet Identifier.
6223 isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent,
6226 struct iso9660 *iso9660;
6231 size_t ffmax, parent_len;
6232 static const struct archive_rb_tree_ops rb_ops = {
6233 isoent_cmp_node_joliet, isoent_cmp_key_joliet
6236 if (isoent->children.cnt == 0)
6239 iso9660 = a->format_data;
6240 if (iso9660->opt.joliet == OPT_JOLIET_LONGNAME)
6245 r = idr_start(a, idr, isoent->children.cnt, (int)ffmax, 6, 2, &rb_ops);
6250 for (np = isoent; np->parent != np; np = np->parent)
6251 parent_len += np->mb_len + 1;
6253 for (np = isoent->children.first; np != NULL; np = np->chnext) {
6255 int ext_off, noff, weight;
6258 if ((l = np->file->basename_utf16.length) > ffmax)
6261 p = malloc((l+1)*2);
6263 archive_set_error(&a->archive, ENOMEM,
6264 "Can't allocate memory");
6265 return (ARCHIVE_FATAL);
6267 memcpy(p, np->file->basename_utf16.s, l);
6271 np->identifier = (char *)p;
6276 if (!joliet_allowed_char(p[0], p[1]))
6277 archive_be16enc(p, 0x005F); /* '_' */
6278 else if (p[0] == 0 && p[1] == 0x2E) /* '.' */
6283 ext_off = (int)(dot - (unsigned char *)np->identifier);
6284 np->ext_off = ext_off;
6285 np->ext_len = (int)l - ext_off;
6286 np->id_len = (int)l;
6289 * Get a length of MBS of a full-pathname.
6291 if (np->file->basename_utf16.length > ffmax) {
6292 if (archive_strncpy_l(&iso9660->mbs,
6293 (const char *)np->identifier, l,
6294 iso9660->sconv_from_utf16be) != 0 &&
6296 archive_set_error(&a->archive, errno,
6298 return (ARCHIVE_FATAL);
6300 np->mb_len = (int)iso9660->mbs.length;
6301 if (np->mb_len != (int)np->file->basename.length)
6302 weight = np->mb_len;
6304 np->mb_len = (int)np->file->basename.length;
6306 /* If a length of full-pathname is longer than 240 bytes,
6307 * it violates Joliet extensions regulation. */
6308 if (parent_len > 240
6310 || parent_len + np->mb_len > 240) {
6311 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
6312 "The regulation of Joliet extensions;"
6313 " A length of a full-pathname of `%s' is "
6314 "longer than 240 bytes, (p=%d, b=%d)",
6315 archive_entry_pathname(np->file->entry),
6316 (int)parent_len, (int)np->mb_len);
6317 return (ARCHIVE_FATAL);
6320 /* Make an offset of the number which is used to be set
6321 * hexadecimal number to avoid duplicate identifier. */
6324 else if (l == ffmax-2)
6326 else if (l == ffmax-4)
6330 /* Register entry to the identifier resolver. */
6331 idr_register(idr, np, weight, noff);
6334 /* Resolve duplicate identifier with Joliet Volume. */
6335 idr_resolve(idr, idr_set_num_beutf16);
6337 return (ARCHIVE_OK);
6341 * This comparing rule is according to ISO9660 Standard 9.3
6344 isoent_cmp_iso9660_identifier(const struct isoent *p1, const struct isoent *p2)
6346 const char *s1, *s2;
6350 s1 = p1->identifier;
6351 s2 = p2->identifier;
6353 /* Compare File Name */
6355 if (l > p2->ext_off)
6357 cmp = memcmp(s1, s2, l);
6360 if (p1->ext_off < p2->ext_off) {
6362 l = p2->ext_off - p1->ext_off;
6366 - *(const unsigned char *)(s2 - 1));
6367 } else if (p1->ext_off > p2->ext_off) {
6369 l = p1->ext_off - p2->ext_off;
6372 return (*(const unsigned char *)(s1 - 1)
6375 /* Compare File Name Extension */
6376 if (p1->ext_len == 0 && p2->ext_len == 0)
6378 if (p1->ext_len == 1 && p2->ext_len == 1)
6380 if (p1->ext_len <= 1)
6382 if (p2->ext_len <= 1)
6385 if (l > p2->ext_len)
6387 s1 = p1->identifier + p1->ext_off;
6388 s2 = p2->identifier + p2->ext_off;
6390 cmp = memcmp(s1, s2, l);
6394 if (p1->ext_len < p2->ext_len) {
6396 l = p2->ext_len - p1->ext_len;
6400 - *(const unsigned char *)(s2 - 1));
6401 } else if (p1->ext_len > p2->ext_len) {
6403 l = p1->ext_len - p2->ext_len;
6406 return (*(const unsigned char *)(s1 - 1)
6409 /* Compare File Version Number */
6410 /* No operation. The File Version Number is always one. */
6416 isoent_cmp_node_iso9660(const struct archive_rb_node *n1,
6417 const struct archive_rb_node *n2)
6419 const struct idrent *e1 = (const struct idrent *)n1;
6420 const struct idrent *e2 = (const struct idrent *)n2;
6422 return (isoent_cmp_iso9660_identifier(e2->isoent, e1->isoent));
6426 isoent_cmp_key_iso9660(const struct archive_rb_node *node, const void *key)
6428 const struct isoent *isoent = (const struct isoent *)key;
6429 const struct idrent *idrent = (const struct idrent *)node;
6431 return (isoent_cmp_iso9660_identifier(isoent, idrent->isoent));
6435 isoent_cmp_joliet_identifier(const struct isoent *p1, const struct isoent *p2)
6437 const unsigned char *s1, *s2;
6441 s1 = (const unsigned char *)p1->identifier;
6442 s2 = (const unsigned char *)p2->identifier;
6444 /* Compare File Name */
6446 if (l > p2->ext_off)
6448 cmp = memcmp(s1, s2, l);
6451 if (p1->ext_off < p2->ext_off) {
6453 l = p2->ext_off - p1->ext_off;
6456 return (- *(const unsigned char *)(s2 - 1));
6457 } else if (p1->ext_off > p2->ext_off) {
6459 l = p1->ext_off - p2->ext_off;
6462 return (*(const unsigned char *)(s1 - 1));
6464 /* Compare File Name Extension */
6465 if (p1->ext_len == 0 && p2->ext_len == 0)
6467 if (p1->ext_len == 2 && p2->ext_len == 2)
6469 if (p1->ext_len <= 2)
6471 if (p2->ext_len <= 2)
6474 if (l > p2->ext_len)
6476 s1 = (unsigned char *)(p1->identifier + p1->ext_off);
6477 s2 = (unsigned char *)(p2->identifier + p2->ext_off);
6479 cmp = memcmp(s1, s2, l);
6483 if (p1->ext_len < p2->ext_len) {
6485 l = p2->ext_len - p1->ext_len;
6488 return (- *(const unsigned char *)(s2 - 1));
6489 } else if (p1->ext_len > p2->ext_len) {
6491 l = p1->ext_len - p2->ext_len;
6494 return (*(const unsigned char *)(s1 - 1));
6496 /* Compare File Version Number */
6497 /* No operation. The File Version Number is always one. */
6503 isoent_cmp_node_joliet(const struct archive_rb_node *n1,
6504 const struct archive_rb_node *n2)
6506 const struct idrent *e1 = (const struct idrent *)n1;
6507 const struct idrent *e2 = (const struct idrent *)n2;
6509 return (isoent_cmp_joliet_identifier(e2->isoent, e1->isoent));
6513 isoent_cmp_key_joliet(const struct archive_rb_node *node, const void *key)
6515 const struct isoent *isoent = (const struct isoent *)key;
6516 const struct idrent *idrent = (const struct idrent *)node;
6518 return (isoent_cmp_joliet_identifier(isoent, idrent->isoent));
6522 isoent_make_sorted_files(struct archive_write *a, struct isoent *isoent,
6525 struct archive_rb_node *rn;
6526 struct isoent **children;
6528 children = malloc(isoent->children.cnt * sizeof(struct isoent *));
6529 if (children == NULL) {
6530 archive_set_error(&a->archive, ENOMEM,
6531 "Can't allocate memory");
6532 return (ARCHIVE_FATAL);
6534 isoent->children_sorted = children;
6536 ARCHIVE_RB_TREE_FOREACH(rn, &(idr->rbtree)) {
6537 struct idrent *idrent = (struct idrent *)rn;
6538 *children ++ = idrent->isoent;
6540 return (ARCHIVE_OK);
6544 * - Generate ISO9660 and Joliet identifiers from basenames.
6545 * - Sort files by each directory.
6548 isoent_traverse_tree(struct archive_write *a, struct vdd* vdd)
6550 struct iso9660 *iso9660 = a->format_data;
6555 int (*genid)(struct archive_write *, struct isoent *, struct idr *);
6557 idr_init(iso9660, vdd, &idr);
6560 if (vdd->vdd_type == VDD_JOLIET)
6561 genid = isoent_gen_joliet_identifier;
6563 genid = isoent_gen_iso9660_identifier;
6566 !archive_entry_mtime_is_set(np->file->entry)) {
6567 /* Set properly times to virtual directory */
6568 archive_entry_set_mtime(np->file->entry,
6569 iso9660->birth_time, 0);
6570 archive_entry_set_atime(np->file->entry,
6571 iso9660->birth_time, 0);
6572 archive_entry_set_ctime(np->file->entry,
6573 iso9660->birth_time, 0);
6575 if (np->children.first != NULL) {
6576 if (vdd->vdd_type != VDD_JOLIET &&
6577 !iso9660->opt.rr && depth + 1 >= vdd->max_depth) {
6578 if (np->children.cnt > 0)
6579 iso9660->directories_too_deep = np;
6581 /* Generate Identifier */
6582 r = genid(a, np, &idr);
6584 goto exit_traverse_tree;
6585 r = isoent_make_sorted_files(a, np, &idr);
6587 goto exit_traverse_tree;
6589 if (np->subdirs.first != NULL &&
6590 depth + 1 < vdd->max_depth) {
6591 /* Enter to sub directories. */
6592 np = np->subdirs.first;
6598 while (np != np->parent) {
6599 if (np->drnext == NULL) {
6600 /* Return to the parent directory. */
6608 } while (np != np->parent);
6618 * Collect directory entries into path_table by a directory depth.
6621 isoent_collect_dirs(struct vdd *vdd, struct isoent *rootent, int depth)
6625 if (rootent == NULL)
6626 rootent = vdd->rootent;
6629 /* Register current directory to pathtable. */
6630 path_table_add_entry(&(vdd->pathtbl[depth]), np);
6632 if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) {
6633 /* Enter to sub directories. */
6634 np = np->subdirs.first;
6638 while (np != rootent) {
6639 if (np->drnext == NULL) {
6640 /* Return to the parent directory. */
6648 } while (np != rootent);
6650 return (ARCHIVE_OK);
6654 * The entry whose number of levels in a directory hierarchy is
6655 * large than eight relocate to rr_move directory.
6658 isoent_rr_move_dir(struct archive_write *a, struct isoent **rr_moved,
6659 struct isoent *curent, struct isoent **newent)
6661 struct iso9660 *iso9660 = a->format_data;
6662 struct isoent *rrmoved, *mvent, *np;
6664 if ((rrmoved = *rr_moved) == NULL) {
6665 struct isoent *rootent = iso9660->primary.rootent;
6666 /* There isn't rr_move entry.
6667 * Create rr_move entry and insert it into the root entry.
6669 rrmoved = isoent_create_virtual_dir(a, iso9660, "rr_moved");
6670 if (rrmoved == NULL) {
6671 archive_set_error(&a->archive, ENOMEM,
6672 "Can't allocate memory");
6673 return (ARCHIVE_FATAL);
6675 /* Add "rr_moved" entry to the root entry. */
6676 isoent_add_child_head(rootent, rrmoved);
6677 archive_entry_set_nlink(rootent->file->entry,
6678 archive_entry_nlink(rootent->file->entry) + 1);
6679 /* Register "rr_moved" entry to second level pathtable. */
6680 path_table_add_entry(&(iso9660->primary.pathtbl[1]), rrmoved);
6681 /* Save rr_moved. */
6682 *rr_moved = rrmoved;
6685 * Make a clone of curent which is going to be relocated
6688 mvent = isoent_clone(curent);
6689 if (mvent == NULL) {
6690 archive_set_error(&a->archive, ENOMEM,
6691 "Can't allocate memory");
6692 return (ARCHIVE_FATAL);
6694 /* linking.. and use for creating "CL", "PL" and "RE" */
6695 mvent->rr_parent = curent->parent;
6696 curent->rr_child = mvent;
6698 * Move subdirectories from the curent to mvent
6700 if (curent->children.first != NULL) {
6701 *mvent->children.last = curent->children.first;
6702 mvent->children.last = curent->children.last;
6704 for (np = mvent->children.first; np != NULL; np = np->chnext)
6706 mvent->children.cnt = curent->children.cnt;
6707 curent->children.cnt = 0;
6708 curent->children.first = NULL;
6709 curent->children.last = &curent->children.first;
6711 if (curent->subdirs.first != NULL) {
6712 *mvent->subdirs.last = curent->subdirs.first;
6713 mvent->subdirs.last = curent->subdirs.last;
6715 mvent->subdirs.cnt = curent->subdirs.cnt;
6716 curent->subdirs.cnt = 0;
6717 curent->subdirs.first = NULL;
6718 curent->subdirs.last = &curent->subdirs.first;
6721 * The mvent becomes a child of the rr_moved entry.
6723 isoent_add_child_tail(rrmoved, mvent);
6724 archive_entry_set_nlink(rrmoved->file->entry,
6725 archive_entry_nlink(rrmoved->file->entry) + 1);
6727 * This entry which relocated to the rr_moved directory
6728 * has to set the flag as a file.
6729 * See also RRIP 4.1.5.1 Description of the "CL" System Use Entry.
6735 return (ARCHIVE_OK);
6739 isoent_rr_move(struct archive_write *a)
6741 struct iso9660 *iso9660 = a->format_data;
6742 struct path_table *pt;
6743 struct isoent *rootent, *rr_moved;
6744 struct isoent *np, *last;
6747 pt = &(iso9660->primary.pathtbl[MAX_DEPTH-1]);
6748 /* There aren't level 8 directories reaching a deeper level. */
6750 return (ARCHIVE_OK);
6752 rootent = iso9660->primary.rootent;
6753 /* If "rr_moved" directory is already existing,
6754 * we have to use it. */
6755 rr_moved = isoent_find_child(rootent, "rr_moved");
6756 if (rr_moved != NULL &&
6757 rr_moved != rootent->children.first) {
6759 * It's necessary that rr_move is the first entry
6762 /* Remove "rr_moved" entry from children chain. */
6763 isoent_remove_child(rootent, rr_moved);
6765 /* Add "rr_moved" entry into the head of children chain. */
6766 isoent_add_child_head(rootent, rr_moved);
6770 * Check level 8 path_table.
6771 * If find out sub directory entries, that entries move to rr_move.
6774 while (np != NULL) {
6775 last = path_table_last_entry(pt);
6776 for (; np != NULL; np = np->ptnext) {
6777 struct isoent *mvent;
6778 struct isoent *newent;
6782 for (mvent = np->subdirs.first;
6783 mvent != NULL; mvent = mvent->drnext) {
6784 r = isoent_rr_move_dir(a, &rr_moved,
6788 isoent_collect_dirs(&(iso9660->primary),
6792 /* If new entries are added to level 8 path_talbe,
6793 * its sub directory entries move to rr_move too.
6798 return (ARCHIVE_OK);
6802 * This comparing rule is according to ISO9660 Standard 6.9.1
6805 _compare_path_table(const void *v1, const void *v2)
6807 const struct isoent *p1, *p2;
6808 const char *s1, *s2;
6811 p1 = *((const struct isoent **)(uintptr_t)v1);
6812 p2 = *((const struct isoent **)(uintptr_t)v2);
6814 /* Compare parent directory number */
6815 cmp = p1->parent->dir_number - p2->parent->dir_number;
6819 /* Compare identifier */
6820 s1 = p1->identifier;
6821 s2 = p2->identifier;
6823 if (l > p2->ext_off)
6825 cmp = strncmp(s1, s2, l);
6828 if (p1->ext_off < p2->ext_off) {
6830 l = p2->ext_off - p1->ext_off;
6834 - *(const unsigned char *)(s2 - 1));
6835 } else if (p1->ext_off > p2->ext_off) {
6837 l = p1->ext_off - p2->ext_off;
6840 return (*(const unsigned char *)(s1 - 1)
6847 _compare_path_table_joliet(const void *v1, const void *v2)
6849 const struct isoent *p1, *p2;
6850 const unsigned char *s1, *s2;
6853 p1 = *((const struct isoent **)(uintptr_t)v1);
6854 p2 = *((const struct isoent **)(uintptr_t)v2);
6856 /* Compare parent directory number */
6857 cmp = p1->parent->dir_number - p2->parent->dir_number;
6861 /* Compare identifier */
6862 s1 = (const unsigned char *)p1->identifier;
6863 s2 = (const unsigned char *)p2->identifier;
6865 if (l > p2->ext_off)
6867 cmp = memcmp(s1, s2, l);
6870 if (p1->ext_off < p2->ext_off) {
6872 l = p2->ext_off - p1->ext_off;
6875 return (- *(const unsigned char *)(s2 - 1));
6876 } else if (p1->ext_off > p2->ext_off) {
6878 l = p1->ext_off - p2->ext_off;
6881 return (*(const unsigned char *)(s1 - 1));
6887 path_table_add_entry(struct path_table *pathtbl, struct isoent *ent)
6890 *pathtbl->last = ent;
6891 pathtbl->last = &(ent->ptnext);
6895 static inline struct isoent *
6896 path_table_last_entry(struct path_table *pathtbl)
6898 if (pathtbl->first == NULL)
6900 return (((struct isoent *)(void *)
6901 ((char *)(pathtbl->last) - offsetof(struct isoent, ptnext))));
6905 * Sort directory entries in path_table
6906 * and assign directory number to each entries.
6909 isoent_make_path_table_2(struct archive_write *a, struct vdd *vdd,
6910 int depth, int *dir_number)
6913 struct isoent **enttbl;
6914 struct path_table *pt;
6917 pt = &vdd->pathtbl[depth];
6920 return (ARCHIVE_OK);
6922 enttbl = malloc(pt->cnt * sizeof(struct isoent *));
6923 if (enttbl == NULL) {
6924 archive_set_error(&a->archive, ENOMEM,
6925 "Can't allocate memory");
6926 return (ARCHIVE_FATAL);
6928 pt->sorted = enttbl;
6929 for (np = pt->first; np != NULL; np = np->ptnext)
6931 enttbl = pt->sorted;
6933 switch (vdd->vdd_type) {
6936 #ifdef __COMPAR_FN_T
6937 qsort(enttbl, pt->cnt, sizeof(struct isoent *),
6938 (__compar_fn_t)_compare_path_table);
6940 qsort(enttbl, pt->cnt, sizeof(struct isoent *),
6941 _compare_path_table);
6945 #ifdef __COMPAR_FN_T
6946 qsort(enttbl, pt->cnt, sizeof(struct isoent *),
6947 (__compar_fn_t)_compare_path_table_joliet);
6949 qsort(enttbl, pt->cnt, sizeof(struct isoent *),
6950 _compare_path_table_joliet);
6954 for (i = 0; i < pt->cnt; i++)
6955 enttbl[i]->dir_number = (*dir_number)++;
6957 return (ARCHIVE_OK);
6961 isoent_alloc_path_table(struct archive_write *a, struct vdd *vdd,
6966 vdd->max_depth = max_depth;
6967 vdd->pathtbl = malloc(sizeof(*vdd->pathtbl) * vdd->max_depth);
6968 if (vdd->pathtbl == NULL) {
6969 archive_set_error(&a->archive, ENOMEM,
6970 "Can't allocate memory");
6971 return (ARCHIVE_FATAL);
6973 for (i = 0; i < vdd->max_depth; i++) {
6974 vdd->pathtbl[i].first = NULL;
6975 vdd->pathtbl[i].last = &(vdd->pathtbl[i].first);
6976 vdd->pathtbl[i].sorted = NULL;
6977 vdd->pathtbl[i].cnt = 0;
6979 return (ARCHIVE_OK);
6986 isoent_make_path_table(struct archive_write *a)
6988 struct iso9660 *iso9660 = a->format_data;
6995 if (iso9660->dircnt_max >= MAX_DEPTH &&
6996 (!iso9660->opt.limit_depth || iso9660->opt.iso_level == 4))
6997 r = isoent_alloc_path_table(a, &(iso9660->primary),
6998 iso9660->dircnt_max + 1);
7000 /* The number of levels in the hierarchy cannot exceed
7002 r = isoent_alloc_path_table(a, &(iso9660->primary),
7006 if (iso9660->opt.joliet) {
7007 r = isoent_alloc_path_table(a, &(iso9660->joliet),
7008 iso9660->dircnt_max + 1);
7014 * - Collect directories for primary and joliet.
7016 isoent_collect_dirs(&(iso9660->primary), NULL, 0);
7017 if (iso9660->opt.joliet)
7018 isoent_collect_dirs(&(iso9660->joliet), NULL, 0);
7020 * Rockridge; move deeper depth directories to rr_moved.
7022 if (iso9660->opt.rr) {
7023 r = isoent_rr_move(a);
7029 isofile_connect_hardlink_files(iso9660);
7032 * - Renew a value of the depth of that directories.
7033 * - Resolve hardlinks.
7034 * - Convert pathnames to ISO9660 name or UCS2(joliet).
7035 * - Sort files by each directory.
7037 r = isoent_traverse_tree(a, &(iso9660->primary));
7040 if (iso9660->opt.joliet) {
7041 r = isoent_traverse_tree(a, &(iso9660->joliet));
7047 * - Sort directories.
7048 * - Assign all directory number.
7051 for (depth = 0; depth < iso9660->primary.max_depth; depth++) {
7052 r = isoent_make_path_table_2(a, &(iso9660->primary),
7053 depth, &dir_number);
7057 if (iso9660->opt.joliet) {
7059 for (depth = 0; depth < iso9660->joliet.max_depth; depth++) {
7060 r = isoent_make_path_table_2(a, &(iso9660->joliet),
7061 depth, &dir_number);
7066 if (iso9660->opt.limit_dirs && dir_number > 0xffff) {
7068 * Maximum number of directories is 65535(0xffff)
7069 * doe to size(16bit) of Parent Directory Number of
7071 * See also ISO9660 Standard 9.4.
7073 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7074 "Too many directories(%d) over 65535.", dir_number);
7075 return (ARCHIVE_FATAL);
7078 /* Get the size of the Path Table. */
7079 calculate_path_table_size(&(iso9660->primary));
7080 if (iso9660->opt.joliet)
7081 calculate_path_table_size(&(iso9660->joliet));
7083 return (ARCHIVE_OK);
7087 isoent_find_out_boot_file(struct archive_write *a, struct isoent *rootent)
7089 struct iso9660 *iso9660 = a->format_data;
7091 /* Find a isoent of the boot file. */
7092 iso9660->el_torito.boot = isoent_find_entry(rootent,
7093 iso9660->el_torito.boot_filename.s);
7094 if (iso9660->el_torito.boot == NULL) {
7095 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7096 "Can't find the boot image file ``%s''",
7097 iso9660->el_torito.boot_filename.s);
7098 return (ARCHIVE_FATAL);
7100 iso9660->el_torito.boot->file->boot = BOOT_IMAGE;
7101 return (ARCHIVE_OK);
7105 isoent_create_boot_catalog(struct archive_write *a, struct isoent *rootent)
7107 struct iso9660 *iso9660 = a->format_data;
7108 struct isofile *file;
7109 struct isoent *isoent;
7110 struct archive_entry *entry;
7112 (void)rootent; /* UNUSED */
7114 * Create the entry which is the "boot.catalog" file.
7116 file = isofile_new(a, NULL);
7118 archive_set_error(&a->archive, ENOMEM,
7119 "Can't allocate memory");
7120 return (ARCHIVE_FATAL);
7122 archive_entry_set_pathname(file->entry,
7123 iso9660->el_torito.catalog_filename.s);
7124 archive_entry_set_size(file->entry, LOGICAL_BLOCK_SIZE);
7125 archive_entry_set_mtime(file->entry, iso9660->birth_time, 0);
7126 archive_entry_set_atime(file->entry, iso9660->birth_time, 0);
7127 archive_entry_set_ctime(file->entry, iso9660->birth_time, 0);
7128 archive_entry_set_uid(file->entry, getuid());
7129 archive_entry_set_gid(file->entry, getgid());
7130 archive_entry_set_mode(file->entry, AE_IFREG | 0444);
7131 archive_entry_set_nlink(file->entry, 1);
7133 if (isofile_gen_utility_names(a, file) < ARCHIVE_WARN) {
7135 return (ARCHIVE_FATAL);
7137 file->boot = BOOT_CATALOG;
7138 file->content.size = LOGICAL_BLOCK_SIZE;
7139 isofile_add_entry(iso9660, file);
7141 isoent = isoent_new(file);
7142 if (isoent == NULL) {
7143 archive_set_error(&a->archive, ENOMEM,
7144 "Can't allocate memory");
7145 return (ARCHIVE_FATAL);
7147 isoent->virtual = 1;
7149 /* Add the "boot.catalog" entry into tree */
7150 if (isoent_tree(a, &isoent) != ARCHIVE_OK)
7151 return (ARCHIVE_FATAL);
7153 iso9660->el_torito.catalog = isoent;
7155 * Get a boot media type.
7157 switch (iso9660->opt.boot_type) {
7159 case OPT_BOOT_TYPE_AUTO:
7160 /* Try detecting a media type of the boot image. */
7161 entry = iso9660->el_torito.boot->file->entry;
7162 if (archive_entry_size(entry) == FD_1_2M_SIZE)
7163 iso9660->el_torito.media_type =
7164 BOOT_MEDIA_1_2M_DISKETTE;
7165 else if (archive_entry_size(entry) == FD_1_44M_SIZE)
7166 iso9660->el_torito.media_type =
7167 BOOT_MEDIA_1_44M_DISKETTE;
7168 else if (archive_entry_size(entry) == FD_2_88M_SIZE)
7169 iso9660->el_torito.media_type =
7170 BOOT_MEDIA_2_88M_DISKETTE;
7172 /* We cannot decide whether the boot image is
7174 iso9660->el_torito.media_type =
7175 BOOT_MEDIA_NO_EMULATION;
7177 case OPT_BOOT_TYPE_NO_EMU:
7178 iso9660->el_torito.media_type = BOOT_MEDIA_NO_EMULATION;
7180 case OPT_BOOT_TYPE_HARD_DISK:
7181 iso9660->el_torito.media_type = BOOT_MEDIA_HARD_DISK;
7183 case OPT_BOOT_TYPE_FD:
7184 entry = iso9660->el_torito.boot->file->entry;
7185 if (archive_entry_size(entry) <= FD_1_2M_SIZE)
7186 iso9660->el_torito.media_type =
7187 BOOT_MEDIA_1_2M_DISKETTE;
7188 else if (archive_entry_size(entry) <= FD_1_44M_SIZE)
7189 iso9660->el_torito.media_type =
7190 BOOT_MEDIA_1_44M_DISKETTE;
7191 else if (archive_entry_size(entry) <= FD_2_88M_SIZE)
7192 iso9660->el_torito.media_type =
7193 BOOT_MEDIA_2_88M_DISKETTE;
7195 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7196 "Boot image file(``%s'') size is too big "
7198 iso9660->el_torito.boot_filename.s);
7199 return (ARCHIVE_FATAL);
7205 * Get a system type.
7206 * TODO: `El Torito' specification says "A copy of byte 5 from the
7207 * Partition Table found in the boot image".
7209 iso9660->el_torito.system_type = 0;
7214 if (iso9660->opt.publisher)
7215 archive_string_copy(&(iso9660->el_torito.id),
7216 &(iso9660->publisher_identifier));
7219 return (ARCHIVE_OK);
7223 * If a media type is floppy, return its image size.
7224 * otherwise return 0.
7227 fd_boot_image_size(int media_type)
7229 switch (media_type) {
7230 case BOOT_MEDIA_1_2M_DISKETTE:
7231 return (FD_1_2M_SIZE);
7232 case BOOT_MEDIA_1_44M_DISKETTE:
7233 return (FD_1_44M_SIZE);
7234 case BOOT_MEDIA_2_88M_DISKETTE:
7235 return (FD_2_88M_SIZE);
7242 * Make a boot catalog image data.
7245 make_boot_catalog(struct archive_write *a)
7247 struct iso9660 *iso9660 = a->format_data;
7248 unsigned char *block;
7252 block = wb_buffptr(a);
7253 memset(block, 0, LOGICAL_BLOCK_SIZE);
7261 p[1] = iso9660->el_torito.platform_id;
7265 if (archive_strlen(&(iso9660->el_torito.id)) > 0)
7266 strncpy((char *)p+4, iso9660->el_torito.id.s, 23);
7275 wp = (uint16_t *)block;
7276 while (wp < (uint16_t *)&block[32])
7277 sum += archive_le16dec(wp++);
7278 set_num_721(&block[28], (~sum) + 1);
7281 * Initial/Default Entry
7284 /* Boot Indicator */
7286 /* Boot media type */
7287 p[1] = iso9660->el_torito.media_type;
7289 if (iso9660->el_torito.media_type == BOOT_MEDIA_NO_EMULATION)
7290 set_num_721(&p[2], iso9660->el_torito.boot_load_seg);
7292 set_num_721(&p[2], 0);
7294 p[4] = iso9660->el_torito.system_type;
7298 if (iso9660->el_torito.media_type == BOOT_MEDIA_NO_EMULATION)
7299 set_num_721(&p[6], iso9660->el_torito.boot_load_size);
7301 set_num_721(&p[6], 1);
7304 iso9660->el_torito.boot->file->content.location);
7306 memset(&p[12], 0, 20);
7308 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
7312 setup_boot_information(struct archive_write *a)
7314 struct iso9660 *iso9660 = a->format_data;
7318 unsigned char buff[4096];
7320 np = iso9660->el_torito.boot;
7321 lseek(iso9660->temp_fd,
7322 np->file->content.offset_of_temp + 64, SEEK_SET);
7323 size = archive_entry_size(np->file->entry) - 64;
7325 archive_set_error(&a->archive, errno,
7326 "Boot file(%jd) is too small", (intmax_t)size + 64);
7327 return (ARCHIVE_FATAL);
7334 if (size > (int64_t)sizeof(buff))
7335 rsize = sizeof(buff);
7337 rsize = (size_t)size;
7339 rs = read(iso9660->temp_fd, buff, rsize);
7341 archive_set_error(&a->archive, errno,
7342 "Can't read temporary file(%jd)",
7344 return (ARCHIVE_FATAL);
7346 for (i = 0; i < rs; i += 4)
7347 sum += archive_le32dec(buff + i);
7350 /* Set the location of Primary Volume Descriptor. */
7351 set_num_731(buff, SYSTEM_AREA_BLOCK);
7352 /* Set the location of the boot file. */
7353 set_num_731(buff+4, np->file->content.location);
7354 /* Set the size of the boot file. */
7355 size = fd_boot_image_size(iso9660->el_torito.media_type);
7357 size = archive_entry_size(np->file->entry);
7358 set_num_731(buff+8, (uint32_t)size);
7359 /* Set the sum of the boot file. */
7360 set_num_731(buff+12, sum);
7361 /* Clear reserved bytes. */
7362 memset(buff+16, 0, 40);
7364 /* Overwrite the boot file. */
7365 lseek(iso9660->temp_fd,
7366 np->file->content.offset_of_temp + 8, SEEK_SET);
7367 return (write_to_temp(a, buff, 56));
7373 zisofs_init_zstream(struct archive_write *a)
7375 struct iso9660 *iso9660 = a->format_data;
7378 iso9660->zisofs.stream.next_in = NULL;
7379 iso9660->zisofs.stream.avail_in = 0;
7380 iso9660->zisofs.stream.total_in = 0;
7381 iso9660->zisofs.stream.total_out = 0;
7382 if (iso9660->zisofs.stream_valid)
7383 r = deflateReset(&(iso9660->zisofs.stream));
7385 r = deflateInit(&(iso9660->zisofs.stream),
7386 iso9660->zisofs.compression_level);
7387 iso9660->zisofs.stream_valid = 1;
7393 case Z_STREAM_ERROR:
7394 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7395 "Internal error initializing "
7396 "compression library: invalid setup parameter");
7397 return (ARCHIVE_FATAL);
7399 archive_set_error(&a->archive, ENOMEM,
7400 "Internal error initializing "
7401 "compression library");
7402 return (ARCHIVE_FATAL);
7403 case Z_VERSION_ERROR:
7404 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7405 "Internal error initializing "
7406 "compression library: invalid library version");
7407 return (ARCHIVE_FATAL);
7409 return (ARCHIVE_OK);
7412 #endif /* HAVE_ZLIB_H */
7415 zisofs_init(struct archive_write *a, struct isofile *file)
7417 struct iso9660 *iso9660 = a->format_data;
7420 size_t _ceil, bpsize;
7424 iso9660->zisofs.detect_magic = 0;
7425 iso9660->zisofs.making = 0;
7427 if (!iso9660->opt.rr || !iso9660->opt.zisofs)
7428 return (ARCHIVE_OK);
7430 if (archive_entry_size(file->entry) >= 24 &&
7431 archive_entry_size(file->entry) < MULTI_EXTENT_SIZE) {
7432 /* Acceptable file size for zisofs. */
7433 iso9660->zisofs.detect_magic = 1;
7434 iso9660->zisofs.magic_cnt = 0;
7436 if (!iso9660->zisofs.detect_magic)
7437 return (ARCHIVE_OK);
7440 /* The number of Logical Blocks which uncompressed data
7441 * will use in iso-image file is the same as the number of
7442 * Logical Blocks which zisofs(compressed) data will use
7443 * in ISO-image file. It won't reduce iso-image file size. */
7444 if (archive_entry_size(file->entry) <= LOGICAL_BLOCK_SIZE)
7445 return (ARCHIVE_OK);
7447 /* Initialize compression library */
7448 r = zisofs_init_zstream(a);
7449 if (r != ARCHIVE_OK)
7450 return (ARCHIVE_FATAL);
7452 /* Mark file->zisofs to create RRIP 'ZF' Use Entry. */
7453 file->zisofs.header_size = ZF_HEADER_SIZE >> 2;
7454 file->zisofs.log2_bs = ZF_LOG2_BS;
7455 file->zisofs.uncompressed_size =
7456 (uint32_t)archive_entry_size(file->entry);
7458 /* Calculate a size of Block Pointers of zisofs. */
7459 _ceil = (file->zisofs.uncompressed_size + ZF_BLOCK_SIZE -1)
7460 >> file->zisofs.log2_bs;
7461 iso9660->zisofs.block_pointers_cnt = (int)_ceil + 1;
7462 iso9660->zisofs.block_pointers_idx = 0;
7464 /* Ensure a buffer size used for Block Pointers */
7465 bpsize = iso9660->zisofs.block_pointers_cnt *
7466 sizeof(iso9660->zisofs.block_pointers[0]);
7467 if (iso9660->zisofs.block_pointers_allocated < bpsize) {
7468 free(iso9660->zisofs.block_pointers);
7469 iso9660->zisofs.block_pointers = malloc(bpsize);
7470 if (iso9660->zisofs.block_pointers == NULL) {
7471 archive_set_error(&a->archive, ENOMEM,
7472 "Can't allocate data");
7473 return (ARCHIVE_FATAL);
7475 iso9660->zisofs.block_pointers_allocated = bpsize;
7479 * Skip zisofs header and Block Pointers, which we will write
7480 * after all compressed data of a file written to the temporary
7483 tsize = ZF_HEADER_SIZE + bpsize;
7484 if (write_null(a, (size_t)tsize) != ARCHIVE_OK)
7485 return (ARCHIVE_FATAL);
7488 * Initialize some variables to make zisofs.
7490 archive_le32enc(&(iso9660->zisofs.block_pointers[0]),
7492 iso9660->zisofs.remaining = file->zisofs.uncompressed_size;
7493 iso9660->zisofs.making = 1;
7494 iso9660->zisofs.allzero = 1;
7495 iso9660->zisofs.block_offset = tsize;
7496 iso9660->zisofs.total_size = tsize;
7497 iso9660->cur_file->cur_content->size = tsize;
7500 return (ARCHIVE_OK);
7504 zisofs_detect_magic(struct archive_write *a, const void *buff, size_t s)
7506 struct iso9660 *iso9660 = a->format_data;
7507 struct isofile *file = iso9660->cur_file;
7508 const unsigned char *p, *endp;
7509 const unsigned char *magic_buff;
7510 uint32_t uncompressed_size;
7511 unsigned char header_size;
7512 unsigned char log2_bs;
7518 entry_size = archive_entry_size(file->entry);
7519 if ((int64_t)sizeof(iso9660->zisofs.magic_buffer) > entry_size)
7520 magic_max = (int)entry_size;
7522 magic_max = sizeof(iso9660->zisofs.magic_buffer);
7524 if (iso9660->zisofs.magic_cnt == 0 && s >= (size_t)magic_max)
7525 /* It's unnecessary we copy buffer. */
7528 if (iso9660->zisofs.magic_cnt < magic_max) {
7531 l = sizeof(iso9660->zisofs.magic_buffer)
7532 - iso9660->zisofs.magic_cnt;
7535 memcpy(iso9660->zisofs.magic_buffer
7536 + iso9660->zisofs.magic_cnt, buff, l);
7537 iso9660->zisofs.magic_cnt += (int)l;
7538 if (iso9660->zisofs.magic_cnt < magic_max)
7541 magic_buff = iso9660->zisofs.magic_buffer;
7543 iso9660->zisofs.detect_magic = 0;
7546 /* Check the magic code of zisofs. */
7547 if (memcmp(p, zisofs_magic, sizeof(zisofs_magic)) != 0)
7548 /* This is not zisofs file which made by mkzftree. */
7550 p += sizeof(zisofs_magic);
7552 /* Read a zisofs header. */
7553 uncompressed_size = archive_le32dec(p);
7556 if (uncompressed_size < 24 || header_size != 4 ||
7557 log2_bs > 30 || log2_bs < 7)
7558 return;/* Invalid or not supported header. */
7560 /* Calculate a size of Block Pointers of zisofs. */
7561 _ceil = (uncompressed_size +
7562 (ARCHIVE_LITERAL_LL(1) << log2_bs) -1) >> log2_bs;
7563 doff = (_ceil + 1) * 4 + 16;
7564 if (entry_size < (int64_t)doff)
7565 return;/* Invalid data. */
7567 /* Check every Block Pointer has valid value. */
7568 p = magic_buff + 16;
7569 endp = magic_buff + magic_max;
7570 while (_ceil && p + 8 <= endp) {
7571 bst = archive_le32dec(p);
7573 return;/* Invalid data. */
7575 bed = archive_le32dec(p);
7576 if (bed < bst || bed > entry_size)
7577 return;/* Invalid data. */
7582 file->zisofs.uncompressed_size = uncompressed_size;
7583 file->zisofs.header_size = header_size;
7584 file->zisofs.log2_bs = log2_bs;
7586 /* Disable making a zisofs image. */
7587 iso9660->zisofs.making = 0;
7593 * Compress data and write it to a temporary file.
7596 zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s)
7598 struct iso9660 *iso9660 = a->format_data;
7599 struct isofile *file = iso9660->cur_file;
7600 const unsigned char *b;
7602 size_t avail, csize;
7605 zstrm = &(iso9660->zisofs.stream);
7606 zstrm->next_out = wb_buffptr(a);
7607 zstrm->avail_out = (uInt)wb_remaining(a);
7608 b = (const unsigned char *)buff;
7610 avail = ZF_BLOCK_SIZE - zstrm->total_in;
7616 iso9660->zisofs.remaining -= avail;
7617 if (iso9660->zisofs.remaining <= 0)
7620 zstrm->next_in = (Bytef *)(uintptr_t)(const void *)b;
7621 zstrm->avail_in = (uInt)avail;
7624 * Check if current data block are all zero.
7626 if (iso9660->zisofs.allzero) {
7627 const unsigned char *nonzero = b;
7628 const unsigned char *nonzeroend = b + avail;
7630 while (nonzero < nonzeroend)
7632 iso9660->zisofs.allzero = 0;
7640 * If current data block are all zero, we do not use
7643 if (flush == Z_FINISH && iso9660->zisofs.allzero &&
7644 avail + zstrm->total_in == ZF_BLOCK_SIZE) {
7645 if (iso9660->zisofs.block_offset !=
7646 file->cur_content->size) {
7649 r = wb_set_offset(a,
7650 file->cur_content->offset_of_temp +
7651 iso9660->zisofs.block_offset);
7652 if (r != ARCHIVE_OK)
7654 diff = file->cur_content->size -
7655 iso9660->zisofs.block_offset;
7656 file->cur_content->size -= diff;
7657 iso9660->zisofs.total_size -= diff;
7659 zstrm->avail_in = 0;
7663 * Compress file data.
7665 while (zstrm->avail_in > 0) {
7666 csize = zstrm->total_out;
7667 r = deflate(zstrm, flush);
7671 csize = zstrm->total_out - csize;
7672 if (wb_consume(a, csize) != ARCHIVE_OK)
7673 return (ARCHIVE_FATAL);
7674 iso9660->zisofs.total_size += csize;
7675 iso9660->cur_file->cur_content->size += csize;
7676 zstrm->next_out = wb_buffptr(a);
7677 zstrm->avail_out = (uInt)wb_remaining(a);
7680 archive_set_error(&a->archive,
7682 "Compression failed:"
7683 " deflate() call returned status %d",
7685 return (ARCHIVE_FATAL);
7689 if (flush == Z_FINISH) {
7691 * Save the information of one zisofs block.
7693 iso9660->zisofs.block_pointers_idx ++;
7694 archive_le32enc(&(iso9660->zisofs.block_pointers[
7695 iso9660->zisofs.block_pointers_idx]),
7696 (uint32_t)iso9660->zisofs.total_size);
7697 r = zisofs_init_zstream(a);
7698 if (r != ARCHIVE_OK)
7699 return (ARCHIVE_FATAL);
7700 iso9660->zisofs.allzero = 1;
7701 iso9660->zisofs.block_offset = file->cur_content->size;
7705 return (ARCHIVE_OK);
7709 zisofs_finish_entry(struct archive_write *a)
7711 struct iso9660 *iso9660 = a->format_data;
7712 struct isofile *file = iso9660->cur_file;
7713 unsigned char buff[16];
7717 /* Direct temp file stream to zisofs temp file stream. */
7718 archive_entry_set_size(file->entry, iso9660->zisofs.total_size);
7721 * Save a file pointer which points the end of current zisofs data.
7723 tail = wb_offset(a);
7728 * +-----------------+----------------+-----------------+
7729 * | Header 16 bytes | Block Pointers | Compressed data |
7730 * +-----------------+----------------+-----------------+
7733 * 4 * (((Uncompressed file size + block_size -1) / block_size) + 1)
7735 * Write zisofs header.
7737 * +----+----+----+----+----+----+----+----+
7738 * | 37 | E4 | 53 | 96 | C9 | DB | D6 | 07 |
7739 * +----+----+----+----+----+----+----+----+
7742 * +------------------------+------------------+
7743 * | Uncompressed file size | header_size >> 2 |
7744 * +------------------------+------------------+
7747 * +-----------------+----------------+
7748 * | log2 block_size | Reserved(0000) |
7749 * +-----------------+----------------+
7752 memcpy(buff, zisofs_magic, 8);
7753 set_num_731(buff+8, file->zisofs.uncompressed_size);
7754 buff[12] = file->zisofs.header_size;
7755 buff[13] = file->zisofs.log2_bs;
7756 buff[14] = buff[15] = 0;/* Reserved */
7758 /* Move to the right position to write the header. */
7759 wb_set_offset(a, file->content.offset_of_temp);
7761 /* Write the header. */
7762 if (wb_write_to_temp(a, buff, 16) != ARCHIVE_OK)
7763 return (ARCHIVE_FATAL);
7766 * Write zisofs Block Pointers.
7768 s = iso9660->zisofs.block_pointers_cnt *
7769 sizeof(iso9660->zisofs.block_pointers[0]);
7770 if (wb_write_to_temp(a, iso9660->zisofs.block_pointers, s)
7772 return (ARCHIVE_FATAL);
7774 /* Set a file pointer back to the end of the temporary file. */
7775 wb_set_offset(a, tail);
7777 return (ARCHIVE_OK);
7781 zisofs_free(struct archive_write *a)
7783 struct iso9660 *iso9660 = a->format_data;
7784 int ret = ARCHIVE_OK;
7786 free(iso9660->zisofs.block_pointers);
7787 if (iso9660->zisofs.stream_valid &&
7788 deflateEnd(&(iso9660->zisofs.stream)) != Z_OK) {
7789 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7790 "Failed to clean up compressor");
7791 ret = ARCHIVE_FATAL;
7793 iso9660->zisofs.block_pointers = NULL;
7794 iso9660->zisofs.stream_valid = 0;
7798 struct zisofs_extract {
7799 int pz_log2_bs; /* Log2 of block size */
7800 uint64_t pz_uncompressed_size;
7801 size_t uncompressed_buffer_size;
7803 signed int initialized:1;
7804 signed int header_passed:1;
7807 unsigned char *block_pointers;
7808 size_t block_pointers_size;
7809 size_t block_pointers_avail;
7811 uint32_t block_avail;
7818 zisofs_extract_init(struct archive_write *a, struct zisofs_extract *zisofs,
7819 const unsigned char *p, size_t bytes)
7821 size_t avail = bytes;
7822 size_t _ceil, xsize;
7824 /* Allocate block pointers buffer. */
7825 _ceil = (size_t)((zisofs->pz_uncompressed_size +
7826 (((int64_t)1) << zisofs->pz_log2_bs) - 1)
7827 >> zisofs->pz_log2_bs);
7828 xsize = (_ceil + 1) * 4;
7829 if (zisofs->block_pointers == NULL) {
7830 size_t alloc = ((xsize >> 10) + 1) << 10;
7831 zisofs->block_pointers = malloc(alloc);
7832 if (zisofs->block_pointers == NULL) {
7833 archive_set_error(&a->archive, ENOMEM,
7834 "No memory for zisofs decompression");
7835 return (ARCHIVE_FATAL);
7838 zisofs->block_pointers_size = xsize;
7840 /* Allocate uncompressed data buffer. */
7841 zisofs->uncompressed_buffer_size = (size_t)1UL << zisofs->pz_log2_bs;
7844 * Read the file header, and check the magic code of zisofs.
7846 if (!zisofs->header_passed) {
7849 archive_set_error(&a->archive,
7850 ARCHIVE_ERRNO_FILE_FORMAT,
7851 "Illegal zisofs file body");
7852 return (ARCHIVE_FATAL);
7855 if (memcmp(p, zisofs_magic, sizeof(zisofs_magic)) != 0)
7857 else if (archive_le32dec(p + 8) != zisofs->pz_uncompressed_size)
7859 else if (p[12] != 4 || p[13] != zisofs->pz_log2_bs)
7862 archive_set_error(&a->archive,
7863 ARCHIVE_ERRNO_FILE_FORMAT,
7864 "Illegal zisofs file body");
7865 return (ARCHIVE_FATAL);
7869 zisofs->header_passed = 1;
7873 * Read block pointers.
7875 if (zisofs->header_passed &&
7876 zisofs->block_pointers_avail < zisofs->block_pointers_size) {
7877 xsize = zisofs->block_pointers_size
7878 - zisofs->block_pointers_avail;
7881 memcpy(zisofs->block_pointers
7882 + zisofs->block_pointers_avail, p, xsize);
7883 zisofs->block_pointers_avail += xsize;
7885 if (zisofs->block_pointers_avail
7886 == zisofs->block_pointers_size) {
7887 /* We've got all block pointers and initialize
7888 * related variables. */
7889 zisofs->block_off = 0;
7890 zisofs->block_avail = 0;
7891 /* Complete a initialization */
7892 zisofs->initialized = 1;
7895 return ((ssize_t)avail);
7899 zisofs_extract(struct archive_write *a, struct zisofs_extract *zisofs,
7900 const unsigned char *p, size_t bytes)
7905 if (!zisofs->initialized) {
7906 ssize_t rs = zisofs_extract_init(a, zisofs, p, bytes);
7909 if (!zisofs->initialized) {
7910 /* We need more data. */
7911 zisofs->pz_offset += (uint32_t)bytes;
7920 * Get block offsets from block pointers.
7922 if (zisofs->block_avail == 0) {
7925 if (zisofs->block_off + 4 >= zisofs->block_pointers_size) {
7926 /* There isn't a pair of offsets. */
7927 archive_set_error(&a->archive,
7928 ARCHIVE_ERRNO_FILE_FORMAT,
7929 "Illegal zisofs block pointers");
7930 return (ARCHIVE_FATAL);
7932 bst = archive_le32dec(
7933 zisofs->block_pointers + zisofs->block_off);
7934 if (bst != zisofs->pz_offset + (bytes - avail)) {
7935 archive_set_error(&a->archive,
7936 ARCHIVE_ERRNO_FILE_FORMAT,
7937 "Illegal zisofs block pointers(cannot seek)");
7938 return (ARCHIVE_FATAL);
7940 bed = archive_le32dec(
7941 zisofs->block_pointers + zisofs->block_off + 4);
7943 archive_set_error(&a->archive,
7944 ARCHIVE_ERRNO_FILE_FORMAT,
7945 "Illegal zisofs block pointers");
7946 return (ARCHIVE_FATAL);
7948 zisofs->block_avail = bed - bst;
7949 zisofs->block_off += 4;
7951 /* Initialize compression library for new block. */
7952 if (zisofs->stream_valid)
7953 r = inflateReset(&zisofs->stream);
7955 r = inflateInit(&zisofs->stream);
7957 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7958 "Can't initialize zisofs decompression.");
7959 return (ARCHIVE_FATAL);
7961 zisofs->stream_valid = 1;
7962 zisofs->stream.total_in = 0;
7963 zisofs->stream.total_out = 0;
7967 * Make uncompressed data.
7969 if (zisofs->block_avail == 0) {
7971 * It's basically 32K bytes NUL data.
7976 size = zisofs->uncompressed_buffer_size;
7979 if (size > wb_remaining(a))
7980 wsize = wb_remaining(a);
7983 memset(wb, 0, wsize);
7984 r = wb_consume(a, wsize);
7990 zisofs->stream.next_in = (Bytef *)(uintptr_t)(const void *)p;
7991 if (avail > zisofs->block_avail)
7992 zisofs->stream.avail_in = zisofs->block_avail;
7994 zisofs->stream.avail_in = (uInt)avail;
7995 zisofs->stream.next_out = wb_buffptr(a);
7996 zisofs->stream.avail_out = (uInt)wb_remaining(a);
7998 r = inflate(&zisofs->stream, 0);
8000 case Z_OK: /* Decompressor made some progress.*/
8001 case Z_STREAM_END: /* Found end of stream. */
8004 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
8005 "zisofs decompression failed (%d)", r);
8006 return (ARCHIVE_FATAL);
8008 avail -= zisofs->stream.next_in - p;
8009 zisofs->block_avail -= (uint32_t)(zisofs->stream.next_in - p);
8010 r = wb_consume(a, wb_remaining(a) - zisofs->stream.avail_out);
8014 zisofs->pz_offset += (uint32_t)bytes;
8015 return (bytes - avail);
8019 zisofs_rewind_boot_file(struct archive_write *a)
8021 struct iso9660 *iso9660 = a->format_data;
8022 struct isofile *file;
8023 unsigned char *rbuff;
8025 size_t remaining, rbuff_size;
8026 struct zisofs_extract zext;
8027 int64_t read_offset, write_offset, new_offset;
8028 int fd, ret = ARCHIVE_OK;
8030 file = iso9660->el_torito.boot->file;
8032 * There is nothing to do if this boot file does not have
8035 if (file->zisofs.header_size == 0)
8036 return (ARCHIVE_OK);
8039 * Uncompress the zisofs'ed file contents.
8041 memset(&zext, 0, sizeof(zext));
8042 zext.pz_uncompressed_size = file->zisofs.uncompressed_size;
8043 zext.pz_log2_bs = file->zisofs.log2_bs;
8045 fd = iso9660->temp_fd;
8046 new_offset = wb_offset(a);
8047 read_offset = file->content.offset_of_temp;
8048 remaining = (size_t)file->content.size;
8049 if (remaining > 1024 * 32)
8050 rbuff_size = 1024 * 32;
8052 rbuff_size = remaining;
8054 rbuff = malloc(rbuff_size);
8055 if (rbuff == NULL) {
8056 archive_set_error(&a->archive, ENOMEM, "Can't allocate memory");
8057 return (ARCHIVE_FATAL);
8063 /* Get the current file pointer. */
8064 write_offset = lseek(fd, 0, SEEK_CUR);
8066 /* Change the file pointer to read. */
8067 lseek(fd, read_offset, SEEK_SET);
8070 if (rsize > remaining)
8072 rs = read(iso9660->temp_fd, rbuff, rsize);
8074 archive_set_error(&a->archive, errno,
8075 "Can't read temporary file(%jd)", (intmax_t)rs);
8076 ret = ARCHIVE_FATAL;
8082 /* Put the file pointer back to write. */
8083 lseek(fd, write_offset, SEEK_SET);
8085 r = zisofs_extract(a, &zext, rbuff, rs);
8092 if (ret == ARCHIVE_OK) {
8094 * Change the boot file content from zisofs'ed data
8097 file->content.offset_of_temp = new_offset;
8098 file->content.size = file->zisofs.uncompressed_size;
8099 archive_entry_set_size(file->entry, file->content.size);
8100 /* Set to be no zisofs. */
8101 file->zisofs.header_size = 0;
8102 file->zisofs.log2_bs = 0;
8103 file->zisofs.uncompressed_size = 0;
8104 r = wb_write_padding_to_temp(a, file->content.size);
8106 ret = ARCHIVE_FATAL;
8110 * Free the resource we used in this function only.
8113 free(zext.block_pointers);
8114 if (zext.stream_valid && inflateEnd(&(zext.stream)) != Z_OK) {
8115 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
8116 "Failed to clean up compressor");
8117 ret = ARCHIVE_FATAL;
8126 zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s)
8128 (void)buff; /* UNUSED */
8129 (void)s; /* UNUSED */
8130 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Programming error");
8131 return (ARCHIVE_FATAL);
8135 zisofs_rewind_boot_file(struct archive_write *a)
8137 struct iso9660 *iso9660 = a->format_data;
8139 if (iso9660->el_torito.boot->file->zisofs.header_size != 0) {
8140 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
8141 "We cannot extract the zisofs imaged boot file;"
8142 " this may not boot in being zisofs imaged");
8143 return (ARCHIVE_FAILED);
8145 return (ARCHIVE_OK);
8149 zisofs_finish_entry(struct archive_write *a)
8151 (void)a; /* UNUSED */
8152 return (ARCHIVE_OK);
8156 zisofs_free(struct archive_write *a)
8158 (void)a; /* UNUSED */
8159 return (ARCHIVE_OK);
8162 #endif /* HAVE_ZLIB_H */