2 * Copyright (c) 2009-2012 Michihiro NAKAJIMA
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include "archive_platform.h"
28 #ifdef HAVE_SYS_TYPES_H
29 #include <sys/types.h>
31 #ifdef HAVE_SYS_UTSNAME_H
32 #include <sys/utsname.h>
54 #include "archive_endian.h"
55 #include "archive_entry.h"
56 #include "archive_entry_locale.h"
57 #include "archive_private.h"
58 #include "archive_rb.h"
59 #include "archive_write_private.h"
61 #if defined(_WIN32) && !defined(__CYGWIN__)
68 /* To compare to the ISO image file made by mkisofs. */
69 #define COMPAT_MKISOFS 1
72 #define LOGICAL_BLOCK_BITS 11
73 #define LOGICAL_BLOCK_SIZE 2048
74 #define PATH_TABLE_BLOCK_SIZE 4096
76 #define SYSTEM_AREA_BLOCK 16
77 #define PRIMARY_VOLUME_DESCRIPTOR_BLOCK 1
78 #define SUPPLEMENTARY_VOLUME_DESCRIPTOR_BLOCK 1
79 #define BOOT_RECORD_DESCRIPTOR_BLOCK 1
80 #define VOLUME_DESCRIPTOR_SET_TERMINATOR_BLOCK 1
81 #define NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK 1
82 #define RRIP_ER_BLOCK 1
83 #define PADDING_BLOCK 150
85 #define FD_1_2M_SIZE (1024 * 1200)
86 #define FD_1_44M_SIZE (1024 * 1440)
87 #define FD_2_88M_SIZE (1024 * 2880)
88 #define MULTI_EXTENT_SIZE (ARCHIVE_LITERAL_LL(1) << 32) /* 4Gi bytes. */
90 #define RR_CE_SIZE 28 /* SUSP "CE" extension size */
92 #define FILE_FLAG_EXISTENCE 0x01
93 #define FILE_FLAG_DIRECTORY 0x02
94 #define FILE_FLAG_ASSOCIATED 0x04
95 #define FILE_FLAG_RECORD 0x08
96 #define FILE_FLAG_PROTECTION 0x10
97 #define FILE_FLAG_MULTI_EXTENT 0x80
99 static const char rrip_identifier[] =
101 static const char rrip_descriptor[] =
102 "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR "
103 "POSIX FILE SYSTEM SEMANTICS";
104 static const char rrip_source[] =
105 "PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. "
106 "SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR "
107 "CONTACT INFORMATION.";
108 #define RRIP_ER_ID_SIZE (sizeof(rrip_identifier)-1)
109 #define RRIP_ER_DSC_SIZE (sizeof(rrip_descriptor)-1)
110 #define RRIP_ER_SRC_SIZE (sizeof(rrip_source)-1)
111 #define RRIP_ER_SIZE (8 + RRIP_ER_ID_SIZE + \
112 RRIP_ER_DSC_SIZE + RRIP_ER_SRC_SIZE)
114 static const unsigned char zisofs_magic[8] = {
115 0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07
118 #define ZF_HEADER_SIZE 16 /* zisofs header size. */
119 #define ZF_LOG2_BS 15 /* log2 block size; 32K bytes. */
120 #define ZF_BLOCK_SIZE (1UL << ZF_LOG2_BS)
123 * Manage extra records.
128 unsigned char buf[LOGICAL_BLOCK_SIZE];
129 struct extr_rec *next;
132 struct ctl_extr_rec {
135 struct isoent *isoent;
136 unsigned char *ce_ptr;
143 #define DR_SAFETY RR_CE_SIZE
144 #define DR_LIMIT (254 - DR_SAFETY)
147 * The relation of struct isofile and isoent and archive_entry.
149 * Primary volume tree --> struct isoent
152 * struct isofile --> archive_entry
155 * Joliet volume tree --> struct isoent
157 * struct isoent has specific information for volume.
161 /* Used for managing struct isofile list. */
162 struct isofile *allnext;
163 struct isofile *datanext;
164 /* Used for managing a hardlined struct isofile list. */
165 struct isofile *hlnext;
166 struct isofile *hardlink_target;
168 struct archive_entry *entry;
171 * Used for making a directory tree.
173 struct archive_string parentdir;
174 struct archive_string basename;
175 struct archive_string basename_utf16;
176 struct archive_string symlink;
177 int dircnt; /* The number of elements of
178 * its parent directory */
181 * Used for a Directory Record.
184 int64_t offset_of_temp;
189 * One extent equals one content.
190 * If this entry has multi extent, `next' variable points
193 struct content *next; /* next content */
194 } content, *cur_content;
207 unsigned char header_size;
208 unsigned char log2_bs;
209 uint32_t uncompressed_size;
214 /* Keep `rbnode' at the first member of struct isoent. */
215 struct archive_rb_node rbnode;
217 struct isofile *file;
219 struct isoent *parent;
220 /* A list of children.(use chnext) */
222 struct isoent *first;
223 struct isoent **last;
226 struct archive_rb_tree rbtree;
228 /* A list of sub directories.(use drnext) */
230 struct isoent *first;
231 struct isoent **last;
234 /* A sorted list of sub directories. */
235 struct isoent **children_sorted;
236 /* Used for managing struct isoent list. */
237 struct isoent *chnext;
238 struct isoent *drnext;
239 struct isoent *ptnext;
242 * Used for making a Directory Record.
251 uint32_t dir_location;
256 * on primary, ISO9660 file/directory name.
257 * on joliet, UCS2 file/directory name.
258 * ext_off : offset of identifier extension.
259 * ext_len : length of identifier extension.
260 * id_len : byte size of identifier.
261 * on primary, this is ext_off + ext_len + version length.
262 * on joliet, this is ext_off + ext_len.
263 * mb_len : length of multibyte-character of identifier.
264 * on primary, mb_len and id_len are always the same.
265 * on joliet, mb_len and id_len are different.
274 * Used for making a Rockridge extension.
275 * This is a part of Directory Records.
277 struct isoent *rr_parent;
278 struct isoent *rr_child;
280 /* Extra Record.(which we call in this source file)
281 * A maximum size of the Directory Record is 254.
282 * so, if generated RRIP data of a file cannot into a Directory
283 * Record because of its size, that surplus data relocate this
287 struct extr_rec *first;
288 struct extr_rec **last;
289 struct extr_rec *current;
293 /* If set to one, this file type is a directory.
294 * A convenience flag to be used as
295 * "archive_entry_filetype(isoent->file->entry) == AE_IFDIR".
301 struct archive_rb_node rbnode;
304 struct isofile *first;
305 struct isofile **last;
314 * Usage : abstract-file=<value>
315 * Type : string, max 37 bytes
316 * Default: Not specified
317 * COMPAT : mkisofs -abstract <value>
319 * Specifies Abstract Filename.
320 * This file shall be described in the Root Directory
321 * and containing a abstract statement.
323 unsigned int abstract_file:1;
324 #define OPT_ABSTRACT_FILE_DEFAULT 0 /* Not specified */
325 #define ABSTRACT_FILE_SIZE 37
328 * Usage : application-id=<value>
329 * Type : string, max 128 bytes
330 * Default: Not specified
331 * COMPAT : mkisofs -A/-appid <value>.
333 * Specifies Application Identifier.
334 * If the first byte is set to '_'(5F), the remaining
335 * bytes of this option shall specify an identifier
336 * for a file containing the identification of the
338 * This file shall be described in the Root Directory.
340 unsigned int application_id:1;
341 #define OPT_APPLICATION_ID_DEFAULT 0 /* Use default identifier */
342 #define APPLICATION_IDENTIFIER_SIZE 128
345 * Usage : !allow-vernum
348 * : Violates the ISO9660 standard if disable.
351 * Allow filenames to use version numbers.
353 unsigned int allow_vernum:1;
354 #define OPT_ALLOW_VERNUM_DEFAULT 1 /* Enabled */
357 * Usage : biblio-file=<value>
358 * Type : string, max 37 bytes
359 * Default: Not specified
360 * COMPAT : mkisofs -biblio <value>
362 * Specifies Bibliographic Filename.
363 * This file shall be described in the Root Directory
364 * and containing bibliographic records.
366 unsigned int biblio_file:1;
367 #define OPT_BIBLIO_FILE_DEFAULT 0 /* Not specified */
368 #define BIBLIO_FILE_SIZE 37
371 * Usage : boot=<value>
373 * Default: Not specified
374 * COMPAT : mkisofs -b/-eltorito-boot <value>
376 * Specifies "El Torito" boot image file to make
380 #define OPT_BOOT_DEFAULT 0 /* Not specified */
383 * Usage : boot-catalog=<value>
385 * Default: "boot.catalog"
386 * COMPAT : mkisofs -c/-eltorito-catalog <value>
388 * Specifies a fullpath of El Torito boot catalog.
390 unsigned int boot_catalog:1;
391 #define OPT_BOOT_CATALOG_DEFAULT 0 /* Not specified */
394 * Usage : boot-info-table
397 * COMPAT : mkisofs -boot-info-table
399 * Modify the boot image file specified by `boot'
400 * option; ISO writer stores boot file information
401 * into the boot file in ISO image at offset 8
404 unsigned int boot_info_table:1;
405 #define OPT_BOOT_INFO_TABLE_DEFAULT 0 /* Disabled */
408 * Usage : boot-load-seg=<value>
410 * Default: Not specified
411 * COMPAT : mkisofs -boot-load-seg <value>
413 * Specifies a load segment for boot image.
414 * This is used with no-emulation mode.
416 unsigned int boot_load_seg:1;
417 #define OPT_BOOT_LOAD_SEG_DEFAULT 0 /* Not specified */
420 * Usage : boot-load-size=<value>
422 * Default: Not specified
423 * COMPAT : mkisofs -boot-load-size <value>
425 * Specifies a sector count for boot image.
426 * This is used with no-emulation mode.
428 unsigned int boot_load_size:1;
429 #define OPT_BOOT_LOAD_SIZE_DEFAULT 0 /* Not specified */
432 * Usage : boot-type=<boot-media-type>
433 * : 'no-emulation' : 'no emulation' image
434 * : 'fd' : floppy disk image
435 * : 'hard-disk' : hard disk image
437 * Default: Auto detect
438 * : We check a size of boot image;
439 * : If ths size is just 1.22M/1.44M/2.88M,
440 * : we assume boot_type is 'fd';
441 * : otherwise boot_type is 'no-emulation'.
444 * mkisofs -no-emul-boot
446 * This is a default on the mkisofs.
448 * mkisofs -hard-disk-boot
450 * Specifies a type of "El Torito" boot image.
452 unsigned int boot_type:2;
453 #define OPT_BOOT_TYPE_AUTO 0 /* auto detect */
454 #define OPT_BOOT_TYPE_NO_EMU 1 /* ``no emulation'' image */
455 #define OPT_BOOT_TYPE_FD 2 /* floppy disk image */
456 #define OPT_BOOT_TYPE_HARD_DISK 3 /* hard disk image */
457 #define OPT_BOOT_TYPE_DEFAULT OPT_BOOT_TYPE_AUTO
460 * Usage : compression-level=<value>
462 * Default: Not specified
465 * Specifies compression level for option zisofs=direct.
467 unsigned int compression_level:1;
468 #define OPT_COMPRESSION_LEVEL_DEFAULT 0 /* Not specified */
471 * Usage : copyright-file=<value>
472 * Type : string, max 37 bytes
473 * Default: Not specified
474 * COMPAT : mkisofs -copyright <value>
476 * Specifies Copyright Filename.
477 * This file shall be described in the Root Directory
478 * and containing a copyright statement.
480 unsigned int copyright_file:1;
481 #define OPT_COPYRIGHT_FILE_DEFAULT 0 /* Not specified */
482 #define COPYRIGHT_FILE_SIZE 37
485 * Usage : gid=<value>
487 * Default: Not specified
488 * COMPAT : mkisofs -gid <value>
490 * Specifies a group id to rewrite the group id of all files.
493 #define OPT_GID_DEFAULT 0 /* Not specified */
496 * Usage : iso-level=[1234]
499 * COMPAT : mkisofs -iso-level <value>
501 * Specifies ISO9600 Level.
503 * - limits each file size less than 4Gi bytes;
504 * - a File Name shall not contain more than eight
505 * d-characters or eight d1-characters;
506 * - a File Name Extension shall not contain more than
507 * three d-characters or three d1-characters;
508 * - a Directory Identifier shall not contain more
509 * than eight d-characters or eight d1-characters.
511 * - limits each file size less than 4Giga bytes;
512 * - a File Name shall not contain more than thirty
513 * d-characters or thirty d1-characters;
514 * - a File Name Extension shall not contain more than
515 * thirty d-characters or thirty d1-characters;
516 * - a Directory Identifier shall not contain more
517 * than thirty-one d-characters or thirty-one
520 * - no limit of file size; use multi extent.
522 * - this level 4 simulates mkisofs option
524 * - crate a enhanced volume as mkisofs doing;
525 * - allow a File Name to have leading dot;
526 * - allow a File Name to have all ASCII letters;
527 * - allow a File Name to have multiple dots;
528 * - allow more then 8 depths of directory trees;
529 * - disable a version number to a File Name;
530 * - disable a forced period to the tail of a File Name;
531 * - the maxinum length of files and directories is raised to 193.
532 * if rockridge option is disabled, raised to 207.
534 unsigned int iso_level:3;
535 #define OPT_ISO_LEVEL_DEFAULT 1 /* ISO Level 1 */
538 * Usage : joliet[=long]
540 * : Do not generate Joliet Volume and Records.
542 * : Generates Joliet Volume and Directory Records.
543 * : [COMPAT: mkisofs -J/-joliet]
545 * : The joliet filenames are up to 103 Unicode
547 * : This option breaks the Joliet specification.
548 * : [COMPAT: mkisofs -J -joliet-long]
549 * Type : boolean/string
551 * COMPAT : mkisofs -J / -joliet-long
553 * Generates Joliet Volume and Directory Records.
555 unsigned int joliet:2;
556 #define OPT_JOLIET_DISABLE 0 /* Not generate Joliet Records. */
557 #define OPT_JOLIET_ENABLE 1 /* Generate Joliet Records. */
558 #define OPT_JOLIET_LONGNAME 2 /* Use long joliet filenames.*/
559 #define OPT_JOLIET_DEFAULT OPT_JOLIET_ENABLE
562 * Usage : !limit-depth
565 * : Violates the ISO9660 standard if disable.
566 * COMPAT : mkisofs -D/-disable-deep-relocation
568 * The number of levels in hierarchy cannot exceed eight.
570 unsigned int limit_depth:1;
571 #define OPT_LIMIT_DEPTH_DEFAULT 1 /* Enabled */
574 * Usage : !limit-dirs
577 * : Violates the ISO9660 standard if disable.
578 * COMPAT : mkisofs -no-limit-pathtables
580 * Limits the number of directories less than 65536 due
581 * to the size of the Parent Directory Number of Path
584 unsigned int limit_dirs:1;
585 #define OPT_LIMIT_DIRS_DEFAULT 1 /* Enabled */
591 * COMPAT : -pad/-no-pad
593 * Pads the end of the ISO image by null of 300Ki bytes.
596 #define OPT_PAD_DEFAULT 1 /* Enabled */
599 * Usage : publisher=<value>
600 * Type : string, max 128 bytes
601 * Default: Not specified
602 * COMPAT : mkisofs -publisher <value>
604 * Specifies Publisher Identifier.
605 * If the first byte is set to '_'(5F), the remaining
606 * bytes of this option shall specify an identifier
607 * for a file containing the identification of the user.
608 * This file shall be described in the Root Directory.
610 unsigned int publisher:1;
611 #define OPT_PUBLISHER_DEFAULT 0 /* Not specified */
612 #define PUBLISHER_IDENTIFIER_SIZE 128
617 * : disable to generate SUSP and RR records.
619 * : the same as 'rockridge=useful'.
621 * : generate SUSP and RR records.
622 * : [COMPAT: mkisofs -R]
623 * : rockridge=useful [DEFAULT]
624 * : generate SUSP and RR records.
625 * : [COMPAT: mkisofs -r]
626 * : NOTE Our rockridge=useful option does not set a zero
627 * : to uid and gid, you should use application
628 * : option such as --gid,--gname,--uid and --uname
629 * : badtar options instead.
630 * Type : boolean/string
631 * Default: Enabled as rockridge=useful
632 * COMPAT : mkisofs -r / -R
634 * Generates SUSP and RR records.
637 #define OPT_RR_DISABLED 0
638 #define OPT_RR_STRICT 1
639 #define OPT_RR_USEFUL 2
640 #define OPT_RR_DEFAULT OPT_RR_USEFUL
643 * Usage : volume-id=<value>
644 * Type : string, max 32 bytes
645 * Default: Not specified
646 * COMPAT : mkisofs -V <value>
648 * Specifies Volume Identifier.
650 unsigned int volume_id:1;
651 #define OPT_VOLUME_ID_DEFAULT 0 /* Use default identifier */
652 #define VOLUME_IDENTIFIER_SIZE 32
655 * Usage : !zisofs [DEFAULT]
656 * : Disable to generate RRIP 'ZF' extension.
658 * : Make files zisofs file and generate RRIP 'ZF'
659 * : extension. So you do not need mkzftree utility
660 * : for making zisofs.
661 * : When the file size is less than one Logical Block
662 * : size, that file will not zisofs'ed since it does
663 * : reduece an ISO-image size.
665 * : When you specify option 'boot=<boot-image>', that
666 * : 'boot-image' file won't be converted to zisofs file.
670 * Generates RRIP 'ZF' System Use Entry.
672 unsigned int zisofs:1;
673 #define OPT_ZISOFS_DISABLED 0
674 #define OPT_ZISOFS_DIRECT 1
675 #define OPT_ZISOFS_DEFAULT OPT_ZISOFS_DISABLED
680 /* The creation time of ISO image. */
682 /* A file stream of a temporary file, which file contents
683 * save to until ISO iamge can be created. */
686 struct isofile *cur_file;
687 struct isoent *cur_dirent;
688 struct archive_string cur_dirstr;
689 uint64_t bytes_remaining;
690 int need_multi_extent;
692 /* Temporary string buffer for Joliet extension. */
693 struct archive_string utf16be;
694 struct archive_string mbs;
696 struct archive_string_conv *sconv_to_utf16be;
697 struct archive_string_conv *sconv_from_utf16be;
699 /* A list of all of struct isofile entries. */
701 struct isofile *first;
702 struct isofile **last;
705 /* A list of struct isofile entries which have its
706 * contents and are not a directory, a hardlined file
707 * and a symlink file. */
709 struct isofile *first;
710 struct isofile **last;
713 /* Used for managing to find hardlinking files. */
714 struct archive_rb_tree hardlink_rbtree;
716 /* Used for making the Path Table Record. */
718 /* the root of entry tree. */
719 struct isoent *rootent;
727 struct isoent *first;
728 struct isoent **last;
729 struct isoent **sorted;
734 int path_table_block;
736 int location_type_L_path_table;
737 int location_type_M_path_table;
741 /* Used for making a Volume Descriptor. */
742 int volume_space_size;
743 int volume_sequence_number;
744 int total_file_block;
745 struct archive_string volume_identifier;
746 struct archive_string publisher_identifier;
747 struct archive_string data_preparer_identifier;
748 struct archive_string application_identifier;
749 struct archive_string copyright_file_identifier;
750 struct archive_string abstract_file_identifier;
751 struct archive_string bibliographic_file_identifier;
753 /* Used for making rockridge extensions. */
754 int location_rrip_er;
756 /* Used for making zisofs. */
761 unsigned char magic_buffer[64];
766 * Copy a compressed file to iso9660.zisofs.temp_fd
767 * and also copy a uncompressed file(original file) to
768 * iso9660.temp_fd . If the number of logical block
769 * of the compressed file is less than the number of
770 * logical block of the uncompressed file, use it and
771 * remove the copy of the uncompressed file.
772 * but if not, we use uncompressed file and remove
773 * the copy of the compressed file.
775 uint32_t *block_pointers;
776 size_t block_pointers_allocated;
777 int block_pointers_cnt;
778 int block_pointers_idx;
780 int64_t block_offset;
785 int compression_level;
789 struct isoent *directories_too_deep;
793 #define wb_buffmax() (LOGICAL_BLOCK_SIZE * 32)
794 #define wb_remaining(a) (((struct iso9660 *)(a)->format_data)->wbuff_remaining)
795 #define wb_offset(a) (((struct iso9660 *)(a)->format_data)->wbuff_offset \
796 + wb_buffmax() - wb_remaining(a))
797 unsigned char wbuff[LOGICAL_BLOCK_SIZE * 32];
798 size_t wbuff_remaining;
803 int64_t wbuff_offset;
804 int64_t wbuff_written;
807 /* 'El Torito' boot data. */
809 /* boot catalog file */
810 struct archive_string catalog_filename;
811 struct isoent *catalog;
812 /* boot image file */
813 struct archive_string boot_filename;
816 unsigned char platform_id;
817 #define BOOT_PLATFORM_X86 0
818 #define BOOT_PLATFORM_PPC 1
819 #define BOOT_PLATFORM_MAC 2
820 struct archive_string id;
821 unsigned char media_type;
822 #define BOOT_MEDIA_NO_EMULATION 0
823 #define BOOT_MEDIA_1_2M_DISKETTE 1
824 #define BOOT_MEDIA_1_44M_DISKETTE 2
825 #define BOOT_MEDIA_2_88M_DISKETTE 3
826 #define BOOT_MEDIA_HARD_DISK 4
827 unsigned char system_type;
828 uint16_t boot_load_seg;
829 uint16_t boot_load_size;
830 #define BOOT_LOAD_SIZE 4
833 struct iso_option opt;
837 * Types of Volume Descriptor
840 VDT_BOOT_RECORD=0, /* Boot Record Volume Descriptor */
841 VDT_PRIMARY=1, /* Primary Volume Descriptor */
842 VDT_SUPPLEMENTARY=2, /* Supplementary Volume Descriptor */
843 VDT_TERMINATOR=255 /* Volume Descriptor Set Terminator */
847 * Types of Directory Record
850 DIR_REC_VD, /* Stored in Volume Descriptor. */
851 DIR_REC_SELF, /* Stored as Current Directory. */
852 DIR_REC_PARENT, /* Stored as Parent Directory. */
853 DIR_REC_NORMAL /* Stored as Child. */
857 * Kinds of Volume Descriptor Character
867 * IDentifier Resolver.
868 * Used for resolving duplicated filenames.
872 struct archive_rb_node rbnode;
873 /* Used in wait_list. */
874 struct idrent *wnext;
875 struct idrent *avail;
877 struct isoent *isoent;
883 struct archive_rb_tree rbtree;
886 struct idrent *first;
887 struct idrent **last;
904 static int iso9660_options(struct archive_write *,
905 const char *, const char *);
906 static int iso9660_write_header(struct archive_write *,
907 struct archive_entry *);
908 static ssize_t iso9660_write_data(struct archive_write *,
909 const void *, size_t);
910 static int iso9660_finish_entry(struct archive_write *);
911 static int iso9660_close(struct archive_write *);
912 static int iso9660_free(struct archive_write *);
914 static void get_system_identitier(char *, size_t);
915 static void set_str(unsigned char *, const char *, size_t, char,
917 static inline int joliet_allowed_char(unsigned char, unsigned char);
918 static int set_str_utf16be(struct archive_write *, unsigned char *,
919 const char *, size_t, uint16_t, enum vdc);
920 static int set_str_a_characters_bp(struct archive_write *,
921 unsigned char *, int, int, const char *, enum vdc);
922 static int set_str_d_characters_bp(struct archive_write *,
923 unsigned char *, int, int, const char *, enum vdc);
924 static void set_VD_bp(unsigned char *, enum VD_type, unsigned char);
925 static inline void set_unused_field_bp(unsigned char *, int, int);
927 static unsigned char *extra_open_record(unsigned char *, int,
928 struct isoent *, struct ctl_extr_rec *);
929 static void extra_close_record(struct ctl_extr_rec *, int);
930 static unsigned char * extra_next_record(struct ctl_extr_rec *, int);
931 static unsigned char *extra_get_record(struct isoent *, int *, int *, int *);
932 static void extra_tell_used_size(struct ctl_extr_rec *, int);
933 static int extra_setup_location(struct isoent *, int);
934 static int set_directory_record_rr(unsigned char *, int,
935 struct isoent *, struct iso9660 *, enum dir_rec_type);
936 static int set_directory_record(unsigned char *, size_t,
937 struct isoent *, struct iso9660 *, enum dir_rec_type,
939 static inline int get_dir_rec_size(struct iso9660 *, struct isoent *,
940 enum dir_rec_type, enum vdd_type);
941 static inline unsigned char *wb_buffptr(struct archive_write *);
942 static int wb_write_out(struct archive_write *);
943 static int wb_consume(struct archive_write *, size_t);
945 static int wb_set_offset(struct archive_write *, int64_t);
947 static int write_null(struct archive_write *, size_t);
948 static int write_VD_terminator(struct archive_write *);
949 static int set_file_identifier(unsigned char *, int, int, enum vdc,
950 struct archive_write *, struct vdd *,
951 struct archive_string *, const char *, int,
953 static int write_VD(struct archive_write *, struct vdd *);
954 static int write_VD_boot_record(struct archive_write *);
955 static int write_information_block(struct archive_write *);
956 static int write_path_table(struct archive_write *, int,
958 static int write_directory_descriptors(struct archive_write *,
960 static int write_file_descriptors(struct archive_write *);
961 static int write_rr_ER(struct archive_write *);
962 static void calculate_path_table_size(struct vdd *);
964 static void isofile_init_entry_list(struct iso9660 *);
965 static void isofile_add_entry(struct iso9660 *, struct isofile *);
966 static void isofile_free_all_entries(struct iso9660 *);
967 static void isofile_init_entry_data_file_list(struct iso9660 *);
968 static void isofile_add_data_file(struct iso9660 *, struct isofile *);
969 static struct isofile * isofile_new(struct archive_write *,
970 struct archive_entry *);
971 static void isofile_free(struct isofile *);
972 static int isofile_gen_utility_names(struct archive_write *,
974 static int isofile_register_hardlink(struct archive_write *,
976 static void isofile_connect_hardlink_files(struct iso9660 *);
977 static void isofile_init_hardlinks(struct iso9660 *);
978 static void isofile_free_hardlinks(struct iso9660 *);
980 static struct isoent *isoent_new(struct isofile *);
981 static int isoent_clone_tree(struct archive_write *,
982 struct isoent **, struct isoent *);
983 static void _isoent_free(struct isoent *isoent);
984 static void isoent_free_all(struct isoent *);
985 static struct isoent * isoent_create_virtual_dir(struct archive_write *,
986 struct iso9660 *, const char *);
987 static int isoent_cmp_node(const struct archive_rb_node *,
988 const struct archive_rb_node *);
989 static int isoent_cmp_key(const struct archive_rb_node *,
991 static int isoent_add_child_head(struct isoent *, struct isoent *);
992 static int isoent_add_child_tail(struct isoent *, struct isoent *);
993 static void isoent_remove_child(struct isoent *, struct isoent *);
994 static void isoent_setup_directory_location(struct iso9660 *,
996 static void isoent_setup_file_location(struct iso9660 *, int);
997 static int get_path_component(char *, 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 convertors.
1911 * if there is no file entry, convertors are still
1913 if (iso9660->sconv_to_utf16be == NULL) {
1914 iso9660->sconv_to_utf16be =
1915 archive_string_conversion_to_charset(
1916 &(a->archive), "UTF-16BE", 1);
1917 if (iso9660->sconv_to_utf16be == NULL)
1918 /* Couldn't allocate memory */
1919 return (ARCHIVE_FATAL);
1920 iso9660->sconv_from_utf16be =
1921 archive_string_conversion_from_charset(
1922 &(a->archive), "UTF-16BE", 1);
1923 if (iso9660->sconv_from_utf16be == NULL)
1924 /* Couldn't allocate memory */
1925 return (ARCHIVE_FATAL);
1932 ret = isoent_make_path_table(a);
1937 * Calculate a total volume size and setup all locations of
1938 * contents of an iso9660 image.
1940 blocks = SYSTEM_AREA_BLOCK
1941 + PRIMARY_VOLUME_DESCRIPTOR_BLOCK
1942 + VOLUME_DESCRIPTOR_SET_TERMINATOR_BLOCK
1943 + NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK;
1944 if (iso9660->opt.boot)
1945 blocks += BOOT_RECORD_DESCRIPTOR_BLOCK;
1946 if (iso9660->opt.joliet)
1947 blocks += SUPPLEMENTARY_VOLUME_DESCRIPTOR_BLOCK;
1948 if (iso9660->opt.iso_level == 4)
1949 blocks += SUPPLEMENTARY_VOLUME_DESCRIPTOR_BLOCK;
1951 /* Setup the locations of Path Table. */
1952 iso9660->primary.location_type_L_path_table = blocks;
1953 blocks += iso9660->primary.path_table_block;
1954 iso9660->primary.location_type_M_path_table = blocks;
1955 blocks += iso9660->primary.path_table_block;
1956 if (iso9660->opt.joliet) {
1957 iso9660->joliet.location_type_L_path_table = blocks;
1958 blocks += iso9660->joliet.path_table_block;
1959 iso9660->joliet.location_type_M_path_table = blocks;
1960 blocks += iso9660->joliet.path_table_block;
1963 /* Setup the locations of directories. */
1964 isoent_setup_directory_location(iso9660, blocks,
1965 &(iso9660->primary));
1966 blocks += iso9660->primary.total_dir_block;
1967 if (iso9660->opt.joliet) {
1968 isoent_setup_directory_location(iso9660, blocks,
1969 &(iso9660->joliet));
1970 blocks += iso9660->joliet.total_dir_block;
1973 if (iso9660->opt.rr) {
1974 iso9660->location_rrip_er = blocks;
1975 blocks += RRIP_ER_BLOCK;
1978 /* Setup the locations of all file contents. */
1979 isoent_setup_file_location(iso9660, blocks);
1980 blocks += iso9660->total_file_block;
1981 if (iso9660->opt.boot && iso9660->opt.boot_info_table) {
1982 ret = setup_boot_information(a);
1987 /* Now we have a total volume size. */
1988 iso9660->volume_space_size = blocks;
1989 if (iso9660->opt.pad)
1990 iso9660->volume_space_size += PADDING_BLOCK;
1991 iso9660->volume_sequence_number = 1;
1995 * Write an ISO 9660 image.
1998 /* Switc to start using wbuff as file buffer. */
1999 iso9660->wbuff_remaining = wb_buffmax();
2000 iso9660->wbuff_type = WB_TO_STREAM;
2001 iso9660->wbuff_offset = 0;
2002 iso9660->wbuff_written = 0;
2003 iso9660->wbuff_tail = 0;
2005 /* Write The System Area */
2006 ret = write_null(a, SYSTEM_AREA_BLOCK * LOGICAL_BLOCK_SIZE);
2007 if (ret != ARCHIVE_OK)
2008 return (ARCHIVE_FATAL);
2010 /* Write Primary Volume Descriptor */
2011 ret = write_VD(a, &(iso9660->primary));
2012 if (ret != ARCHIVE_OK)
2013 return (ARCHIVE_FATAL);
2015 if (iso9660->opt.boot) {
2016 /* Write Boot Record Volume Descriptor */
2017 ret = write_VD_boot_record(a);
2018 if (ret != ARCHIVE_OK)
2019 return (ARCHIVE_FATAL);
2022 if (iso9660->opt.iso_level == 4) {
2023 /* Write Enhanced Volume Descriptor */
2024 iso9660->primary.vdd_type = VDD_ENHANCED;
2025 ret = write_VD(a, &(iso9660->primary));
2026 iso9660->primary.vdd_type = VDD_PRIMARY;
2027 if (ret != ARCHIVE_OK)
2028 return (ARCHIVE_FATAL);
2031 if (iso9660->opt.joliet) {
2032 ret = write_VD(a, &(iso9660->joliet));
2033 if (ret != ARCHIVE_OK)
2034 return (ARCHIVE_FATAL);
2037 /* Write Volume Descriptor Set Terminator */
2038 ret = write_VD_terminator(a);
2039 if (ret != ARCHIVE_OK)
2040 return (ARCHIVE_FATAL);
2042 /* Write Non-ISO File System Information */
2043 ret = write_information_block(a);
2044 if (ret != ARCHIVE_OK)
2045 return (ARCHIVE_FATAL);
2047 /* Write Type L Path Table */
2048 ret = write_path_table(a, 0, &(iso9660->primary));
2049 if (ret != ARCHIVE_OK)
2050 return (ARCHIVE_FATAL);
2052 /* Write Type M Path Table */
2053 ret = write_path_table(a, 1, &(iso9660->primary));
2054 if (ret != ARCHIVE_OK)
2055 return (ARCHIVE_FATAL);
2057 if (iso9660->opt.joliet) {
2058 /* Write Type L Path Table */
2059 ret = write_path_table(a, 0, &(iso9660->joliet));
2060 if (ret != ARCHIVE_OK)
2061 return (ARCHIVE_FATAL);
2063 /* Write Type M Path Table */
2064 ret = write_path_table(a, 1, &(iso9660->joliet));
2065 if (ret != ARCHIVE_OK)
2066 return (ARCHIVE_FATAL);
2069 /* Write Directory Descriptors */
2070 ret = write_directory_descriptors(a, &(iso9660->primary));
2071 if (ret != ARCHIVE_OK)
2072 return (ARCHIVE_FATAL);
2074 if (iso9660->opt.joliet) {
2075 ret = write_directory_descriptors(a, &(iso9660->joliet));
2076 if (ret != ARCHIVE_OK)
2077 return (ARCHIVE_FATAL);
2080 if (iso9660->opt.rr) {
2081 /* Write Rockridge ER(Extensions Reference) */
2082 ret = write_rr_ER(a);
2083 if (ret != ARCHIVE_OK)
2084 return (ARCHIVE_FATAL);
2087 /* Write File Descriptors */
2088 ret = write_file_descriptors(a);
2089 if (ret != ARCHIVE_OK)
2090 return (ARCHIVE_FATAL);
2093 if (iso9660->opt.pad) {
2094 ret = write_null(a, PADDING_BLOCK * LOGICAL_BLOCK_SIZE);
2095 if (ret != ARCHIVE_OK)
2096 return (ARCHIVE_FATAL);
2099 if (iso9660->directories_too_deep != NULL) {
2100 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2101 "%s: Directories too deep.",
2102 archive_entry_pathname(
2103 iso9660->directories_too_deep->file->entry));
2104 return (ARCHIVE_WARN);
2107 /* Write remaining data out. */
2108 ret = wb_write_out(a);
2114 iso9660_free(struct archive_write *a)
2116 struct iso9660 *iso9660;
2119 iso9660 = a->format_data;
2121 /* Close the temporary file. */
2122 if (iso9660->temp_fd >= 0)
2123 close(iso9660->temp_fd);
2125 /* Free some stuff for zisofs operations. */
2126 ret = zisofs_free(a);
2128 /* Remove directory entries in tree which includes file entries. */
2129 isoent_free_all(iso9660->primary.rootent);
2130 for (i = 0; i < iso9660->primary.max_depth; i++)
2131 free(iso9660->primary.pathtbl[i].sorted);
2132 free(iso9660->primary.pathtbl);
2134 if (iso9660->opt.joliet) {
2135 isoent_free_all(iso9660->joliet.rootent);
2136 for (i = 0; i < iso9660->joliet.max_depth; i++)
2137 free(iso9660->joliet.pathtbl[i].sorted);
2138 free(iso9660->joliet.pathtbl);
2141 /* Remove isofile entries. */
2142 isofile_free_all_entries(iso9660);
2143 isofile_free_hardlinks(iso9660);
2145 archive_string_free(&(iso9660->cur_dirstr));
2146 archive_string_free(&(iso9660->volume_identifier));
2147 archive_string_free(&(iso9660->publisher_identifier));
2148 archive_string_free(&(iso9660->data_preparer_identifier));
2149 archive_string_free(&(iso9660->application_identifier));
2150 archive_string_free(&(iso9660->copyright_file_identifier));
2151 archive_string_free(&(iso9660->abstract_file_identifier));
2152 archive_string_free(&(iso9660->bibliographic_file_identifier));
2153 archive_string_free(&(iso9660->el_torito.catalog_filename));
2154 archive_string_free(&(iso9660->el_torito.boot_filename));
2155 archive_string_free(&(iso9660->el_torito.id));
2156 archive_string_free(&(iso9660->utf16be));
2157 archive_string_free(&(iso9660->mbs));
2160 a->format_data = NULL;
2166 * Get the System Identifier
2169 get_system_identitier(char *system_id, size_t size)
2171 #if defined(HAVE_SYS_UTSNAME_H)
2175 strncpy(system_id, u.sysname, size-1);
2176 system_id[size-1] = '\0';
2177 #elif defined(_WIN32) && !defined(__CYGWIN__)
2178 strncpy(system_id, "Windows", size-1);
2179 system_id[size-1] = '\0';
2181 #error no way to get the system identifier on your platform.
2186 set_str(unsigned char *p, const char *s, size_t l, char f, const char *map)
2192 while ((c = *s++) != 0 && l > 0) {
2193 if (c >= 0x80 || map[c] == 0)
2195 /* illegal character */
2196 if (c >= 'a' && c <= 'z') {
2197 /* convert c from a-z to A-Z */
2205 /* If l isn't zero, fill p buffer by the character
2206 * which indicated by f. */
2212 joliet_allowed_char(unsigned char high, unsigned char low)
2214 int utf16 = (high << 8) | low;
2216 if (utf16 <= 0x001F)
2220 case 0x002A: /* '*' */
2221 case 0x002F: /* '/' */
2222 case 0x003A: /* ':' */
2223 case 0x003B: /* ';' */
2224 case 0x003F: /* '?' */
2225 case 0x005C: /* '\' */
2226 return (0);/* Not allowed. */
2232 set_str_utf16be(struct archive_write *a, unsigned char *p, const char *s,
2233 size_t l, uint16_t uf, enum vdc vdc)
2245 if (vdc == VDC_UCS2) {
2246 struct iso9660 *iso9660 = a->format_data;
2247 if (archive_strncpy_l(&iso9660->utf16be, s, strlen(s),
2248 iso9660->sconv_to_utf16be) != 0 && errno == ENOMEM) {
2249 archive_set_error(&a->archive, ENOMEM,
2250 "Can't allocate memory for UTF-16BE");
2251 return (ARCHIVE_FATAL);
2253 size = iso9660->utf16be.length;
2256 memcpy(p, iso9660->utf16be.s, size);
2258 const uint16_t *u16 = (const uint16_t *)s;
2267 for (i = 0; i < size; i += 2, p += 2) {
2268 if (!joliet_allowed_char(p[0], p[1]))
2269 archive_be16enc(p, 0x005F);/* '_' */
2273 archive_be16enc(p, uf);
2279 return (ARCHIVE_OK);
2282 static const char a_characters_map[0x80] = {
2283 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
2284 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
2285 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
2286 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20-2F */
2287 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30-3F */
2288 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
2289 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
2290 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 60-6F */
2291 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 70-7F */
2294 static const char a1_characters_map[0x80] = {
2295 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
2296 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
2297 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
2298 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20-2F */
2299 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30-3F */
2300 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
2301 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
2302 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60-6F */
2303 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,/* 70-7F */
2306 static const char d_characters_map[0x80] = {
2307 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
2308 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
2309 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
2310 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 20-2F */
2311 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,/* 30-3F */
2312 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
2313 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
2314 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 60-6F */
2315 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 70-7F */
2318 static const char d1_characters_map[0x80] = {
2319 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
2320 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
2321 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
2322 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 20-2F */
2323 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,/* 30-3F */
2324 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
2325 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
2326 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60-6F */
2327 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,/* 70-7F */
2331 set_str_a_characters_bp(struct archive_write *a, unsigned char *bp,
2332 int from, int to, const char *s, enum vdc vdc)
2338 set_str(bp+from, s, to - from + 1, 0x20,
2343 set_str(bp+from, s, to - from + 1, 0x20,
2348 case VDC_UCS2_DIRECT:
2349 r = set_str_utf16be(a, bp+from, s, to - from + 1,
2359 set_str_d_characters_bp(struct archive_write *a, unsigned char *bp,
2360 int from, int to, const char *s, enum vdc vdc)
2366 set_str(bp+from, s, to - from + 1, 0x20,
2371 set_str(bp+from, s, to - from + 1, 0x20,
2376 case VDC_UCS2_DIRECT:
2377 r = set_str_utf16be(a, bp+from, s, to - from + 1,
2387 set_VD_bp(unsigned char *bp, enum VD_type type, unsigned char ver)
2390 /* Volume Descriptor Type */
2391 bp[1] = (unsigned char)type;
2392 /* Standard Identifier */
2393 memcpy(bp + 2, "CD001", 5);
2394 /* Volume Descriptor Version */
2399 set_unused_field_bp(unsigned char *bp, int from, int to)
2401 memset(bp + from, 0, to - from + 1);
2405 * 8-bit unsigned numerical values.
2406 * ISO9660 Standard 7.1.1
2409 set_num_711(unsigned char *p, unsigned char value)
2415 * 8-bit signed numerical values.
2416 * ISO9660 Standard 7.1.2
2419 set_num_712(unsigned char *p, char value)
2421 *((char *)p) = value;
2425 * Least significant byte first.
2426 * ISO9660 Standard 7.2.1
2429 set_num_721(unsigned char *p, uint16_t value)
2431 archive_le16enc(p, value);
2435 * Most significant byte first.
2436 * ISO9660 Standard 7.2.2
2439 set_num_722(unsigned char *p, uint16_t value)
2441 archive_be16enc(p, value);
2446 * ISO9660 Standard 7.2.3
2449 set_num_723(unsigned char *p, uint16_t value)
2451 archive_le16enc(p, value);
2452 archive_be16enc(p+2, value);
2456 * Least significant byte first.
2457 * ISO9660 Standard 7.3.1
2460 set_num_731(unsigned char *p, uint32_t value)
2462 archive_le32enc(p, value);
2466 * Most significant byte first.
2467 * ISO9660 Standard 7.3.2
2470 set_num_732(unsigned char *p, uint32_t value)
2472 archive_be32enc(p, value);
2477 * ISO9660 Standard 7.3.3
2480 set_num_733(unsigned char *p, uint32_t value)
2482 archive_le32enc(p, value);
2483 archive_be32enc(p+4, value);
2487 set_digit(unsigned char *p, size_t s, int value)
2491 p[s] = '0' + (value % 10);
2496 #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
2497 #define get_gmoffset(tm) ((tm)->tm_gmtoff)
2498 #elif defined(HAVE_STRUCT_TM___TM_GMTOFF)
2499 #define get_gmoffset(tm) ((tm)->__tm_gmtoff)
2502 get_gmoffset(struct tm *tm)
2506 #if defined(HAVE__GET_TIMEZONE)
2507 _get_timezone(&offset);
2508 #elif defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
2521 get_tmfromtime(struct tm *tm, time_t *t)
2523 #if HAVE_LOCALTIME_R
2526 #elif HAVE__LOCALTIME64_S
2527 _localtime64_s(tm, t);
2529 memcpy(tm, localtime(t), sizeof(*tm));
2534 * Date and Time Format.
2535 * ISO9660 Standard 8.4.26.1
2538 set_date_time(unsigned char *p, time_t t)
2542 get_tmfromtime(&tm, &t);
2543 set_digit(p, 4, tm.tm_year + 1900);
2544 set_digit(p+4, 2, tm.tm_mon + 1);
2545 set_digit(p+6, 2, tm.tm_mday);
2546 set_digit(p+8, 2, tm.tm_hour);
2547 set_digit(p+10, 2, tm.tm_min);
2548 set_digit(p+12, 2, tm.tm_sec);
2549 set_digit(p+14, 2, 0);
2550 set_num_712(p+16, (char)(get_gmoffset(&tm)/(60*15)));
2554 set_date_time_null(unsigned char *p)
2561 set_time_915(unsigned char *p, time_t t)
2565 get_tmfromtime(&tm, &t);
2566 set_num_711(p+0, tm.tm_year);
2567 set_num_711(p+1, tm.tm_mon+1);
2568 set_num_711(p+2, tm.tm_mday);
2569 set_num_711(p+3, tm.tm_hour);
2570 set_num_711(p+4, tm.tm_min);
2571 set_num_711(p+5, tm.tm_sec);
2572 set_num_712(p+6, (char)(get_gmoffset(&tm)/(60*15)));
2577 * Write SUSP "CE" System Use Entry.
2580 set_SUSP_CE(unsigned char *p, int location, int offset, int size)
2582 unsigned char *bp = p -1;
2583 /* Extend the System Use Area
2586 * +----+----+----+----+-----------+-----------+
2587 * | 'C'| 'E'| 1C | 01 | LOCATION1 | LOCATION2 |
2588 * +----+----+----+----+-----------+-----------+
2594 * LOCATION1 : Location of Continuation of System Use Area.
2595 * LOCATION2 : Offset to Start of Continuation.
2596 * LOCATION3 : Length of the Continuation.
2601 bp[3] = RR_CE_SIZE; /* length */
2602 bp[4] = 1; /* version */
2603 set_num_733(bp+5, location);
2604 set_num_733(bp+13, offset);
2605 set_num_733(bp+21, size);
2606 return (RR_CE_SIZE);
2610 * The functions, which names are beginning with extra_, are used to
2611 * control extra records.
2612 * The maximum size of a Directory Record is 254. When a filename is
2613 * very long, all of RRIP data of a file won't stored to the Directory
2614 * Record and so remaining RRIP data store to an extra record instead.
2616 static unsigned char *
2617 extra_open_record(unsigned char *bp, int dr_len, struct isoent *isoent,
2618 struct ctl_extr_rec *ctl)
2624 ctl->isoent = isoent;
2626 ctl->cur_len = ctl->dr_len = dr_len;
2627 ctl->limit = DR_LIMIT;
2633 extra_close_record(struct ctl_extr_rec *ctl, int ce_size)
2638 extra_tell_used_size(ctl, ce_size);
2640 if (ctl->cur_len & 0x01) {
2642 if (ctl->bp != NULL)
2643 ctl->bp[ctl->cur_len] = 0;
2646 if (ctl->use_extr) {
2647 if (ctl->ce_ptr != NULL)
2648 set_SUSP_CE(ctl->ce_ptr, ctl->extr_loc,
2649 ctl->extr_off, ctl->cur_len - padding);
2651 ctl->dr_len = ctl->cur_len;
2654 #define extra_space(ctl) ((ctl)->limit - (ctl)->cur_len)
2656 static unsigned char *
2657 extra_next_record(struct ctl_extr_rec *ctl, int length)
2659 int cur_len = ctl->cur_len;/* save cur_len */
2661 /* Close the current extra record or Directory Record. */
2662 extra_close_record(ctl, RR_CE_SIZE);
2664 /* Get a next extra record. */
2666 if (ctl->bp != NULL) {
2667 /* Storing data into an extra record. */
2670 /* Save the pointer where a CE extension will be
2672 ctl->ce_ptr = &ctl->bp[cur_len+1];
2673 p = extra_get_record(ctl->isoent,
2674 &ctl->limit, &ctl->extr_off, &ctl->extr_loc);
2675 ctl->bp = p - 1;/* the base of bp offset is 1. */
2677 /* Calculating the size of an extra record. */
2678 (void)extra_get_record(ctl->isoent,
2679 &ctl->limit, NULL, NULL);
2681 /* Check if an extra record is almost full.
2682 * If so, get a next one. */
2683 if (extra_space(ctl) < length)
2684 (void)extra_next_record(ctl, length);
2689 static inline struct extr_rec *
2690 extra_last_record(struct isoent *isoent)
2692 if (isoent->extr_rec_list.first == NULL)
2694 return ((struct extr_rec *)(void *)
2695 ((char *)(isoent->extr_rec_list.last)
2696 - offsetof(struct extr_rec, next)));
2699 static unsigned char *
2700 extra_get_record(struct isoent *isoent, int *space, int *off, int *loc)
2702 struct extr_rec *rec;
2704 isoent = isoent->parent;
2706 /* Storing data into an extra record. */
2707 rec = isoent->extr_rec_list.current;
2708 if (DR_SAFETY > LOGICAL_BLOCK_SIZE - rec->offset)
2711 /* Calculating the size of an extra record. */
2712 rec = extra_last_record(isoent);
2714 DR_SAFETY > LOGICAL_BLOCK_SIZE - rec->offset) {
2715 rec = malloc(sizeof(*rec));
2720 /* Insert `rec` into the tail of isoent->extr_rec_list */
2723 * Note: testing isoent->extr_rec_list.last == NULL
2724 * here is really unneeded since it has been already
2725 * initialized at isoent_new function but Clang Static
2726 * Analyzer claims that it is dereference of null
2729 if (isoent->extr_rec_list.last == NULL)
2730 isoent->extr_rec_list.last =
2731 &(isoent->extr_rec_list.first);
2732 *isoent->extr_rec_list.last = rec;
2733 isoent->extr_rec_list.last = &(rec->next);
2736 *space = LOGICAL_BLOCK_SIZE - rec->offset - DR_SAFETY;
2738 *space -= 1;/* Keep padding space. */
2742 *loc = rec->location;
2743 isoent->extr_rec_list.current = rec;
2745 return (&rec->buf[rec->offset]);
2749 extra_tell_used_size(struct ctl_extr_rec *ctl, int size)
2751 struct isoent *isoent;
2752 struct extr_rec *rec;
2754 if (ctl->use_extr) {
2755 isoent = ctl->isoent->parent;
2756 rec = isoent->extr_rec_list.current;
2758 rec->offset += size;
2760 ctl->cur_len += size;
2764 extra_setup_location(struct isoent *isoent, int location)
2766 struct extr_rec *rec;
2770 rec = isoent->extr_rec_list.first;
2771 isoent->extr_rec_list.current = rec;
2774 rec->location = location++;
2782 * Create the RRIP entries.
2785 set_directory_record_rr(unsigned char *bp, int dr_len,
2786 struct isoent *isoent, struct iso9660 *iso9660, enum dir_rec_type t)
2788 /* Flags(BP 5) of the Rockridge "RR" System Use Field */
2789 unsigned char rr_flag;
2790 #define RR_USE_PX 0x01
2791 #define RR_USE_PN 0x02
2792 #define RR_USE_SL 0x04
2793 #define RR_USE_NM 0x08
2794 #define RR_USE_CL 0x10
2795 #define RR_USE_PL 0x20
2796 #define RR_USE_RE 0x40
2797 #define RR_USE_TF 0x80
2799 struct ctl_extr_rec ctl;
2800 struct isoent *rr_parent, *pxent;
2801 struct isofile *file;
2803 bp = extra_open_record(bp, dr_len, isoent, &ctl);
2805 if (t == DIR_REC_PARENT) {
2806 rr_parent = isoent->rr_parent;
2807 pxent = isoent->parent;
2808 if (rr_parent != NULL)
2811 isoent = isoent->parent;
2816 file = isoent->file;
2818 if (t != DIR_REC_NORMAL) {
2819 rr_flag = RR_USE_PX | RR_USE_TF;
2820 if (rr_parent != NULL)
2821 rr_flag |= RR_USE_PL;
2823 rr_flag = RR_USE_PX | RR_USE_NM | RR_USE_TF;
2824 if (archive_entry_filetype(file->entry) == AE_IFLNK)
2825 rr_flag |= RR_USE_SL;
2826 if (isoent->rr_parent != NULL)
2827 rr_flag |= RR_USE_RE;
2828 if (isoent->rr_child != NULL)
2829 rr_flag |= RR_USE_CL;
2830 if (archive_entry_filetype(file->entry) == AE_IFCHR ||
2831 archive_entry_filetype(file->entry) == AE_IFBLK)
2832 rr_flag |= RR_USE_PN;
2833 #ifdef COMPAT_MKISOFS
2835 * mkisofs 2.01.01a63 records "RE" extension to
2836 * the entry of "rr_moved" directory.
2837 * I don't understand this behavior.
2839 if (isoent->virtual &&
2840 isoent->parent == iso9660->primary.rootent &&
2841 strcmp(isoent->file->basename.s, "rr_moved") == 0)
2842 rr_flag |= RR_USE_RE;
2846 /* Write "SP" System Use Entry. */
2847 if (t == DIR_REC_SELF && isoent == isoent->parent) {
2853 bp[4] = 1; /* version */
2854 bp[5] = 0xBE; /* Check Byte */
2855 bp[6] = 0xEF; /* Check Byte */
2859 extra_tell_used_size(&ctl, length);
2862 /* Write "RR" System Use Entry. */
2864 if (extra_space(&ctl) < length)
2865 bp = extra_next_record(&ctl, length);
2870 bp[4] = 1; /* version */
2874 extra_tell_used_size(&ctl, length);
2876 /* Write "NM" System Use Entry. */
2877 if (rr_flag & RR_USE_NM) {
2880 * e.g. a basename is 'foo'
2882 * +----+----+----+----+----+----+----+----+
2883 * | 'N'| 'M'| 08 | 01 | 00 | 'f'| 'o'| 'o'|
2884 * +----+----+----+----+----+----+----+----+
2885 * <----------------- len ----------------->
2887 size_t nmlen = file->basename.length;
2888 const char *nm = file->basename.s;
2891 if (extra_space(&ctl) < 6)
2892 bp = extra_next_record(&ctl, 6);
2896 bp[4] = 1; /* version */
2898 nmmax = extra_space(&ctl);
2901 while (nmlen + 5 > nmmax) {
2902 length = (int)nmmax;
2905 bp[5] = 0x01;/* Alternate Name continues
2906 * in next "NM" field */
2907 memcpy(bp+6, nm, length - 5);
2910 nmlen -= length - 5;
2912 extra_tell_used_size(&ctl, length);
2913 if (extra_space(&ctl) < 6) {
2914 bp = extra_next_record(&ctl, 6);
2915 nmmax = extra_space(&ctl);
2922 bp[4] = 1; /* version */
2925 length = 5 + (int)nmlen;
2929 memcpy(bp+6, nm, nmlen);
2932 extra_tell_used_size(&ctl, length);
2935 /* Write "PX" System Use Entry. */
2936 if (rr_flag & RR_USE_PX) {
2940 * +----+----+----+----+-----------+-----------+
2941 * | 'P'| 'X'| 2C | 01 | FILE MODE | LINKS |
2942 * +----+----+----+----+-----------+-----------+
2944 * +-----------+-----------+------------------+
2945 * | USER ID | GROUP ID |FILE SERIAL NUMBER|
2946 * +-----------+-----------+------------------+
2950 if (extra_space(&ctl) < length)
2951 bp = extra_next_record(&ctl, length);
2957 mode = archive_entry_mode(file->entry);
2958 uid = archive_entry_uid(file->entry);
2959 gid = archive_entry_gid(file->entry);
2960 if (iso9660->opt.rr == OPT_RR_USEFUL) {
2962 * This action is simular mkisofs -r option
2963 * but our rockridge=useful option does not
2964 * set a zero to uid and gid.
2966 /* set all read bit ON */
2968 #if !defined(_WIN32) && !defined(__CYGWIN__)
2971 /* set all exec bit ON */
2973 /* clear all write bits. */
2975 /* clear setuid,setgid,sticky bits. */
2982 bp[4] = 1; /* version */
2984 set_num_733(bp+5, mode);
2985 /* file links (stat.st_nlink) */
2987 archive_entry_nlink(file->entry));
2988 set_num_733(bp+21, (uint32_t)uid);
2989 set_num_733(bp+29, (uint32_t)gid);
2990 /* File Serial Number */
2992 set_num_733(bp+37, pxent->dir_location);
2993 else if (file->hardlink_target != NULL)
2995 file->hardlink_target->cur_content->location);
2998 file->cur_content->location);
3001 extra_tell_used_size(&ctl, length);
3004 /* Write "SL" System Use Entry. */
3005 if (rr_flag & RR_USE_SL) {
3008 * e.g. a symbolic name is 'foo/bar'
3010 * +----+----+----+----+----+------------+
3011 * | 'S'| 'L'| 0F | 01 | 00 | components |
3012 * +----+----+----+----+----+-----+------+
3013 * 0 1 2 3 4 5 ...|... 15
3014 * <----------------- len --------+------>
3017 * +----+----+----+----+----+ |
3018 * | 00 | 03 | 'f'| 'o'| 'o'| <---+
3019 * +----+----+----+----+----+ |
3022 * +----+----+----+----+----+ |
3023 * | 00 | 03 | 'b'| 'a'| 'r'| <---+
3024 * +----+----+----+----+----+
3027 * - cflg : flag of componet
3028 * - clen : length of componet
3033 if (extra_space(&ctl) < 7)
3034 bp = extra_next_record(&ctl, 7);
3035 sl = file->symlink.s;
3040 bp[4] = 1; /* version */
3043 unsigned char *nc, *cf, *cl, cldmy = 0;
3046 slmax = extra_space(&ctl);
3055 while (*sl && sllen + 11 < slmax) {
3056 if (sl_last == '\0' && sl[0] == '/') {
3060 * | 08 | 00 | ROOT component.
3063 * Root component has to appear
3064 * at the first component only.
3068 *cf = 0x08; /* ROOT */
3077 if (((sl_last == '\0' || sl_last == '/') &&
3078 sl[0] == '.' && sl[1] == '.' &&
3079 (sl[2] == '/' || sl[2] == '\0')) ||
3081 sl[1] == '.' && sl[2] == '.' &&
3082 (sl[3] == '/' || sl[3] == '\0'))) {
3086 * | 04 | 00 | PARENT component.
3087 * +----+----+ ("..")
3091 *cf = 0x04; /* PARENT */
3096 sl += 3;/* skip "/.." */
3098 sl += 2;/* skip ".." */
3103 if (((sl_last == '\0' || sl_last == '/') &&
3105 (sl[1] == '/' || sl[1] == '\0')) ||
3106 (sl[0] == '/' && sl[1] == '.' &&
3107 (sl[2] == '/' || sl[2] == '\0'))) {
3111 * | 02 | 00 | CURREENT component.
3116 *cf = 0x02; /* CURRENT */
3121 sl += 2;/* skip "/." */
3123 sl ++; /* skip "." */
3128 if (sl[0] == '/' || cl == NULL) {
3153 * Mark flg as CONTINUE component.
3158 * +----+----+----+----+----+-
3159 * | 'S'| 'L'| XX | 01 | 01 |
3160 * +----+----+----+----+----+-
3162 * continues in next "SL"
3165 bp[5] = 0x01;/* This Symbolic Link
3170 extra_tell_used_size(&ctl, length);
3171 if (extra_space(&ctl) < 11)
3172 bp = extra_next_record(&ctl, 11);
3177 bp[4] = 1; /* version */
3186 extra_tell_used_size(&ctl, length);
3192 /* Write "TF" System Use Entry. */
3193 if (rr_flag & RR_USE_TF) {
3197 * +----+----+----+----+-----+-------------+
3198 * | 'T'| 'F'| XX | 01 |FLAGS| TIME STAMPS |
3199 * +----+----+----+----+-----+-------------+
3201 * TIME STAMPS : ISO 9660 Standard 9.1.5.
3202 * If TF_LONG_FORM FLAGS is set,
3203 * use ISO9660 Standard 8.4.26.1.
3205 #define TF_CREATION 0x01 /* Creation time recorded */
3206 #define TF_MODIFY 0x02 /* Modification time recorded */
3207 #define TF_ACCESS 0x04 /* Last Access time recorded */
3208 #define TF_ATTRIBUTES 0x08 /* Last Attribute Change time recorded */
3209 #define TF_BACKUP 0x10 /* Last Backup time recorded */
3210 #define TF_EXPIRATION 0x20 /* Expiration time recorded */
3211 #define TF_EFFECTIVE 0x40 /* Effective time recorded */
3212 #define TF_LONG_FORM 0x80 /* ISO 9660 17-byte time format used */
3213 unsigned char tf_flags;
3217 #ifndef COMPAT_MKISOFS
3218 if (archive_entry_birthtime_is_set(file->entry) &&
3219 archive_entry_birthtime(file->entry) <=
3220 archive_entry_mtime(file->entry)) {
3222 tf_flags |= TF_CREATION;
3225 if (archive_entry_mtime_is_set(file->entry)) {
3227 tf_flags |= TF_MODIFY;
3229 if (archive_entry_atime_is_set(file->entry)) {
3231 tf_flags |= TF_ACCESS;
3233 if (archive_entry_ctime_is_set(file->entry)) {
3235 tf_flags |= TF_ATTRIBUTES;
3237 if (extra_space(&ctl) < length)
3238 bp = extra_next_record(&ctl, length);
3243 bp[4] = 1; /* version */
3247 if (tf_flags & TF_CREATION) {
3249 archive_entry_birthtime(file->entry));
3252 /* Modification time */
3253 if (tf_flags & TF_MODIFY) {
3255 archive_entry_mtime(file->entry));
3258 /* Last Access time */
3259 if (tf_flags & TF_ACCESS) {
3261 archive_entry_atime(file->entry));
3264 /* Last Attribute Change time */
3265 if (tf_flags & TF_ATTRIBUTES) {
3267 archive_entry_ctime(file->entry));
3271 extra_tell_used_size(&ctl, length);
3274 /* Write "RE" System Use Entry. */
3275 if (rr_flag & RR_USE_RE) {
3279 * +----+----+----+----+
3280 * | 'R'| 'E'| 04 | 01 |
3281 * +----+----+----+----+
3285 if (extra_space(&ctl) < length)
3286 bp = extra_next_record(&ctl, length);
3291 bp[4] = 1; /* version */
3294 extra_tell_used_size(&ctl, length);
3297 /* Write "PL" System Use Entry. */
3298 if (rr_flag & RR_USE_PL) {
3302 * +----+----+----+----+------------+
3303 * | 'P'| 'L'| 0C | 01 | *LOCATION |
3304 * +----+----+----+----+------------+
3306 * *LOCATION: location of parent directory
3309 if (extra_space(&ctl) < length)
3310 bp = extra_next_record(&ctl, length);
3315 bp[4] = 1; /* version */
3317 rr_parent->dir_location);
3320 extra_tell_used_size(&ctl, length);
3323 /* Write "CL" System Use Entry. */
3324 if (rr_flag & RR_USE_CL) {
3328 * +----+----+----+----+------------+
3329 * | 'C'| 'L'| 0C | 01 | *LOCATION |
3330 * +----+----+----+----+------------+
3332 * *LOCATION: location of child directory
3335 if (extra_space(&ctl) < length)
3336 bp = extra_next_record(&ctl, length);
3341 bp[4] = 1; /* version */
3343 isoent->rr_child->dir_location);
3346 extra_tell_used_size(&ctl, length);
3349 /* Write "PN" System Use Entry. */
3350 if (rr_flag & RR_USE_PN) {
3354 * +----+----+----+----+------------+------------+
3355 * | 'P'| 'N'| 14 | 01 | dev_t high | dev_t low |
3356 * +----+----+----+----+------------+------------+
3360 if (extra_space(&ctl) < length)
3361 bp = extra_next_record(&ctl, length);
3368 bp[4] = 1; /* version */
3369 dev = (uint64_t)archive_entry_rdev(file->entry);
3370 set_num_733(bp + 5, (uint32_t)(dev >> 32));
3371 set_num_733(bp + 13, (uint32_t)(dev & 0xFFFFFFFF));
3374 extra_tell_used_size(&ctl, length);
3377 /* Write "ZF" System Use Entry. */
3378 if (file->zisofs.header_size) {
3382 * +----+----+----+----+----+----+-------------+
3383 * | 'Z'| 'F'| 10 | 01 | 'p'| 'z'| Header Size |
3384 * +----+----+----+----+----+----+-------------+
3386 * +--------------------+-------------------+
3387 * | Log2 of block Size | Uncompressed Size |
3388 * +--------------------+-------------------+
3392 if (extra_space(&ctl) < length)
3393 bp = extra_next_record(&ctl, length);
3398 bp[4] = 1; /* version */
3401 bp[7] = file->zisofs.header_size;
3402 bp[8] = file->zisofs.log2_bs;
3403 set_num_733(bp + 9, file->zisofs.uncompressed_size);
3406 extra_tell_used_size(&ctl, length);
3409 /* Write "CE" System Use Entry. */
3410 if (t == DIR_REC_SELF && isoent == isoent->parent) {
3411 length = RR_CE_SIZE;
3413 set_SUSP_CE(bp+1, iso9660->location_rrip_er,
3415 extra_tell_used_size(&ctl, length);
3418 extra_close_record(&ctl, 0);
3420 return (ctl.dr_len);
3424 * Write data of a Directory Record or calculate writing bytes itself.
3425 * If parameter `p' is NULL, calculates the size of writing data, which
3426 * a Directory Record needs to write, then it saved and return
3427 * the calculated size.
3428 * Parameter `n' is a remaining size of buffer. when parameter `p' is
3429 * not NULL, check whether that `n' is not less than the saved size.
3430 * if that `n' is small, return zero.
3432 * This format of the Directory Record is according to
3433 * ISO9660 Standard 9.1
3436 set_directory_record(unsigned char *p, size_t n, struct isoent *isoent,
3437 struct iso9660 *iso9660, enum dir_rec_type t,
3438 enum vdd_type vdd_type)
3446 * Check whether a write buffer size is less than the
3447 * saved size which is needed to write this Directory
3452 dr_len = isoent->dr_len.vd; break;
3454 dr_len = isoent->dr_len.self; break;
3455 case DIR_REC_PARENT:
3456 dr_len = isoent->dr_len.parent; break;
3457 case DIR_REC_NORMAL:
3459 dr_len = isoent->dr_len.normal; break;
3462 return (0);/* Needs more buffer size. */
3465 if (t == DIR_REC_NORMAL && isoent->identifier != NULL)
3466 fi_len = isoent->id_len;
3471 struct isoent *xisoent;
3472 struct isofile *file;
3475 if (t == DIR_REC_PARENT)
3476 xisoent = isoent->parent;
3479 file = isoent->file;
3480 if (file->hardlink_target != NULL)
3481 file = file->hardlink_target;
3482 /* Make a file flag. */
3484 flag = FILE_FLAG_DIRECTORY;
3486 if (file->cur_content->next != NULL)
3487 flag = FILE_FLAG_MULTI_EXTENT;
3493 /* Extended Attribute Record Length */
3494 set_num_711(bp+2, 0);
3495 /* Location of Extent */
3497 set_num_733(bp+3, xisoent->dir_location);
3499 set_num_733(bp+3, file->cur_content->location);
3503 xisoent->dir_block * LOGICAL_BLOCK_SIZE);
3505 set_num_733(bp+11, (uint32_t)file->cur_content->size);
3506 /* Recording Date and Time */
3508 * If a file type is symbolic link, you are seeing this
3509 * field value is different from a value mkisofs makes.
3510 * libarchive uses lstat to get this one, but it
3511 * seems mkisofs uses stat to get.
3514 archive_entry_mtime(xisoent->file->entry));
3517 /* File Unit Size */
3518 set_num_711(bp+27, 0);
3519 /* Interleave Gap Size */
3520 set_num_711(bp+28, 0);
3521 /* Volume Sequence Number */
3522 set_num_723(bp+29, iso9660->volume_sequence_number);
3523 /* Length of File Identifier */
3524 set_num_711(bp+33, (unsigned char)fi_len);
3525 /* File Identifier */
3529 set_num_711(bp+34, 0);
3531 case DIR_REC_PARENT:
3532 set_num_711(bp+34, 1);
3534 case DIR_REC_NORMAL:
3535 if (isoent->identifier != NULL)
3536 memcpy(bp+34, isoent->identifier, fi_len);
3538 set_num_711(bp+34, 0);
3543 dr_len = 33 + fi_len;
3545 if (dr_len & 0x01) {
3551 /* Volume Descriptor does not record extension. */
3552 if (t == DIR_REC_VD) {
3554 /* Length of Directory Record */
3555 set_num_711(p, (unsigned char)dr_len);
3557 isoent->dr_len.vd = (int)dr_len;
3558 return ((int)dr_len);
3562 if (iso9660->opt.rr && vdd_type != VDD_JOLIET)
3563 dr_len = set_directory_record_rr(bp, (int)dr_len,
3564 isoent, iso9660, t);
3567 /* Length of Directory Record */
3568 set_num_711(p, (unsigned char)dr_len);
3571 * Save the size which is needed to write this
3576 /* This case does not come, but compiler
3577 * complains that DIR_REC_VD not handled
3581 isoent->dr_len.self = (int)dr_len; break;
3582 case DIR_REC_PARENT:
3583 isoent->dr_len.parent = (int)dr_len; break;
3584 case DIR_REC_NORMAL:
3585 isoent->dr_len.normal = (int)dr_len; break;
3589 return ((int)dr_len);
3593 * Calculate the size of a directory record.
3596 get_dir_rec_size(struct iso9660 *iso9660, struct isoent *isoent,
3597 enum dir_rec_type t, enum vdd_type vdd_type)
3600 return (set_directory_record(NULL, SIZE_MAX,
3601 isoent, iso9660, t, vdd_type));
3605 * Manage to write ISO-image data with wbuff to reduce calling
3606 * __archive_write_output() for performance.
3610 static inline unsigned char *
3611 wb_buffptr(struct archive_write *a)
3613 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3615 return (&(iso9660->wbuff[sizeof(iso9660->wbuff)
3616 - iso9660->wbuff_remaining]));
3620 wb_write_out(struct archive_write *a)
3622 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3626 wsize = sizeof(iso9660->wbuff) - iso9660->wbuff_remaining;
3627 nw = wsize % LOGICAL_BLOCK_SIZE;
3628 if (iso9660->wbuff_type == WB_TO_STREAM)
3629 r = __archive_write_output(a, iso9660->wbuff, wsize - nw);
3631 r = write_to_temp(a, iso9660->wbuff, wsize - nw);
3632 /* Increase the offset. */
3633 iso9660->wbuff_offset += wsize - nw;
3634 if (iso9660->wbuff_offset > iso9660->wbuff_written)
3635 iso9660->wbuff_written = iso9660->wbuff_offset;
3636 iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
3638 iso9660->wbuff_remaining -= nw;
3639 memmove(iso9660->wbuff, iso9660->wbuff + wsize - nw, nw);
3645 wb_consume(struct archive_write *a, size_t size)
3647 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3649 if (size > iso9660->wbuff_remaining ||
3650 iso9660->wbuff_remaining == 0) {
3651 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
3652 "Internal Programing error: iso9660:wb_consume()"
3653 " size=%jd, wbuff_remaining=%jd",
3654 (intmax_t)size, (intmax_t)iso9660->wbuff_remaining);
3655 return (ARCHIVE_FATAL);
3657 iso9660->wbuff_remaining -= size;
3658 if (iso9660->wbuff_remaining < LOGICAL_BLOCK_SIZE)
3659 return (wb_write_out(a));
3660 return (ARCHIVE_OK);
3666 wb_set_offset(struct archive_write *a, int64_t off)
3668 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3669 int64_t used, ext_bytes;
3671 if (iso9660->wbuff_type != WB_TO_TEMP) {
3672 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
3673 "Internal Programing error: iso9660:wb_set_offset()");
3674 return (ARCHIVE_FATAL);
3677 used = sizeof(iso9660->wbuff) - iso9660->wbuff_remaining;
3678 if (iso9660->wbuff_offset + used > iso9660->wbuff_tail)
3679 iso9660->wbuff_tail = iso9660->wbuff_offset + used;
3680 if (iso9660->wbuff_offset < iso9660->wbuff_written) {
3682 write_to_temp(a, iso9660->wbuff, (size_t)used) != ARCHIVE_OK)
3683 return (ARCHIVE_FATAL);
3684 iso9660->wbuff_offset = iso9660->wbuff_written;
3685 lseek(iso9660->temp_fd, iso9660->wbuff_offset, SEEK_SET);
3686 iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
3689 if (off < iso9660->wbuff_offset) {
3691 * Write out waiting data.
3694 if (wb_write_out(a) != ARCHIVE_OK)
3695 return (ARCHIVE_FATAL);
3697 lseek(iso9660->temp_fd, off, SEEK_SET);
3698 iso9660->wbuff_offset = off;
3699 iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
3700 } else if (off <= iso9660->wbuff_tail) {
3701 iso9660->wbuff_remaining = (size_t)
3702 (sizeof(iso9660->wbuff) - (off - iso9660->wbuff_offset));
3704 ext_bytes = off - iso9660->wbuff_tail;
3705 iso9660->wbuff_remaining = (size_t)(sizeof(iso9660->wbuff)
3706 - (iso9660->wbuff_tail - iso9660->wbuff_offset));
3707 while (ext_bytes >= (int64_t)iso9660->wbuff_remaining) {
3708 if (write_null(a, (size_t)iso9660->wbuff_remaining)
3710 return (ARCHIVE_FATAL);
3711 ext_bytes -= iso9660->wbuff_remaining;
3713 if (ext_bytes > 0) {
3714 if (write_null(a, (size_t)ext_bytes) != ARCHIVE_OK)
3715 return (ARCHIVE_FATAL);
3718 return (ARCHIVE_OK);
3721 #endif /* HAVE_ZLIB_H */
3724 write_null(struct archive_write *a, size_t size)
3727 unsigned char *p, *old;
3730 remaining = wb_remaining(a);
3732 if (size <= remaining) {
3734 return (wb_consume(a, size));
3736 memset(p, 0, remaining);
3737 r = wb_consume(a, remaining);
3738 if (r != ARCHIVE_OK)
3743 memset(p, 0, old - p);
3744 remaining = wb_remaining(a);
3746 size_t wsize = size;
3748 if (wsize > remaining)
3750 r = wb_consume(a, wsize);
3751 if (r != ARCHIVE_OK)
3755 return (ARCHIVE_OK);
3759 * Write Volume Descriptor Set Terminator
3762 write_VD_terminator(struct archive_write *a)
3766 bp = wb_buffptr(a) -1;
3767 set_VD_bp(bp, VDT_TERMINATOR, 1);
3768 set_unused_field_bp(bp, 8, LOGICAL_BLOCK_SIZE);
3770 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
3774 set_file_identifier(unsigned char *bp, int from, int to, enum vdc vdc,
3775 struct archive_write *a, struct vdd *vdd, struct archive_string *id,
3776 const char *label, int leading_under, enum char_type char_type)
3778 char identifier[256];
3779 struct isoent *isoent;
3784 if (id->length > 0 && leading_under && id->s[0] != '_') {
3785 if (char_type == A_CHAR)
3786 r = set_str_a_characters_bp(a, bp, from, to, id->s, vdc);
3788 r = set_str_d_characters_bp(a, bp, from, to, id->s, vdc);
3789 } else if (id->length > 0) {
3793 isoent = isoent_find_entry(vdd->rootent, ids);
3794 if (isoent == NULL) {
3795 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
3796 "Not Found %s `%s'.",
3798 return (ARCHIVE_FATAL);
3800 len = isoent->ext_off + isoent->ext_len;
3801 if (vdd->vdd_type == VDD_JOLIET) {
3802 if (len > sizeof(identifier)-2)
3803 len = sizeof(identifier)-2;
3805 if (len > sizeof(identifier)-1)
3806 len = sizeof(identifier)-1;
3808 memcpy(identifier, isoent->identifier, len);
3809 identifier[len] = '\0';
3810 if (vdd->vdd_type == VDD_JOLIET) {
3811 identifier[len+1] = 0;
3812 vdc = VDC_UCS2_DIRECT;
3814 if (char_type == A_CHAR)
3815 r = set_str_a_characters_bp(a, bp, from, to,
3818 r = set_str_d_characters_bp(a, bp, from, to,
3821 if (char_type == A_CHAR)
3822 r = set_str_a_characters_bp(a, bp, from, to, NULL, vdc);
3824 r = set_str_d_characters_bp(a, bp, from, to, NULL, vdc);
3830 * Write Primary/Supplementary Volume Descriptor
3833 write_VD(struct archive_write *a, struct vdd *vdd)
3835 struct iso9660 *iso9660;
3837 uint16_t volume_set_size = 1;
3838 char identifier[256];
3841 unsigned char vd_ver, fst_ver;
3844 iso9660 = a->format_data;
3845 switch (vdd->vdd_type) {
3847 vdt = VDT_SUPPLEMENTARY;
3848 vd_ver = fst_ver = 1;
3852 vdt = VDT_SUPPLEMENTARY;
3853 vd_ver = fst_ver = 2;
3854 vdc = VDC_LOWERCASE;
3859 vd_ver = fst_ver = 1;
3860 #ifdef COMPAT_MKISOFS
3861 vdc = VDC_LOWERCASE;
3868 bp = wb_buffptr(a) -1;
3869 /* Volume Descriptor Type */
3870 set_VD_bp(bp, vdt, vd_ver);
3872 set_unused_field_bp(bp, 8, 8);
3873 /* System Identifier */
3874 get_system_identitier(identifier, sizeof(identifier));
3875 r = set_str_a_characters_bp(a, bp, 9, 40, identifier, vdc);
3876 if (r != ARCHIVE_OK)
3878 /* Volume Identifier */
3879 r = set_str_d_characters_bp(a, bp, 41, 72,
3880 iso9660->volume_identifier.s, vdc);
3881 if (r != ARCHIVE_OK)
3884 set_unused_field_bp(bp, 73, 80);
3885 /* Volume Space Size */
3886 set_num_733(bp+81, iso9660->volume_space_size);
3887 if (vdd->vdd_type == VDD_JOLIET) {
3888 /* Escape Sequences */
3889 bp[89] = 0x25;/* UCS-2 Level 3 */
3892 memset(bp + 92, 0, 120 - 92 + 1);
3895 set_unused_field_bp(bp, 89, 120);
3897 /* Volume Set Size */
3898 set_num_723(bp+121, volume_set_size);
3899 /* Volume Sequence Number */
3900 set_num_723(bp+125, iso9660->volume_sequence_number);
3901 /* Logical Block Size */
3902 set_num_723(bp+129, LOGICAL_BLOCK_SIZE);
3903 /* Path Table Size */
3904 set_num_733(bp+133, vdd->path_table_size);
3905 /* Location of Occurrence of Type L Path Table */
3906 set_num_731(bp+141, vdd->location_type_L_path_table);
3907 /* Location of Optional Occurrence of Type L Path Table */
3908 set_num_731(bp+145, 0);
3909 /* Location of Occurrence of Type M Path Table */
3910 set_num_732(bp+149, vdd->location_type_M_path_table);
3911 /* Location of Optional Occurrence of Type M Path Table */
3912 set_num_732(bp+153, 0);
3913 /* Directory Record for Root Directory(BP 157 to 190) */
3914 set_directory_record(bp+157, 190-157+1, vdd->rootent,
3915 iso9660, DIR_REC_VD, vdd->vdd_type);
3916 /* Volume Set Identifier */
3917 r = set_str_d_characters_bp(a, bp, 191, 318, "", vdc);
3918 if (r != ARCHIVE_OK)
3920 /* Publisher Identifier */
3921 r = set_file_identifier(bp, 319, 446, vdc, a, vdd,
3922 &(iso9660->publisher_identifier),
3923 "Publisher File", 1, A_CHAR);
3924 if (r != ARCHIVE_OK)
3926 /* Data Preparer Identifier */
3927 r = set_file_identifier(bp, 447, 574, vdc, a, vdd,
3928 &(iso9660->data_preparer_identifier),
3929 "Data Preparer File", 1, A_CHAR);
3930 if (r != ARCHIVE_OK)
3932 /* Application Identifier */
3933 r = set_file_identifier(bp, 575, 702, vdc, a, vdd,
3934 &(iso9660->application_identifier),
3935 "Application File", 1, A_CHAR);
3936 if (r != ARCHIVE_OK)
3938 /* Copyright File Identifier */
3939 r = set_file_identifier(bp, 703, 739, vdc, a, vdd,
3940 &(iso9660->copyright_file_identifier),
3941 "Copyright File", 0, D_CHAR);
3942 if (r != ARCHIVE_OK)
3944 /* Abstract File Identifier */
3945 r = set_file_identifier(bp, 740, 776, vdc, a, vdd,
3946 &(iso9660->abstract_file_identifier),
3947 "Abstract File", 0, D_CHAR);
3948 if (r != ARCHIVE_OK)
3950 /* Bibliongraphic File Identifier */
3951 r = set_file_identifier(bp, 777, 813, vdc, a, vdd,
3952 &(iso9660->bibliographic_file_identifier),
3953 "Bibliongraphic File", 0, D_CHAR);
3954 if (r != ARCHIVE_OK)
3956 /* Volume Creation Date and Time */
3957 set_date_time(bp+814, iso9660->birth_time);
3958 /* Volume Modification Date and Time */
3959 set_date_time(bp+831, iso9660->birth_time);
3960 /* Volume Expiration Date and Time(obsolete) */
3961 set_date_time_null(bp+848);
3962 /* Volume Effective Date and Time */
3963 set_date_time(bp+865, iso9660->birth_time);
3964 /* File Structure Version */
3968 /* Application Use */
3969 memset(bp + 884, 0x20, 1395 - 884 + 1);
3971 set_unused_field_bp(bp, 1396, LOGICAL_BLOCK_SIZE);
3973 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
3977 * Write Boot Record Volume Descriptor
3980 write_VD_boot_record(struct archive_write *a)
3982 struct iso9660 *iso9660;
3985 iso9660 = a->format_data;
3986 bp = wb_buffptr(a) -1;
3987 /* Volume Descriptor Type */
3988 set_VD_bp(bp, VDT_BOOT_RECORD, 1);
3989 /* Boot System Identifier */
3990 memcpy(bp+8, "EL TORITO SPECIFICATION", 23);
3991 set_unused_field_bp(bp, 8+23, 39);
3993 set_unused_field_bp(bp, 40, 71);
3994 /* Absolute pointer to first sector of Boot Catalog */
3996 iso9660->el_torito.catalog->file->content.location);
3998 set_unused_field_bp(bp, 76, LOGICAL_BLOCK_SIZE);
4000 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4010 set_option_info(struct archive_string *info, int *opt, const char *key,
4011 enum keytype type, ...)
4018 prefix = (*opt==0)? ' ':',';
4022 d = va_arg(ap, int);
4023 archive_string_sprintf(info, "%c%s%s",
4024 prefix, (d == 0)?"!":"", key);
4027 s = va_arg(ap, const char *);
4028 archive_string_sprintf(info, "%c%s=%s",
4032 d = va_arg(ap, int);
4033 archive_string_sprintf(info, "%c%s=%d",
4037 d = va_arg(ap, int);
4038 archive_string_sprintf(info, "%c%s=%x",
4048 * Make Non-ISO File System Information
4051 write_information_block(struct archive_write *a)
4053 struct iso9660 *iso9660;
4057 struct archive_string info;
4058 size_t info_size = LOGICAL_BLOCK_SIZE *
4059 NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK;
4061 iso9660 = (struct iso9660 *)a->format_data;
4062 if (info_size > wb_remaining(a)) {
4063 r = wb_write_out(a);
4064 if (r != ARCHIVE_OK)
4067 archive_string_init(&info);
4068 if (archive_string_ensure(&info, info_size) == NULL) {
4069 archive_set_error(&a->archive, ENOMEM,
4070 "Can't allocate memory");
4071 return (ARCHIVE_FATAL);
4073 memset(info.s, 0, info_size);
4075 #if defined(HAVE__CTIME64_S)
4076 _ctime64_s(buf, sizeof(buf), &(iso9660->birth_time));
4077 #elif defined(HAVE_CTIME_R)
4078 ctime_r(&(iso9660->birth_time), buf);
4080 strncpy(buf, ctime(&(iso9660->birth_time)), sizeof(buf)-1);
4081 buf[sizeof(buf)-1] = '\0';
4083 archive_string_sprintf(&info,
4084 "INFO %s%s", buf, archive_version_string());
4085 if (iso9660->opt.abstract_file != OPT_ABSTRACT_FILE_DEFAULT)
4086 set_option_info(&info, &opt, "abstract-file",
4087 KEY_STR, iso9660->abstract_file_identifier.s);
4088 if (iso9660->opt.application_id != OPT_APPLICATION_ID_DEFAULT)
4089 set_option_info(&info, &opt, "application-id",
4090 KEY_STR, iso9660->application_identifier.s);
4091 if (iso9660->opt.allow_vernum != OPT_ALLOW_VERNUM_DEFAULT)
4092 set_option_info(&info, &opt, "allow-vernum",
4093 KEY_FLG, iso9660->opt.allow_vernum);
4094 if (iso9660->opt.biblio_file != OPT_BIBLIO_FILE_DEFAULT)
4095 set_option_info(&info, &opt, "biblio-file",
4096 KEY_STR, iso9660->bibliographic_file_identifier.s);
4097 if (iso9660->opt.boot != OPT_BOOT_DEFAULT)
4098 set_option_info(&info, &opt, "boot",
4099 KEY_STR, iso9660->el_torito.boot_filename.s);
4100 if (iso9660->opt.boot_catalog != OPT_BOOT_CATALOG_DEFAULT)
4101 set_option_info(&info, &opt, "boot-catalog",
4102 KEY_STR, iso9660->el_torito.catalog_filename.s);
4103 if (iso9660->opt.boot_info_table != OPT_BOOT_INFO_TABLE_DEFAULT)
4104 set_option_info(&info, &opt, "boot-info-table",
4105 KEY_FLG, iso9660->opt.boot_info_table);
4106 if (iso9660->opt.boot_load_seg != OPT_BOOT_LOAD_SEG_DEFAULT)
4107 set_option_info(&info, &opt, "boot-load-seg",
4108 KEY_HEX, iso9660->el_torito.boot_load_seg);
4109 if (iso9660->opt.boot_load_size != OPT_BOOT_LOAD_SIZE_DEFAULT)
4110 set_option_info(&info, &opt, "boot-load-size",
4111 KEY_INT, iso9660->el_torito.boot_load_size);
4112 if (iso9660->opt.boot_type != OPT_BOOT_TYPE_DEFAULT) {
4114 if (iso9660->opt.boot_type == OPT_BOOT_TYPE_FD)
4116 if (iso9660->opt.boot_type == OPT_BOOT_TYPE_HARD_DISK)
4118 set_option_info(&info, &opt, "boot-type",
4122 if (iso9660->opt.compression_level != OPT_COMPRESSION_LEVEL_DEFAULT)
4123 set_option_info(&info, &opt, "compression-level",
4124 KEY_INT, iso9660->zisofs.compression_level);
4126 if (iso9660->opt.copyright_file != OPT_COPYRIGHT_FILE_DEFAULT)
4127 set_option_info(&info, &opt, "copyright-file",
4128 KEY_STR, iso9660->copyright_file_identifier.s);
4129 if (iso9660->opt.iso_level != OPT_ISO_LEVEL_DEFAULT)
4130 set_option_info(&info, &opt, "iso-level",
4131 KEY_INT, iso9660->opt.iso_level);
4132 if (iso9660->opt.joliet != OPT_JOLIET_DEFAULT) {
4133 if (iso9660->opt.joliet == OPT_JOLIET_LONGNAME)
4134 set_option_info(&info, &opt, "joliet",
4137 set_option_info(&info, &opt, "joliet",
4138 KEY_FLG, iso9660->opt.joliet);
4140 if (iso9660->opt.limit_depth != OPT_LIMIT_DEPTH_DEFAULT)
4141 set_option_info(&info, &opt, "limit-depth",
4142 KEY_FLG, iso9660->opt.limit_depth);
4143 if (iso9660->opt.limit_dirs != OPT_LIMIT_DIRS_DEFAULT)
4144 set_option_info(&info, &opt, "limit-dirs",
4145 KEY_FLG, iso9660->opt.limit_dirs);
4146 if (iso9660->opt.pad != OPT_PAD_DEFAULT)
4147 set_option_info(&info, &opt, "pad",
4148 KEY_FLG, iso9660->opt.pad);
4149 if (iso9660->opt.publisher != OPT_PUBLISHER_DEFAULT)
4150 set_option_info(&info, &opt, "publisher",
4151 KEY_STR, iso9660->publisher_identifier.s);
4152 if (iso9660->opt.rr != OPT_RR_DEFAULT) {
4153 if (iso9660->opt.rr == OPT_RR_DISABLED)
4154 set_option_info(&info, &opt, "rockridge",
4155 KEY_FLG, iso9660->opt.rr);
4156 else if (iso9660->opt.rr == OPT_RR_STRICT)
4157 set_option_info(&info, &opt, "rockridge",
4159 else if (iso9660->opt.rr == OPT_RR_USEFUL)
4160 set_option_info(&info, &opt, "rockridge",
4163 if (iso9660->opt.volume_id != OPT_VOLUME_ID_DEFAULT)
4164 set_option_info(&info, &opt, "volume-id",
4165 KEY_STR, iso9660->volume_identifier.s);
4166 if (iso9660->opt.zisofs != OPT_ZISOFS_DEFAULT)
4167 set_option_info(&info, &opt, "zisofs",
4168 KEY_FLG, iso9660->opt.zisofs);
4170 memcpy(wb_buffptr(a), info.s, info_size);
4171 archive_string_free(&info);
4172 return (wb_consume(a, info_size));
4176 write_rr_ER(struct archive_write *a)
4182 memset(p, 0, LOGICAL_BLOCK_SIZE);
4186 p[2] = RRIP_ER_SIZE;
4187 p[4] = RRIP_ER_ID_SIZE;
4188 p[5] = RRIP_ER_DSC_SIZE;
4189 p[6] = RRIP_ER_SRC_SIZE;
4191 memcpy(&p[8], rrip_identifier, p[4]);
4192 memcpy(&p[8+p[4]], rrip_descriptor, p[5]);
4193 memcpy(&p[8+p[4]+p[5]], rrip_source, p[6]);
4195 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4199 calculate_path_table_size(struct vdd *vdd)
4202 struct path_table *pt;
4206 for (depth = 0; depth < vdd->max_depth; depth++) {
4207 struct isoent **ptbl;
4210 if ((cnt = pt[depth].cnt) == 0)
4213 ptbl = pt[depth].sorted;
4214 for (i = 0; i < cnt; i++) {
4217 if (ptbl[i]->identifier == NULL)
4218 len = 1; /* root directory */
4220 len = ptbl[i]->id_len;
4222 len++; /* Padding Field */
4226 vdd->path_table_size = size;
4227 vdd->path_table_block =
4228 ((size + PATH_TABLE_BLOCK_SIZE -1) /
4229 PATH_TABLE_BLOCK_SIZE) *
4230 (PATH_TABLE_BLOCK_SIZE / LOGICAL_BLOCK_SIZE);
4234 _write_path_table(struct archive_write *a, int type_m, int depth,
4237 unsigned char *bp, *wb;
4238 struct isoent **ptbl;
4242 if (vdd->pathtbl[depth].cnt == 0)
4247 wbremaining = wb_remaining(a);
4249 ptbl = vdd->pathtbl[depth].sorted;
4250 for (i = 0; i < vdd->pathtbl[depth].cnt; i++) {
4255 if (np->identifier == NULL)
4256 len = 1; /* root directory */
4259 if (wbremaining - ((bp+1) - wb) < (len + 1 + 8)) {
4260 r = wb_consume(a, (bp+1) - wb);
4264 wbremaining = wb_remaining(a);
4267 /* Length of Directory Identifier */
4268 set_num_711(bp+1, (unsigned char)len);
4269 /* Extended Attribute Record Length */
4270 set_num_711(bp+2, 0);
4271 /* Location of Extent */
4273 set_num_732(bp+3, np->dir_location);
4275 set_num_731(bp+3, np->dir_location);
4276 /* Parent Directory Number */
4278 set_num_722(bp+7, np->parent->dir_number);
4280 set_num_721(bp+7, np->parent->dir_number);
4281 /* Directory Identifier */
4282 if (np->identifier == NULL)
4285 memcpy(&bp[9], np->identifier, len);
4291 wsize += 8 + (int)len;
4294 if ((bp + 1) > wb) {
4295 r = wb_consume(a, (bp+1)-wb);
4303 write_path_table(struct archive_write *a, int type_m, struct vdd *vdd)
4306 size_t path_table_size;
4309 path_table_size = 0;
4310 for (depth = 0; depth < vdd->max_depth; depth++) {
4311 r = _write_path_table(a, type_m, depth, vdd);
4314 path_table_size += r;
4317 /* Write padding data. */
4318 path_table_size = path_table_size % PATH_TABLE_BLOCK_SIZE;
4319 if (path_table_size > 0)
4320 r = write_null(a, PATH_TABLE_BLOCK_SIZE - path_table_size);
4325 calculate_directory_descriptors(struct iso9660 *iso9660, struct vdd *vdd,
4326 struct isoent *isoent, int depth)
4328 struct isoent **enttbl;
4332 bs = get_dir_rec_size(iso9660, isoent, DIR_REC_SELF, vdd->vdd_type);
4333 bs += get_dir_rec_size(iso9660, isoent, DIR_REC_PARENT, vdd->vdd_type);
4335 if (isoent->children.cnt <= 0 || (vdd->vdd_type != VDD_JOLIET &&
4336 !iso9660->opt.rr && depth + 1 >= vdd->max_depth))
4339 enttbl = isoent->children_sorted;
4340 for (i = 0; i < isoent->children.cnt; i++) {
4341 struct isoent *np = enttbl[i];
4342 struct isofile *file;
4345 if (file->hardlink_target != NULL)
4346 file = file->hardlink_target;
4347 file->cur_content = &(file->content);
4351 dr_l = get_dir_rec_size(iso9660, np, DIR_REC_NORMAL,
4353 if ((bs + dr_l) > LOGICAL_BLOCK_SIZE) {
4358 file->cur_content = file->cur_content->next;
4359 } while (file->cur_content != NULL);
4365 _write_directory_descriptors(struct archive_write *a, struct vdd *vdd,
4366 struct isoent *isoent, int depth)
4368 struct iso9660 *iso9660 = a->format_data;
4369 struct isoent **enttbl;
4370 unsigned char *p, *wb;
4374 p = wb = wb_buffptr(a);
4375 #define WD_REMAINING (LOGICAL_BLOCK_SIZE - (p - wb))
4376 p += set_directory_record(p, WD_REMAINING, isoent,
4377 iso9660, DIR_REC_SELF, vdd->vdd_type);
4378 p += set_directory_record(p, WD_REMAINING, isoent,
4379 iso9660, DIR_REC_PARENT, vdd->vdd_type);
4381 if (isoent->children.cnt <= 0 || (vdd->vdd_type != VDD_JOLIET &&
4382 !iso9660->opt.rr && depth + 1 >= vdd->max_depth)) {
4383 memset(p, 0, WD_REMAINING);
4384 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4387 enttbl = isoent->children_sorted;
4388 for (i = 0; i < isoent->children.cnt; i++) {
4389 struct isoent *np = enttbl[i];
4390 struct isofile *file = np->file;
4392 if (file->hardlink_target != NULL)
4393 file = file->hardlink_target;
4394 file->cur_content = &(file->content);
4396 dr_l = set_directory_record(p, WD_REMAINING,
4397 np, iso9660, DIR_REC_NORMAL,
4400 memset(p, 0, WD_REMAINING);
4401 r = wb_consume(a, LOGICAL_BLOCK_SIZE);
4404 p = wb = wb_buffptr(a);
4405 dr_l = set_directory_record(p,
4406 WD_REMAINING, np, iso9660,
4407 DIR_REC_NORMAL, vdd->vdd_type);
4410 file->cur_content = file->cur_content->next;
4411 } while (file->cur_content != NULL);
4413 memset(p, 0, WD_REMAINING);
4414 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4418 write_directory_descriptors(struct archive_write *a, struct vdd *vdd)
4426 struct extr_rec *extr;
4428 r = _write_directory_descriptors(a, vdd, np, depth);
4431 if (vdd->vdd_type != VDD_JOLIET) {
4433 * This extract record is used by SUSP,RRIP.
4436 for (extr = np->extr_rec_list.first;
4438 extr = extr->next) {
4442 memcpy(wb, extr->buf, extr->offset);
4443 memset(wb + extr->offset, 0,
4444 LOGICAL_BLOCK_SIZE - extr->offset);
4445 r = wb_consume(a, LOGICAL_BLOCK_SIZE);
4451 if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) {
4452 /* Enter to sub directories. */
4453 np = np->subdirs.first;
4457 while (np != np->parent) {
4458 if (np->drnext == NULL) {
4459 /* Return to the parent directory. */
4467 } while (np != np->parent);
4469 return (ARCHIVE_OK);
4473 * Read file contents from the temporary file, and write it.
4476 write_file_contents(struct archive_write *a, int64_t offset, int64_t size)
4478 struct iso9660 *iso9660 = a->format_data;
4481 lseek(iso9660->temp_fd, offset, SEEK_SET);
4489 rsize = wb_remaining(a);
4490 if (rsize > (size_t)size)
4491 rsize = (size_t)size;
4492 rs = read(iso9660->temp_fd, wb, rsize);
4494 archive_set_error(&a->archive, errno,
4495 "Can't read temporary file(%jd)", (intmax_t)rs);
4496 return (ARCHIVE_FATAL);
4499 r = wb_consume(a, rs);
4503 return (ARCHIVE_OK);
4507 write_file_descriptors(struct archive_write *a)
4509 struct iso9660 *iso9660 = a->format_data;
4510 struct isofile *file;
4511 int64_t blocks, offset;
4517 /* Make the boot catalog contents, and write it. */
4518 if (iso9660->el_torito.catalog != NULL) {
4519 r = make_boot_catalog(a);
4524 /* Write the boot file contents. */
4525 if (iso9660->el_torito.boot != NULL) {
4526 file = iso9660->el_torito.boot->file;
4527 blocks = file->content.blocks;
4528 offset = file->content.offset_of_temp;
4530 r = write_file_contents(a, offset,
4531 blocks << LOGICAL_BLOCK_BITS);
4539 /* Write out all file contents. */
4540 for (file = iso9660->data_file_list.first;
4541 file != NULL; file = file->datanext) {
4543 if (!file->write_content)
4546 if ((offset + (blocks << LOGICAL_BLOCK_BITS)) <
4547 file->content.offset_of_temp) {
4549 r = write_file_contents(a, offset,
4550 blocks << LOGICAL_BLOCK_BITS);
4555 offset = file->content.offset_of_temp;
4558 file->cur_content = &(file->content);
4560 blocks += file->cur_content->blocks;
4561 /* Next fragument */
4562 file->cur_content = file->cur_content->next;
4563 } while (file->cur_content != NULL);
4566 /* Flush out remaining blocks. */
4568 r = write_file_contents(a, offset,
4569 blocks << LOGICAL_BLOCK_BITS);
4574 return (ARCHIVE_OK);
4578 isofile_init_entry_list(struct iso9660 *iso9660)
4580 iso9660->all_file_list.first = NULL;
4581 iso9660->all_file_list.last = &(iso9660->all_file_list.first);
4585 isofile_add_entry(struct iso9660 *iso9660, struct isofile *file)
4587 file->allnext = NULL;
4588 *iso9660->all_file_list.last = file;
4589 iso9660->all_file_list.last = &(file->allnext);
4593 isofile_free_all_entries(struct iso9660 *iso9660)
4595 struct isofile *file, *file_next;
4597 file = iso9660->all_file_list.first;
4598 while (file != NULL) {
4599 file_next = file->allnext;
4606 isofile_init_entry_data_file_list(struct iso9660 *iso9660)
4608 iso9660->data_file_list.first = NULL;
4609 iso9660->data_file_list.last = &(iso9660->data_file_list.first);
4613 isofile_add_data_file(struct iso9660 *iso9660, struct isofile *file)
4615 file->datanext = NULL;
4616 *iso9660->data_file_list.last = file;
4617 iso9660->data_file_list.last = &(file->datanext);
4621 static struct isofile *
4622 isofile_new(struct archive_write *a, struct archive_entry *entry)
4624 struct isofile *file;
4626 file = calloc(1, sizeof(*file));
4631 file->entry = archive_entry_clone(entry);
4633 file->entry = archive_entry_new2(&a->archive);
4634 if (file->entry == NULL) {
4638 archive_string_init(&(file->parentdir));
4639 archive_string_init(&(file->basename));
4640 archive_string_init(&(file->basename_utf16));
4641 archive_string_init(&(file->symlink));
4642 file->cur_content = &(file->content);
4648 isofile_free(struct isofile *file)
4650 struct content *con, *tmp;
4652 con = file->content.next;
4653 while (con != NULL) {
4658 archive_entry_free(file->entry);
4659 archive_string_free(&(file->parentdir));
4660 archive_string_free(&(file->basename));
4661 archive_string_free(&(file->basename_utf16));
4662 archive_string_free(&(file->symlink));
4666 #if defined(_WIN32) || defined(__CYGWIN__)
4668 cleanup_backslash_1(char *p)
4674 if (*(unsigned char *)p > 127)
4677 /* If we have not met any multi-byte characters,
4678 * we can replace '\' with '/'. */
4691 cleanup_backslash_2(wchar_t *p)
4694 /* Convert a path-separator from '\' to '/' */
4695 while (*p != L'\0') {
4704 * Generate a parent directory name and a base name from a pathname.
4707 isofile_gen_utility_names(struct archive_write *a, struct isofile *file)
4709 struct iso9660 *iso9660;
4710 const char *pathname;
4711 char *p, *dirname, *slash;
4713 int ret = ARCHIVE_OK;
4715 iso9660 = a->format_data;
4717 archive_string_empty(&(file->parentdir));
4718 archive_string_empty(&(file->basename));
4719 archive_string_empty(&(file->basename_utf16));
4720 archive_string_empty(&(file->symlink));
4722 pathname = archive_entry_pathname(file->entry);
4723 if (pathname == NULL || pathname[0] == '\0') {/* virtual root */
4729 * Make a UTF-16BE basename if Joliet extension enabled.
4731 if (iso9660->opt.joliet) {
4732 const char *u16, *ulast;
4733 size_t u16len, ulen_last;
4735 if (iso9660->sconv_to_utf16be == NULL) {
4736 iso9660->sconv_to_utf16be =
4737 archive_string_conversion_to_charset(
4738 &(a->archive), "UTF-16BE", 1);
4739 if (iso9660->sconv_to_utf16be == NULL)
4740 /* Couldn't allocate memory */
4741 return (ARCHIVE_FATAL);
4742 iso9660->sconv_from_utf16be =
4743 archive_string_conversion_from_charset(
4744 &(a->archive), "UTF-16BE", 1);
4745 if (iso9660->sconv_from_utf16be == NULL)
4746 /* Couldn't allocate memory */
4747 return (ARCHIVE_FATAL);
4751 * Converte a filename to UTF-16BE.
4753 if (0 > archive_entry_pathname_l(file->entry, &u16, &u16len,
4754 iso9660->sconv_to_utf16be)) {
4755 if (errno == ENOMEM) {
4756 archive_set_error(&a->archive, ENOMEM,
4757 "Can't allocate memory for UTF-16BE");
4758 return (ARCHIVE_FATAL);
4760 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
4761 "A filename cannot be converted to UTF-16BE;"
4762 "You should disable making Joliet extension");
4767 * Make sure a path separator is not in the last;
4768 * Remove trailing '/'.
4770 while (u16len >= 2) {
4771 #if defined(_WIN32) || defined(__CYGWIN__)
4772 if (u16[u16len-2] == 0 &&
4773 (u16[u16len-1] == '/' || u16[u16len-1] == '\\'))
4775 if (u16[u16len-2] == 0 && u16[u16len-1] == '/')
4784 * Find a basename in UTF-16BE.
4789 while (u16len > 0) {
4790 #if defined(_WIN32) || defined(__CYGWIN__)
4791 if (u16[0] == 0 && (u16[1] == '/' || u16[1] == '\\'))
4793 if (u16[0] == 0 && u16[1] == '/')
4797 ulen_last = u16len -1;
4803 if (archive_string_ensure(&(file->basename_utf16),
4804 ulen_last) == NULL) {
4805 archive_set_error(&a->archive, ENOMEM,
4806 "Can't allocate memory for UTF-16BE");
4807 return (ARCHIVE_FATAL);
4811 * Set UTF-16BE basename.
4813 memcpy(file->basename_utf16.s, ulast, ulen_last);
4814 file->basename_utf16.length = ulen_last;
4817 archive_strcpy(&(file->parentdir), pathname);
4818 #if defined(_WIN32) || defined(__CYGWIN__)
4820 * Convert a path-separator from '\' to '/'
4822 if (cleanup_backslash_1(file->parentdir.s) != 0) {
4823 const wchar_t *wp = archive_entry_pathname_w(file->entry);
4824 struct archive_wstring ws;
4828 archive_string_init(&ws);
4829 archive_wstrcpy(&ws, wp);
4830 cleanup_backslash_2(ws.s);
4831 archive_string_empty(&(file->parentdir));
4832 r = archive_string_append_from_wcs(&(file->parentdir),
4834 archive_wstring_free(&ws);
4835 if (r < 0 && errno == ENOMEM) {
4836 archive_set_error(&a->archive, ENOMEM,
4837 "Can't allocate memory");
4838 return (ARCHIVE_FATAL);
4844 len = file->parentdir.length;
4845 p = dirname = file->parentdir.s;
4848 * Remove leading '/', '../' and './' elements
4854 } else if (p[0] != '.')
4856 else if (p[1] == '.' && p[2] == '/') {
4859 } else if (p[1] == '/' || (p[1] == '.' && p[2] == '\0')) {
4862 } else if (p[1] == '\0') {
4869 memmove(dirname, p, len+1);
4873 * Remove "/","/." and "/.." elements from tail.
4878 if (len > 0 && p[len-1] == '/') {
4882 if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
4886 if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
4897 /* Convert '//' --> '/' */
4899 else if (p[1] == '.' && p[2] == '/')
4900 /* Convert '/./' --> '/' */
4902 else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
4903 /* Convert 'dir/dir1/../dir2/'
4907 while (rp >= dirname) {
4916 strcpy(dirname, p+4);
4927 if (archive_entry_filetype(file->entry) == AE_IFLNK) {
4928 /* Convert symlink name too. */
4929 pathname = archive_entry_symlink(file->entry);
4930 archive_strcpy(&(file->symlink), pathname);
4931 #if defined(_WIN32) || defined(__CYGWIN__)
4933 * Convert a path-separator from '\' to '/'
4935 if (archive_strlen(&(file->symlink)) > 0 &&
4936 cleanup_backslash_1(file->symlink.s) != 0) {
4938 archive_entry_symlink_w(file->entry);
4939 struct archive_wstring ws;
4943 archive_string_init(&ws);
4944 archive_wstrcpy(&ws, wp);
4945 cleanup_backslash_2(ws.s);
4946 archive_string_empty(&(file->symlink));
4947 r = archive_string_append_from_wcs(
4950 archive_wstring_free(&ws);
4951 if (r < 0 && errno == ENOMEM) {
4952 archive_set_error(&a->archive, ENOMEM,
4953 "Can't allocate memory");
4954 return (ARCHIVE_FATAL);
4961 * - Count up directory elements.
4962 * - Find out the position which points the last position of
4963 * path separator('/').
4967 for (; *p != '\0'; p++)
4972 if (slash == NULL) {
4973 /* The pathname doesn't have a parent directory. */
4974 file->parentdir.length = len;
4975 archive_string_copy(&(file->basename), &(file->parentdir));
4976 archive_string_empty(&(file->parentdir));
4977 *file->parentdir.s = '\0';
4981 /* Make a basename from dirname and slash */
4983 file->parentdir.length = slash - dirname;
4984 archive_strcpy(&(file->basename), slash + 1);
4985 if (archive_entry_filetype(file->entry) == AE_IFDIR)
4991 * Register a entry to get a hardlink target.
4994 isofile_register_hardlink(struct archive_write *a, struct isofile *file)
4996 struct iso9660 *iso9660 = a->format_data;
4997 struct hardlink *hl;
4998 const char *pathname;
5000 archive_entry_set_nlink(file->entry, 1);
5001 pathname = archive_entry_hardlink(file->entry);
5002 if (pathname == NULL) {
5003 /* This `file` is a hardlink target. */
5004 hl = malloc(sizeof(*hl));
5006 archive_set_error(&a->archive, ENOMEM,
5007 "Can't allocate memory");
5008 return (ARCHIVE_FATAL);
5011 /* A hardlink target must be the first position. */
5012 file->hlnext = NULL;
5013 hl->file_list.first = file;
5014 hl->file_list.last = &(file->hlnext);
5015 __archive_rb_tree_insert_node(&(iso9660->hardlink_rbtree),
5016 (struct archive_rb_node *)hl);
5018 hl = (struct hardlink *)__archive_rb_tree_find_node(
5019 &(iso9660->hardlink_rbtree), pathname);
5021 /* Insert `file` entry into the tail. */
5022 file->hlnext = NULL;
5023 *hl->file_list.last = file;
5024 hl->file_list.last = &(file->hlnext);
5027 archive_entry_unset_size(file->entry);
5030 return (ARCHIVE_OK);
5034 * Hardlinked files have to have the same location of extent.
5035 * We have to find out hardlink target entries for the entries
5036 * which have a hardlink target name.
5039 isofile_connect_hardlink_files(struct iso9660 *iso9660)
5041 struct archive_rb_node *n;
5042 struct hardlink *hl;
5043 struct isofile *target, *nf;
5045 ARCHIVE_RB_TREE_FOREACH(n, &(iso9660->hardlink_rbtree)) {
5046 hl = (struct hardlink *)n;
5048 /* The first entry must be a hardlink target. */
5049 target = hl->file_list.first;
5050 archive_entry_set_nlink(target->entry, hl->nlink);
5051 /* Set a hardlink target to reference entries. */
5052 for (nf = target->hlnext;
5053 nf != NULL; nf = nf->hlnext) {
5054 nf->hardlink_target = target;
5055 archive_entry_set_nlink(nf->entry, hl->nlink);
5061 isofile_hd_cmp_node(const struct archive_rb_node *n1,
5062 const struct archive_rb_node *n2)
5064 const struct hardlink *h1 = (const struct hardlink *)n1;
5065 const struct hardlink *h2 = (const struct hardlink *)n2;
5067 return (strcmp(archive_entry_pathname(h1->file_list.first->entry),
5068 archive_entry_pathname(h2->file_list.first->entry)));
5072 isofile_hd_cmp_key(const struct archive_rb_node *n, const void *key)
5074 const struct hardlink *h = (const struct hardlink *)n;
5076 return (strcmp(archive_entry_pathname(h->file_list.first->entry),
5077 (const char *)key));
5081 isofile_init_hardlinks(struct iso9660 *iso9660)
5083 static const struct archive_rb_tree_ops rb_ops = {
5084 isofile_hd_cmp_node, isofile_hd_cmp_key,
5087 __archive_rb_tree_init(&(iso9660->hardlink_rbtree), &rb_ops);
5091 isofile_free_hardlinks(struct iso9660 *iso9660)
5093 struct archive_rb_node *n, *next;
5095 for (n = ARCHIVE_RB_TREE_MIN(&(iso9660->hardlink_rbtree)); n;) {
5096 next = __archive_rb_tree_iterate(&(iso9660->hardlink_rbtree),
5097 n, ARCHIVE_RB_DIR_RIGHT);
5103 static struct isoent *
5104 isoent_new(struct isofile *file)
5106 struct isoent *isoent;
5107 static const struct archive_rb_tree_ops rb_ops = {
5108 isoent_cmp_node, isoent_cmp_key,
5111 isoent = calloc(1, sizeof(*isoent));
5114 isoent->file = file;
5115 isoent->children.first = NULL;
5116 isoent->children.last = &(isoent->children.first);
5117 __archive_rb_tree_init(&(isoent->rbtree), &rb_ops);
5118 isoent->subdirs.first = NULL;
5119 isoent->subdirs.last = &(isoent->subdirs.first);
5120 isoent->extr_rec_list.first = NULL;
5121 isoent->extr_rec_list.last = &(isoent->extr_rec_list.first);
5122 isoent->extr_rec_list.current = NULL;
5123 if (archive_entry_filetype(file->entry) == AE_IFDIR)
5129 static inline struct isoent *
5130 isoent_clone(struct isoent *src)
5132 return (isoent_new(src->file));
5136 _isoent_free(struct isoent *isoent)
5138 struct extr_rec *er, *er_next;
5140 free(isoent->children_sorted);
5141 free(isoent->identifier);
5142 er = isoent->extr_rec_list.first;
5143 while (er != NULL) {
5152 isoent_free_all(struct isoent *isoent)
5154 struct isoent *np, *np_temp;
5161 if (np->children.first != NULL) {
5162 /* Enter to sub directories. */
5163 np = np->children.first;
5169 if (np->chnext == NULL) {
5170 /* Return to the parent directory. */
5172 _isoent_free(np_temp);
5177 _isoent_free(np_temp);
5184 static struct isoent *
5185 isoent_create_virtual_dir(struct archive_write *a, struct iso9660 *iso9660, const char *pathname)
5187 struct isofile *file;
5188 struct isoent *isoent;
5190 file = isofile_new(a, NULL);
5193 archive_entry_set_pathname(file->entry, pathname);
5194 archive_entry_unset_mtime(file->entry);
5195 archive_entry_unset_atime(file->entry);
5196 archive_entry_unset_ctime(file->entry);
5197 archive_entry_set_uid(file->entry, getuid());
5198 archive_entry_set_gid(file->entry, getgid());
5199 archive_entry_set_mode(file->entry, 0555 | AE_IFDIR);
5200 archive_entry_set_nlink(file->entry, 2);
5201 if (isofile_gen_utility_names(a, file) < ARCHIVE_WARN) {
5205 isofile_add_entry(iso9660, file);
5207 isoent = isoent_new(file);
5211 isoent->virtual = 1;
5217 isoent_cmp_node(const struct archive_rb_node *n1,
5218 const struct archive_rb_node *n2)
5220 const struct isoent *e1 = (const struct isoent *)n1;
5221 const struct isoent *e2 = (const struct isoent *)n2;
5223 return (strcmp(e1->file->basename.s, e2->file->basename.s));
5227 isoent_cmp_key(const struct archive_rb_node *n, const void *key)
5229 const struct isoent *e = (const struct isoent *)n;
5231 return (strcmp(e->file->basename.s, (const char *)key));
5235 isoent_add_child_head(struct isoent *parent, struct isoent *child)
5238 if (!__archive_rb_tree_insert_node(
5239 &(parent->rbtree), (struct archive_rb_node *)child))
5241 if ((child->chnext = parent->children.first) == NULL)
5242 parent->children.last = &(child->chnext);
5243 parent->children.first = child;
5244 parent->children.cnt++;
5245 child->parent = parent;
5247 /* Add a child to a sub-directory chain */
5249 if ((child->drnext = parent->subdirs.first) == NULL)
5250 parent->subdirs.last = &(child->drnext);
5251 parent->subdirs.first = child;
5252 parent->subdirs.cnt++;
5253 child->parent = parent;
5255 child->drnext = NULL;
5260 isoent_add_child_tail(struct isoent *parent, struct isoent *child)
5263 if (!__archive_rb_tree_insert_node(
5264 &(parent->rbtree), (struct archive_rb_node *)child))
5266 child->chnext = NULL;
5267 *parent->children.last = child;
5268 parent->children.last = &(child->chnext);
5269 parent->children.cnt++;
5270 child->parent = parent;
5272 /* Add a child to a sub-directory chain */
5273 child->drnext = NULL;
5275 *parent->subdirs.last = child;
5276 parent->subdirs.last = &(child->drnext);
5277 parent->subdirs.cnt++;
5278 child->parent = parent;
5284 isoent_remove_child(struct isoent *parent, struct isoent *child)
5288 /* Remove a child entry from children chain. */
5289 ent = parent->children.first;
5290 while (ent->chnext != child)
5292 if ((ent->chnext = ent->chnext->chnext) == NULL)
5293 parent->children.last = &(ent->chnext);
5294 parent->children.cnt--;
5297 /* Remove a child entry from sub-directory chain. */
5298 ent = parent->subdirs.first;
5299 while (ent->drnext != child)
5301 if ((ent->drnext = ent->drnext->drnext) == NULL)
5302 parent->subdirs.last = &(ent->drnext);
5303 parent->subdirs.cnt--;
5306 __archive_rb_tree_remove_node(&(parent->rbtree),
5307 (struct archive_rb_node *)child);
5311 isoent_clone_tree(struct archive_write *a, struct isoent **nroot,
5312 struct isoent *root)
5314 struct isoent *np, *xroot, *newent;
5319 newent = isoent_clone(np);
5320 if (newent == NULL) {
5321 archive_set_error(&a->archive, ENOMEM,
5322 "Can't allocate memory");
5323 return (ARCHIVE_FATAL);
5325 if (xroot == NULL) {
5326 *nroot = xroot = newent;
5327 newent->parent = xroot;
5329 isoent_add_child_tail(xroot, newent);
5330 if (np->dir && np->children.first != NULL) {
5331 /* Enter to sub directories. */
5332 np = np->children.first;
5336 while (np != np->parent) {
5337 if (np->chnext == NULL) {
5338 /* Return to the parent directory. */
5340 xroot = xroot->parent;
5346 } while (np != np->parent);
5348 return (ARCHIVE_OK);
5352 * Setup directory locations.
5355 isoent_setup_directory_location(struct iso9660 *iso9660, int location,
5361 vdd->total_dir_block = 0;
5367 np->dir_block = calculate_directory_descriptors(
5368 iso9660, vdd, np, depth);
5369 vdd->total_dir_block += np->dir_block;
5370 np->dir_location = location;
5371 location += np->dir_block;
5372 block = extra_setup_location(np, location);
5373 vdd->total_dir_block += block;
5376 if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) {
5377 /* Enter to sub directories. */
5378 np = np->subdirs.first;
5382 while (np != np->parent) {
5383 if (np->drnext == NULL) {
5384 /* Return to the parent directory. */
5392 } while (np != np->parent);
5396 _isoent_file_location(struct iso9660 *iso9660, struct isoent *isoent,
5399 struct isoent **children;
5402 if (isoent->children.cnt == 0)
5405 children = isoent->children_sorted;
5406 for (n = 0; n < isoent->children.cnt; n++) {
5408 struct isofile *file;
5413 if (np == iso9660->el_torito.boot)
5416 if (file->boot || file->hardlink_target != NULL)
5418 if (archive_entry_filetype(file->entry) == AE_IFLNK ||
5419 file->content.size == 0) {
5421 * Do not point a valid location.
5422 * Make sure entry is not hardlink file.
5424 file->content.location = (*symlocation)--;
5428 file->write_content = 1;
5433 * Setup file locations.
5436 isoent_setup_file_location(struct iso9660 *iso9660, int location)
5438 struct isoent *isoent;
5440 struct isofile *file;
5448 iso9660->total_file_block = 0;
5449 if ((isoent = iso9660->el_torito.catalog) != NULL) {
5450 isoent->file->content.location = location;
5451 block = (int)((archive_entry_size(isoent->file->entry) +
5452 LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS);
5454 iso9660->total_file_block += block;
5456 if ((isoent = iso9660->el_torito.boot) != NULL) {
5457 isoent->file->content.location = location;
5458 size = fd_boot_image_size(iso9660->el_torito.media_type);
5460 size = (size_t)archive_entry_size(isoent->file->entry);
5461 block = ((int)size + LOGICAL_BLOCK_SIZE -1)
5462 >> LOGICAL_BLOCK_BITS;
5464 iso9660->total_file_block += block;
5465 isoent->file->content.blocks = block;
5470 if (!iso9660->opt.rr && iso9660->opt.joliet) {
5472 np = iso9660->joliet.rootent;
5475 np = iso9660->primary.rootent;
5478 _isoent_file_location(iso9660, np, &symlocation);
5480 if (np->subdirs.first != NULL &&
5482 ((iso9660->opt.rr == OPT_RR_DISABLED &&
5483 depth + 2 < iso9660->primary.max_depth) ||
5485 depth + 1 < iso9660->primary.max_depth)))) {
5486 /* Enter to sub directories. */
5487 np = np->subdirs.first;
5491 while (np != np->parent) {
5492 if (np->drnext == NULL) {
5493 /* Return to the parent directory. */
5501 } while (np != np->parent);
5504 for (file = iso9660->data_file_list.first;
5505 file != NULL; file = file->datanext) {
5507 if (!file->write_content)
5510 file->cur_content = &(file->content);
5512 file->cur_content->location = location;
5513 location += file->cur_content->blocks;
5514 total_block += file->cur_content->blocks;
5515 /* Next fragument */
5516 file->cur_content = file->cur_content->next;
5517 } while (file->cur_content != NULL);
5519 iso9660->total_file_block += total_block;
5523 get_path_component(char *name, size_t n, const char *fn)
5528 p = strchr(fn, '/');
5530 if ((l = strlen(fn)) == 0)
5536 memcpy(name, fn, l);
5543 * Add a new entry into the tree.
5546 isoent_tree(struct archive_write *a, struct isoent **isoentpp)
5548 #if defined(_WIN32) && !defined(__CYGWIN__)
5549 char name[_MAX_FNAME];/* Included null terminator size. */
5550 #elif defined(NAME_MAX) && NAME_MAX >= 255
5551 char name[NAME_MAX+1];
5555 struct iso9660 *iso9660 = a->format_data;
5556 struct isoent *dent, *isoent, *np;
5557 struct isofile *f1, *f2;
5562 dent = iso9660->primary.rootent;
5563 if (isoent->file->parentdir.length > 0)
5564 fn = p = isoent->file->parentdir.s;
5569 * If the path of the parent directory of `isoent' entry is
5570 * the same as the path of `cur_dirent', add isoent to
5573 if (archive_strlen(&(iso9660->cur_dirstr))
5574 == archive_strlen(&(isoent->file->parentdir)) &&
5575 strcmp(iso9660->cur_dirstr.s, fn) == 0) {
5576 if (!isoent_add_child_tail(iso9660->cur_dirent, isoent)) {
5577 np = (struct isoent *)__archive_rb_tree_find_node(
5578 &(iso9660->cur_dirent->rbtree),
5579 isoent->file->basename.s);
5582 return (ARCHIVE_OK);
5586 l = get_path_component(name, sizeof(name), fn);
5592 archive_set_error(&a->archive,
5594 "A name buffer is too small");
5595 _isoent_free(isoent);
5596 return (ARCHIVE_FATAL);
5599 np = isoent_find_child(dent, name);
5600 if (np == NULL || fn[0] == '\0')
5603 /* Find next subdirectory. */
5605 /* NOT Directory! */
5606 archive_set_error(&a->archive,
5608 "`%s' is not directory, we cannot insert `%s' ",
5609 archive_entry_pathname(np->file->entry),
5610 archive_entry_pathname(isoent->file->entry));
5611 _isoent_free(isoent);
5613 return (ARCHIVE_FAILED);
5622 * Create virtual parent directories.
5624 while (fn[0] != '\0') {
5626 struct archive_string as;
5628 archive_string_init(&as);
5629 archive_strncat(&as, p, fn - p + l);
5630 if (as.s[as.length-1] == '/') {
5631 as.s[as.length-1] = '\0';
5634 vp = isoent_create_virtual_dir(a, iso9660, as.s);
5636 archive_string_free(&as);
5637 archive_set_error(&a->archive, ENOMEM,
5638 "Can't allocate memory");
5639 _isoent_free(isoent);
5641 return (ARCHIVE_FATAL);
5643 archive_string_free(&as);
5645 if (vp->file->dircnt > iso9660->dircnt_max)
5646 iso9660->dircnt_max = vp->file->dircnt;
5647 isoent_add_child_tail(dent, vp);
5653 l = get_path_component(name, sizeof(name), fn);
5655 archive_string_free(&as);
5656 archive_set_error(&a->archive,
5658 "A name buffer is too small");
5659 _isoent_free(isoent);
5661 return (ARCHIVE_FATAL);
5666 /* Found out the parent directory where isoent can be
5668 iso9660->cur_dirent = dent;
5669 archive_string_empty(&(iso9660->cur_dirstr));
5670 archive_string_ensure(&(iso9660->cur_dirstr),
5671 archive_strlen(&(dent->file->parentdir)) +
5672 archive_strlen(&(dent->file->basename)) + 2);
5673 if (archive_strlen(&(dent->file->parentdir)) +
5674 archive_strlen(&(dent->file->basename)) == 0)
5675 iso9660->cur_dirstr.s[0] = 0;
5677 if (archive_strlen(&(dent->file->parentdir)) > 0) {
5678 archive_string_copy(&(iso9660->cur_dirstr),
5679 &(dent->file->parentdir));
5680 archive_strappend_char(&(iso9660->cur_dirstr), '/');
5682 archive_string_concat(&(iso9660->cur_dirstr),
5683 &(dent->file->basename));
5686 if (!isoent_add_child_tail(dent, isoent)) {
5687 np = (struct isoent *)__archive_rb_tree_find_node(
5688 &(dent->rbtree), isoent->file->basename.s);
5691 return (ARCHIVE_OK);
5696 * We have already has the entry the filename of which is
5702 /* If the file type of entries is different,
5703 * we cannot handle it. */
5704 if (archive_entry_filetype(f1->entry) !=
5705 archive_entry_filetype(f2->entry)) {
5706 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
5707 "Found duplicate entries `%s' and its file type is "
5709 archive_entry_pathname(f1->entry));
5710 _isoent_free(isoent);
5712 return (ARCHIVE_FAILED);
5715 /* Swap file entries. */
5720 _isoent_free(isoent);
5722 return (ARCHIVE_OK);
5726 * Find a entry from `isoent'
5728 static struct isoent *
5729 isoent_find_child(struct isoent *isoent, const char *child_name)
5733 np = (struct isoent *)__archive_rb_tree_find_node(
5734 &(isoent->rbtree), child_name);
5739 * Find a entry full-path of which is specified by `fn' parameter,
5742 static struct isoent *
5743 isoent_find_entry(struct isoent *rootent, const char *fn)
5745 #if defined(_WIN32) && !defined(__CYGWIN__)
5746 char name[_MAX_FNAME];/* Included null terminator size. */
5747 #elif defined(NAME_MAX) && NAME_MAX >= 255
5748 char name[NAME_MAX+1];
5752 struct isoent *isoent, *np;
5758 l = get_path_component(name, sizeof(name), fn);
5765 np = isoent_find_child(isoent, name);
5769 break;/* We found out the entry */
5771 /* Try sub directory. */
5775 break;/* Not directory */
5782 * Following idr_* functions are used for resolving duplicated filenames
5783 * and unreceivable filenames to generate ISO9660/Joliet Identifiers.
5787 idr_relaxed_filenames(char *map)
5791 for (i = 0x21; i <= 0x2F; i++)
5793 for (i = 0x3A; i <= 0x41; i++)
5795 for (i = 0x5B; i <= 0x5E; i++)
5798 for (i = 0x7B; i <= 0x7E; i++)
5803 idr_init(struct iso9660 *iso9660, struct vdd *vdd, struct idr *idr)
5806 idr->idrent_pool = NULL;
5808 if (vdd->vdd_type != VDD_JOLIET) {
5809 if (iso9660->opt.iso_level <= 3) {
5810 memcpy(idr->char_map, d_characters_map,
5811 sizeof(idr->char_map));
5813 memcpy(idr->char_map, d1_characters_map,
5814 sizeof(idr->char_map));
5815 idr_relaxed_filenames(idr->char_map);
5821 idr_cleanup(struct idr *idr)
5823 free(idr->idrent_pool);
5827 idr_ensure_poolsize(struct archive_write *a, struct idr *idr,
5831 if (idr->pool_size < cnt) {
5833 const int bk = (1 << 7) - 1;
5836 psize = (cnt + bk) & ~bk;
5837 p = realloc(idr->idrent_pool, sizeof(struct idrent) * psize);
5839 archive_set_error(&a->archive, ENOMEM,
5840 "Can't allocate memory");
5841 return (ARCHIVE_FATAL);
5843 idr->idrent_pool = (struct idrent *)p;
5844 idr->pool_size = psize;
5846 return (ARCHIVE_OK);
5850 idr_start(struct archive_write *a, struct idr *idr, int cnt, int ffmax,
5851 int num_size, int null_size, const struct archive_rb_tree_ops *rbt_ops)
5855 (void)ffmax; /* UNUSED */
5857 r = idr_ensure_poolsize(a, idr, cnt);
5858 if (r != ARCHIVE_OK)
5860 __archive_rb_tree_init(&(idr->rbtree), rbt_ops);
5861 idr->wait_list.first = NULL;
5862 idr->wait_list.last = &(idr->wait_list.first);
5864 idr->num_size = num_size;
5865 idr->null_size = null_size;
5866 return (ARCHIVE_OK);
5870 idr_register(struct idr *idr, struct isoent *isoent, int weight, int noff)
5872 struct idrent *idrent, *n;
5874 idrent = &(idr->idrent_pool[idr->pool_idx++]);
5875 idrent->wnext = idrent->avail = NULL;
5876 idrent->isoent = isoent;
5877 idrent->weight = weight;
5878 idrent->noff = noff;
5879 idrent->rename_num = 0;
5881 if (!__archive_rb_tree_insert_node(&(idr->rbtree), &(idrent->rbnode))) {
5882 n = (struct idrent *)__archive_rb_tree_find_node(
5883 &(idr->rbtree), idrent->isoent);
5885 /* this `idrent' needs to rename. */
5887 *idr->wait_list.last = idrent;
5888 idr->wait_list.last = &(idrent->wnext);
5894 idr_extend_identifier(struct idrent *wnp, int numsize, int nullsize)
5899 wnp_ext_off = wnp->isoent->ext_off;
5900 if (wnp->noff + numsize != wnp_ext_off) {
5901 p = (unsigned char *)wnp->isoent->identifier;
5902 /* Extend the filename; foo.c --> foo___.c */
5903 memmove(p + wnp->noff + numsize, p + wnp_ext_off,
5904 wnp->isoent->ext_len + nullsize);
5905 wnp->isoent->ext_off = wnp_ext_off = wnp->noff + numsize;
5906 wnp->isoent->id_len = wnp_ext_off + wnp->isoent->ext_len;
5911 idr_resolve(struct idr *idr, void (*fsetnum)(unsigned char *p, int num))
5916 for (n = idr->wait_list.first; n != NULL; n = n->wnext) {
5917 idr_extend_identifier(n, idr->num_size, idr->null_size);
5918 p = (unsigned char *)n->isoent->identifier + n->noff;
5920 fsetnum(p, n->avail->rename_num++);
5921 } while (!__archive_rb_tree_insert_node(
5922 &(idr->rbtree), &(n->rbnode)));
5927 idr_set_num(unsigned char *p, int num)
5929 static const char xdig[] = {
5930 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
5931 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
5932 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
5933 'U', 'V', 'W', 'X', 'Y', 'Z'
5936 num %= sizeof(xdig) * sizeof(xdig) * sizeof(xdig);
5937 p[0] = xdig[(num / (sizeof(xdig) * sizeof(xdig)))];
5938 num %= sizeof(xdig) * sizeof(xdig);
5939 p[1] = xdig[ (num / sizeof(xdig))];
5940 num %= sizeof(xdig);
5945 idr_set_num_beutf16(unsigned char *p, int num)
5947 static const uint16_t xdig[] = {
5948 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
5949 0x0036, 0x0037, 0x0038, 0x0039,
5950 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046,
5951 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C,
5952 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052,
5953 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
5956 #define XDIG_CNT (sizeof(xdig)/sizeof(xdig[0]))
5958 num %= XDIG_CNT * XDIG_CNT * XDIG_CNT;
5959 archive_be16enc(p, xdig[(num / (XDIG_CNT * XDIG_CNT))]);
5960 num %= XDIG_CNT * XDIG_CNT;
5961 archive_be16enc(p+2, xdig[ (num / XDIG_CNT)]);
5963 archive_be16enc(p+4, xdig[num]);
5967 * Generate ISO9660 Identifier.
5970 isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent,
5973 struct iso9660 *iso9660;
5977 const char *char_map;
5978 char allow_ldots, allow_multidot, allow_period, allow_vernum;
5979 int fnmax, ffmax, dnmax;
5980 static const struct archive_rb_tree_ops rb_ops = {
5981 isoent_cmp_node_iso9660, isoent_cmp_key_iso9660
5984 if (isoent->children.cnt == 0)
5987 iso9660 = a->format_data;
5988 char_map = idr->char_map;
5989 if (iso9660->opt.iso_level <= 3) {
5993 allow_vernum = iso9660->opt.allow_vernum;
5994 if (iso9660->opt.iso_level == 1) {
5996 ffmax = 12;/* fnmax + '.' + 3 */
6004 allow_ldots = allow_multidot = 1;
6005 allow_period = allow_vernum = 0;
6006 if (iso9660->opt.rr)
6008 * MDR : The maximum size of Directory Record(254).
6009 * DRL : A Directory Record Length(33).
6010 * CE : A size of SUSP CE System Use Entry(28).
6011 * MDR - DRL - CE = 254 - 33 - 28 = 193.
6013 fnmax = ffmax = dnmax = 193;
6016 * XA : CD-ROM XA System Use Extension
6018 * MDR - DRL - XA = 254 - 33 -14 = 207.
6020 fnmax = ffmax = dnmax = 207;
6023 r = idr_start(a, idr, isoent->children.cnt, ffmax, 3, 1, &rb_ops);
6027 for (np = isoent->children.first; np != NULL; np = np->chnext) {
6029 int ext_off, noff, weight;
6031 l = (int)np->file->basename.length;
6032 p = malloc(l+31+2+1);
6034 archive_set_error(&a->archive, ENOMEM,
6035 "Can't allocate memory");
6036 return (ARCHIVE_FATAL);
6038 memcpy(p, np->file->basename.s, l);
6045 * If there is a '.' character at the first byte,
6046 * it has to be replaced by '_' character.
6056 if (char_map[(unsigned char)*p]) {
6057 /* if iso-level is '4', a character '.' is
6058 * allowed by char_map. */
6065 if (*p >= 'a' && *p <= 'z') {
6095 ext_off = (int)(dot - p);
6097 if (iso9660->opt.iso_level == 1) {
6099 if (strlen(dot) > 4) {
6100 /* A length of a file extension
6101 * must be less than 4 */
6114 } else if (np->dir) {
6118 if (ext_off > dnmax)
6121 } else if (l > ffmax) {
6122 int extlen = (int)strlen(dot);
6126 xdoff = (int)(xdot - p);
6130 if (extlen > 1 && xdoff < fnmax-1) {
6135 off = ffmax - extlen;
6137 /* A dot('.') character
6138 * does't place to the first
6139 * byte of identifier. */
6143 memmove(p+off, dot, extlen);
6147 #ifdef COMPAT_MKISOFS
6148 } else if (xdoff >= fnmax-1) {
6149 /* Simulate a bug(?) of mkisofs. */
6161 /* Save an offset of a file name extension to sort files. */
6162 np->ext_off = ext_off;
6163 np->ext_len = (int)strlen(&p[ext_off]);
6164 np->id_len = l = ext_off + np->ext_len;
6166 /* Make an offset of the number which is used to be set
6167 * hexadecimal number to avoid duplicate identififier. */
6168 if (iso9660->opt.iso_level == 1) {
6176 else if (l == ffmax-1)
6178 else if (l == ffmax-2)
6183 /* Register entry to the identifier resolver. */
6184 idr_register(idr, np, weight, noff);
6187 /* Resolve duplicate identifier. */
6188 idr_resolve(idr, idr_set_num);
6190 /* Add a period and a version number to identifiers. */
6191 for (np = isoent->children.first; np != NULL; np = np->chnext) {
6192 if (!np->dir && np->rr_child == NULL) {
6193 p = np->identifier + np->ext_off + np->ext_len;
6194 if (np->ext_len == 0 && allow_period) {
6198 if (np->ext_len == 1 && !allow_period) {
6202 np->id_len = np->ext_off + np->ext_len;
6210 np->id_len = np->ext_off + np->ext_len;
6211 np->mb_len = np->id_len;
6213 return (ARCHIVE_OK);
6217 * Generate Joliet Identifier.
6220 isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent,
6223 struct iso9660 *iso9660;
6228 size_t ffmax, parent_len;
6229 static const struct archive_rb_tree_ops rb_ops = {
6230 isoent_cmp_node_joliet, isoent_cmp_key_joliet
6233 if (isoent->children.cnt == 0)
6236 iso9660 = a->format_data;
6237 if (iso9660->opt.joliet == OPT_JOLIET_LONGNAME)
6242 r = idr_start(a, idr, isoent->children.cnt, (int)ffmax, 6, 2, &rb_ops);
6247 for (np = isoent; np->parent != np; np = np->parent)
6248 parent_len += np->mb_len + 1;
6250 for (np = isoent->children.first; np != NULL; np = np->chnext) {
6252 int ext_off, noff, weight;
6255 if ((l = np->file->basename_utf16.length) > ffmax)
6258 p = malloc((l+1)*2);
6260 archive_set_error(&a->archive, ENOMEM,
6261 "Can't allocate memory");
6262 return (ARCHIVE_FATAL);
6264 memcpy(p, np->file->basename_utf16.s, l);
6268 np->identifier = (char *)p;
6273 if (!joliet_allowed_char(p[0], p[1]))
6274 archive_be16enc(p, 0x005F); /* '_' */
6275 else if (p[0] == 0 && p[1] == 0x2E) /* '.' */
6280 ext_off = (int)(dot - (unsigned char *)np->identifier);
6281 np->ext_off = ext_off;
6282 np->ext_len = (int)l - ext_off;
6283 np->id_len = (int)l;
6286 * Get a length of MBS of a full-pathname.
6288 if (np->file->basename_utf16.length > ffmax) {
6289 if (archive_strncpy_l(&iso9660->mbs,
6290 (const char *)np->identifier, l,
6291 iso9660->sconv_from_utf16be) != 0 &&
6293 archive_set_error(&a->archive, errno,
6295 return (ARCHIVE_FATAL);
6297 np->mb_len = (int)iso9660->mbs.length;
6298 if (np->mb_len != (int)np->file->basename.length)
6299 weight = np->mb_len;
6301 np->mb_len = (int)np->file->basename.length;
6303 /* If a length of full-pathname is longer than 240 bytes,
6304 * it violates Joliet extensions regulation. */
6305 if (parent_len > 240
6307 || parent_len + np->mb_len > 240) {
6308 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
6309 "The regulation of Joliet extensions;"
6310 " A length of a full-pathname of `%s' is "
6311 "longer than 240 bytes, (p=%d, b=%d)",
6312 archive_entry_pathname(np->file->entry),
6313 (int)parent_len, (int)np->mb_len);
6314 return (ARCHIVE_FATAL);
6317 /* Make an offset of the number which is used to be set
6318 * hexadecimal number to avoid duplicate identifier. */
6321 else if (l == ffmax-2)
6323 else if (l == ffmax-4)
6327 /* Register entry to the identifier resolver. */
6328 idr_register(idr, np, weight, noff);
6331 /* Resolve duplicate identifier with Joliet Volume. */
6332 idr_resolve(idr, idr_set_num_beutf16);
6334 return (ARCHIVE_OK);
6338 * This comparing rule is according to ISO9660 Standard 9.3
6341 isoent_cmp_iso9660_identifier(const struct isoent *p1, const struct isoent *p2)
6343 const char *s1, *s2;
6347 s1 = p1->identifier;
6348 s2 = p2->identifier;
6350 /* Compare File Name */
6352 if (l > p2->ext_off)
6354 cmp = memcmp(s1, s2, l);
6357 if (p1->ext_off < p2->ext_off) {
6359 l = p2->ext_off - p1->ext_off;
6363 - *(const unsigned char *)(s2 - 1));
6364 } else if (p1->ext_off > p2->ext_off) {
6366 l = p1->ext_off - p2->ext_off;
6369 return (*(const unsigned char *)(s1 - 1)
6372 /* Compare File Name Extension */
6373 if (p1->ext_len == 0 && p2->ext_len == 0)
6375 if (p1->ext_len == 1 && p2->ext_len == 1)
6377 if (p1->ext_len <= 1)
6379 if (p2->ext_len <= 1)
6382 if (l > p2->ext_len)
6384 s1 = p1->identifier + p1->ext_off;
6385 s2 = p2->identifier + p2->ext_off;
6387 cmp = memcmp(s1, s2, l);
6391 if (p1->ext_len < p2->ext_len) {
6393 l = p2->ext_len - p1->ext_len;
6397 - *(const unsigned char *)(s2 - 1));
6398 } else if (p1->ext_len > p2->ext_len) {
6400 l = p1->ext_len - p2->ext_len;
6403 return (*(const unsigned char *)(s1 - 1)
6406 /* Compare File Version Number */
6407 /* No operation. The File Version Number is always one. */
6413 isoent_cmp_node_iso9660(const struct archive_rb_node *n1,
6414 const struct archive_rb_node *n2)
6416 const struct idrent *e1 = (const struct idrent *)n1;
6417 const struct idrent *e2 = (const struct idrent *)n2;
6419 return (isoent_cmp_iso9660_identifier(e2->isoent, e1->isoent));
6423 isoent_cmp_key_iso9660(const struct archive_rb_node *node, const void *key)
6425 const struct isoent *isoent = (const struct isoent *)key;
6426 const struct idrent *idrent = (const struct idrent *)node;
6428 return (isoent_cmp_iso9660_identifier(isoent, idrent->isoent));
6432 isoent_cmp_joliet_identifier(const struct isoent *p1, const struct isoent *p2)
6434 const unsigned char *s1, *s2;
6438 s1 = (const unsigned char *)p1->identifier;
6439 s2 = (const unsigned char *)p2->identifier;
6441 /* Compare File Name */
6443 if (l > p2->ext_off)
6445 cmp = memcmp(s1, s2, l);
6448 if (p1->ext_off < p2->ext_off) {
6450 l = p2->ext_off - p1->ext_off;
6453 return (- *(const unsigned char *)(s2 - 1));
6454 } else if (p1->ext_off > p2->ext_off) {
6456 l = p1->ext_off - p2->ext_off;
6459 return (*(const unsigned char *)(s1 - 1));
6461 /* Compare File Name Extension */
6462 if (p1->ext_len == 0 && p2->ext_len == 0)
6464 if (p1->ext_len == 2 && p2->ext_len == 2)
6466 if (p1->ext_len <= 2)
6468 if (p2->ext_len <= 2)
6471 if (l > p2->ext_len)
6473 s1 = (unsigned char *)(p1->identifier + p1->ext_off);
6474 s2 = (unsigned char *)(p2->identifier + p2->ext_off);
6476 cmp = memcmp(s1, s2, l);
6480 if (p1->ext_len < p2->ext_len) {
6482 l = p2->ext_len - p1->ext_len;
6485 return (- *(const unsigned char *)(s2 - 1));
6486 } else if (p1->ext_len > p2->ext_len) {
6488 l = p1->ext_len - p2->ext_len;
6491 return (*(const unsigned char *)(s1 - 1));
6493 /* Compare File Version Number */
6494 /* No operation. The File Version Number is always one. */
6500 isoent_cmp_node_joliet(const struct archive_rb_node *n1,
6501 const struct archive_rb_node *n2)
6503 const struct idrent *e1 = (const struct idrent *)n1;
6504 const struct idrent *e2 = (const struct idrent *)n2;
6506 return (isoent_cmp_joliet_identifier(e2->isoent, e1->isoent));
6510 isoent_cmp_key_joliet(const struct archive_rb_node *node, const void *key)
6512 const struct isoent *isoent = (const struct isoent *)key;
6513 const struct idrent *idrent = (const struct idrent *)node;
6515 return (isoent_cmp_joliet_identifier(isoent, idrent->isoent));
6519 isoent_make_sorted_files(struct archive_write *a, struct isoent *isoent,
6522 struct archive_rb_node *rn;
6523 struct isoent **children;
6525 children = malloc(isoent->children.cnt * sizeof(struct isoent *));
6526 if (children == NULL) {
6527 archive_set_error(&a->archive, ENOMEM,
6528 "Can't allocate memory");
6529 return (ARCHIVE_FATAL);
6531 isoent->children_sorted = children;
6533 ARCHIVE_RB_TREE_FOREACH(rn, &(idr->rbtree)) {
6534 struct idrent *idrent = (struct idrent *)rn;
6535 *children ++ = idrent->isoent;
6537 return (ARCHIVE_OK);
6541 * - Generate ISO9660 and Joliet identifiers from basenames.
6542 * - Sort files by each directory.
6545 isoent_traverse_tree(struct archive_write *a, struct vdd* vdd)
6547 struct iso9660 *iso9660 = a->format_data;
6552 int (*genid)(struct archive_write *, struct isoent *, struct idr *);
6554 idr_init(iso9660, vdd, &idr);
6557 if (vdd->vdd_type == VDD_JOLIET)
6558 genid = isoent_gen_joliet_identifier;
6560 genid = isoent_gen_iso9660_identifier;
6563 !archive_entry_mtime_is_set(np->file->entry)) {
6564 /* Set properly times to virtual directory */
6565 archive_entry_set_mtime(np->file->entry,
6566 iso9660->birth_time, 0);
6567 archive_entry_set_atime(np->file->entry,
6568 iso9660->birth_time, 0);
6569 archive_entry_set_ctime(np->file->entry,
6570 iso9660->birth_time, 0);
6572 if (np->children.first != NULL) {
6573 if (vdd->vdd_type != VDD_JOLIET &&
6574 !iso9660->opt.rr && depth + 1 >= vdd->max_depth) {
6575 if (np->children.cnt > 0)
6576 iso9660->directories_too_deep = np;
6578 /* Generate Identifier */
6579 r = genid(a, np, &idr);
6581 goto exit_traverse_tree;
6582 r = isoent_make_sorted_files(a, np, &idr);
6584 goto exit_traverse_tree;
6586 if (np->subdirs.first != NULL &&
6587 depth + 1 < vdd->max_depth) {
6588 /* Enter to sub directories. */
6589 np = np->subdirs.first;
6595 while (np != np->parent) {
6596 if (np->drnext == NULL) {
6597 /* Return to the parent directory. */
6605 } while (np != np->parent);
6615 * Collect directory entries into path_table by a directory depth.
6618 isoent_collect_dirs(struct vdd *vdd, struct isoent *rootent, int depth)
6622 if (rootent == NULL)
6623 rootent = vdd->rootent;
6626 /* Register current directory to pathtable. */
6627 path_table_add_entry(&(vdd->pathtbl[depth]), np);
6629 if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) {
6630 /* Enter to sub directories. */
6631 np = np->subdirs.first;
6635 while (np != rootent) {
6636 if (np->drnext == NULL) {
6637 /* Return to the parent directory. */
6645 } while (np != rootent);
6647 return (ARCHIVE_OK);
6651 * The entry whose number of levels in a directory hierarchy is
6652 * large than eight relocate to rr_move directory.
6655 isoent_rr_move_dir(struct archive_write *a, struct isoent **rr_moved,
6656 struct isoent *curent, struct isoent **newent)
6658 struct iso9660 *iso9660 = a->format_data;
6659 struct isoent *rrmoved, *mvent, *np;
6661 if ((rrmoved = *rr_moved) == NULL) {
6662 struct isoent *rootent = iso9660->primary.rootent;
6663 /* There isn't rr_move entry.
6664 * Create rr_move entry and insert it into the root entry.
6666 rrmoved = isoent_create_virtual_dir(a, iso9660, "rr_moved");
6667 if (rrmoved == NULL) {
6668 archive_set_error(&a->archive, ENOMEM,
6669 "Can't allocate memory");
6670 return (ARCHIVE_FATAL);
6672 /* Add "rr_moved" entry to the root entry. */
6673 isoent_add_child_head(rootent, rrmoved);
6674 archive_entry_set_nlink(rootent->file->entry,
6675 archive_entry_nlink(rootent->file->entry) + 1);
6676 /* Register "rr_moved" entry to second level pathtable. */
6677 path_table_add_entry(&(iso9660->primary.pathtbl[1]), rrmoved);
6678 /* Save rr_moved. */
6679 *rr_moved = rrmoved;
6682 * Make a clone of curent which is going to be relocated
6685 mvent = isoent_clone(curent);
6686 if (mvent == NULL) {
6687 archive_set_error(&a->archive, ENOMEM,
6688 "Can't allocate memory");
6689 return (ARCHIVE_FATAL);
6691 /* linking.. and use for creating "CL", "PL" and "RE" */
6692 mvent->rr_parent = curent->parent;
6693 curent->rr_child = mvent;
6695 * Move subdirectories from the curent to mvent
6697 if (curent->children.first != NULL) {
6698 *mvent->children.last = curent->children.first;
6699 mvent->children.last = curent->children.last;
6701 for (np = mvent->children.first; np != NULL; np = np->chnext)
6703 mvent->children.cnt = curent->children.cnt;
6704 curent->children.cnt = 0;
6705 curent->children.first = NULL;
6706 curent->children.last = &curent->children.first;
6708 if (curent->subdirs.first != NULL) {
6709 *mvent->subdirs.last = curent->subdirs.first;
6710 mvent->subdirs.last = curent->subdirs.last;
6712 mvent->subdirs.cnt = curent->subdirs.cnt;
6713 curent->subdirs.cnt = 0;
6714 curent->subdirs.first = NULL;
6715 curent->subdirs.last = &curent->subdirs.first;
6718 * The mvent becomes a child of the rr_moved entry.
6720 isoent_add_child_tail(rrmoved, mvent);
6721 archive_entry_set_nlink(rrmoved->file->entry,
6722 archive_entry_nlink(rrmoved->file->entry) + 1);
6724 * This entry which relocated to the rr_moved directory
6725 * has to set the flag as a file.
6726 * See also RRIP 4.1.5.1 Description of the "CL" System Use Entry.
6732 return (ARCHIVE_OK);
6736 isoent_rr_move(struct archive_write *a)
6738 struct iso9660 *iso9660 = a->format_data;
6739 struct path_table *pt;
6740 struct isoent *rootent, *rr_moved;
6741 struct isoent *np, *last;
6744 pt = &(iso9660->primary.pathtbl[MAX_DEPTH-1]);
6745 /* Theare aren't level 8 directories reaching a deepr level. */
6747 return (ARCHIVE_OK);
6749 rootent = iso9660->primary.rootent;
6750 /* If "rr_moved" directory is already existing,
6751 * we have to use it. */
6752 rr_moved = isoent_find_child(rootent, "rr_moved");
6753 if (rr_moved != NULL &&
6754 rr_moved != rootent->children.first) {
6756 * It's necessary that rr_move is the first entry
6759 /* Remove "rr_moved" entry from children chain. */
6760 isoent_remove_child(rootent, rr_moved);
6762 /* Add "rr_moved" entry into the head of children chain. */
6763 isoent_add_child_head(rootent, rr_moved);
6767 * Check level 8 path_table.
6768 * If find out sub directory entries, that entries move to rr_move.
6771 while (np != NULL) {
6772 last = path_table_last_entry(pt);
6773 for (; np != NULL; np = np->ptnext) {
6774 struct isoent *mvent;
6775 struct isoent *newent;
6779 for (mvent = np->subdirs.first;
6780 mvent != NULL; mvent = mvent->drnext) {
6781 r = isoent_rr_move_dir(a, &rr_moved,
6785 isoent_collect_dirs(&(iso9660->primary),
6789 /* If new entries are added to level 8 path_talbe,
6790 * its sub directory entries move to rr_move too.
6795 return (ARCHIVE_OK);
6799 * This comparing rule is according to ISO9660 Standard 6.9.1
6802 _compare_path_table(const void *v1, const void *v2)
6804 const struct isoent *p1, *p2;
6805 const char *s1, *s2;
6808 p1 = *((const struct isoent **)(uintptr_t)v1);
6809 p2 = *((const struct isoent **)(uintptr_t)v2);
6811 /* Compare parent directory number */
6812 cmp = p1->parent->dir_number - p2->parent->dir_number;
6816 /* Compare indetifier */
6817 s1 = p1->identifier;
6818 s2 = p2->identifier;
6820 if (l > p2->ext_off)
6822 cmp = strncmp(s1, s2, l);
6825 if (p1->ext_off < p2->ext_off) {
6827 l = p2->ext_off - p1->ext_off;
6831 - *(const unsigned char *)(s2 - 1));
6832 } else if (p1->ext_off > p2->ext_off) {
6834 l = p1->ext_off - p2->ext_off;
6837 return (*(const unsigned char *)(s1 - 1)
6844 _compare_path_table_joliet(const void *v1, const void *v2)
6846 const struct isoent *p1, *p2;
6847 const unsigned char *s1, *s2;
6850 p1 = *((const struct isoent **)(uintptr_t)v1);
6851 p2 = *((const struct isoent **)(uintptr_t)v2);
6853 /* Compare parent directory number */
6854 cmp = p1->parent->dir_number - p2->parent->dir_number;
6858 /* Compare indetifier */
6859 s1 = (const unsigned char *)p1->identifier;
6860 s2 = (const unsigned char *)p2->identifier;
6862 if (l > p2->ext_off)
6864 cmp = memcmp(s1, s2, l);
6867 if (p1->ext_off < p2->ext_off) {
6869 l = p2->ext_off - p1->ext_off;
6872 return (- *(const unsigned char *)(s2 - 1));
6873 } else if (p1->ext_off > p2->ext_off) {
6875 l = p1->ext_off - p2->ext_off;
6878 return (*(const unsigned char *)(s1 - 1));
6884 path_table_add_entry(struct path_table *pathtbl, struct isoent *ent)
6887 *pathtbl->last = ent;
6888 pathtbl->last = &(ent->ptnext);
6892 static inline struct isoent *
6893 path_table_last_entry(struct path_table *pathtbl)
6895 if (pathtbl->first == NULL)
6897 return (((struct isoent *)(void *)
6898 ((char *)(pathtbl->last) - offsetof(struct isoent, ptnext))));
6902 * Sort directory entries in path_table
6903 * and assign directory number to each entries.
6906 isoent_make_path_table_2(struct archive_write *a, struct vdd *vdd,
6907 int depth, int *dir_number)
6910 struct isoent **enttbl;
6911 struct path_table *pt;
6914 pt = &vdd->pathtbl[depth];
6917 return (ARCHIVE_OK);
6919 enttbl = malloc(pt->cnt * sizeof(struct isoent *));
6920 if (enttbl == NULL) {
6921 archive_set_error(&a->archive, ENOMEM,
6922 "Can't allocate memory");
6923 return (ARCHIVE_FATAL);
6925 pt->sorted = enttbl;
6926 for (np = pt->first; np != NULL; np = np->ptnext)
6928 enttbl = pt->sorted;
6930 switch (vdd->vdd_type) {
6933 #ifdef __COMPAR_FN_T
6934 qsort(enttbl, pt->cnt, sizeof(struct isoent *),
6935 (__compar_fn_t)_compare_path_table);
6937 qsort(enttbl, pt->cnt, sizeof(struct isoent *),
6938 _compare_path_table);
6942 #ifdef __COMPAR_FN_T
6943 qsort(enttbl, pt->cnt, sizeof(struct isoent *),
6944 (__compar_fn_t)_compare_path_table_joliet);
6946 qsort(enttbl, pt->cnt, sizeof(struct isoent *),
6947 _compare_path_table_joliet);
6951 for (i = 0; i < pt->cnt; i++)
6952 enttbl[i]->dir_number = (*dir_number)++;
6954 return (ARCHIVE_OK);
6958 isoent_alloc_path_table(struct archive_write *a, struct vdd *vdd,
6963 vdd->max_depth = max_depth;
6964 vdd->pathtbl = malloc(sizeof(*vdd->pathtbl) * vdd->max_depth);
6965 if (vdd->pathtbl == NULL) {
6966 archive_set_error(&a->archive, ENOMEM,
6967 "Can't allocate memory");
6968 return (ARCHIVE_FATAL);
6970 for (i = 0; i < vdd->max_depth; i++) {
6971 vdd->pathtbl[i].first = NULL;
6972 vdd->pathtbl[i].last = &(vdd->pathtbl[i].first);
6973 vdd->pathtbl[i].sorted = NULL;
6974 vdd->pathtbl[i].cnt = 0;
6976 return (ARCHIVE_OK);
6983 isoent_make_path_table(struct archive_write *a)
6985 struct iso9660 *iso9660 = a->format_data;
6992 if (iso9660->dircnt_max >= MAX_DEPTH &&
6993 (!iso9660->opt.limit_depth || iso9660->opt.iso_level == 4))
6994 r = isoent_alloc_path_table(a, &(iso9660->primary),
6995 iso9660->dircnt_max + 1);
6997 /* The number of levels in the hierarchy cannot exceed
6999 r = isoent_alloc_path_table(a, &(iso9660->primary),
7003 if (iso9660->opt.joliet) {
7004 r = isoent_alloc_path_table(a, &(iso9660->joliet),
7005 iso9660->dircnt_max + 1);
7011 * - Collect directories for primary and joliet.
7013 isoent_collect_dirs(&(iso9660->primary), NULL, 0);
7014 if (iso9660->opt.joliet)
7015 isoent_collect_dirs(&(iso9660->joliet), NULL, 0);
7017 * Rockridge; move deeper depth directories to rr_moved.
7019 if (iso9660->opt.rr) {
7020 r = isoent_rr_move(a);
7026 isofile_connect_hardlink_files(iso9660);
7029 * - Renew a value of the depth of that directories.
7030 * - Resolve hardlinks.
7031 * - Convert pathnames to ISO9660 name or UCS2(joliet).
7032 * - Sort files by each directory.
7034 r = isoent_traverse_tree(a, &(iso9660->primary));
7037 if (iso9660->opt.joliet) {
7038 r = isoent_traverse_tree(a, &(iso9660->joliet));
7044 * - Sort directories.
7045 * - Assign all directory number.
7048 for (depth = 0; depth < iso9660->primary.max_depth; depth++) {
7049 r = isoent_make_path_table_2(a, &(iso9660->primary),
7050 depth, &dir_number);
7054 if (iso9660->opt.joliet) {
7056 for (depth = 0; depth < iso9660->joliet.max_depth; depth++) {
7057 r = isoent_make_path_table_2(a, &(iso9660->joliet),
7058 depth, &dir_number);
7063 if (iso9660->opt.limit_dirs && dir_number > 0xffff) {
7065 * Maximum number of directories is 65535(0xffff)
7066 * doe to size(16bit) of Parent Directory Number of
7068 * See also ISO9660 Standard 9.4.
7070 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7071 "Too many directories(%d) over 65535.", dir_number);
7072 return (ARCHIVE_FATAL);
7075 /* Get the size of the Path Table. */
7076 calculate_path_table_size(&(iso9660->primary));
7077 if (iso9660->opt.joliet)
7078 calculate_path_table_size(&(iso9660->joliet));
7080 return (ARCHIVE_OK);
7084 isoent_find_out_boot_file(struct archive_write *a, struct isoent *rootent)
7086 struct iso9660 *iso9660 = a->format_data;
7088 /* Find a isoent of the boot file. */
7089 iso9660->el_torito.boot = isoent_find_entry(rootent,
7090 iso9660->el_torito.boot_filename.s);
7091 if (iso9660->el_torito.boot == NULL) {
7092 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7093 "Can't find the boot image file ``%s''",
7094 iso9660->el_torito.boot_filename.s);
7095 return (ARCHIVE_FATAL);
7097 iso9660->el_torito.boot->file->boot = BOOT_IMAGE;
7098 return (ARCHIVE_OK);
7102 isoent_create_boot_catalog(struct archive_write *a, struct isoent *rootent)
7104 struct iso9660 *iso9660 = a->format_data;
7105 struct isofile *file;
7106 struct isoent *isoent;
7107 struct archive_entry *entry;
7109 (void)rootent; /* UNUSED */
7111 * Create the entry which is the "boot.catalog" file.
7113 file = isofile_new(a, NULL);
7115 archive_set_error(&a->archive, ENOMEM,
7116 "Can't allocate memory");
7117 return (ARCHIVE_FATAL);
7119 archive_entry_set_pathname(file->entry,
7120 iso9660->el_torito.catalog_filename.s);
7121 archive_entry_set_size(file->entry, LOGICAL_BLOCK_SIZE);
7122 archive_entry_set_mtime(file->entry, iso9660->birth_time, 0);
7123 archive_entry_set_atime(file->entry, iso9660->birth_time, 0);
7124 archive_entry_set_ctime(file->entry, iso9660->birth_time, 0);
7125 archive_entry_set_uid(file->entry, getuid());
7126 archive_entry_set_gid(file->entry, getgid());
7127 archive_entry_set_mode(file->entry, AE_IFREG | 0444);
7128 archive_entry_set_nlink(file->entry, 1);
7130 if (isofile_gen_utility_names(a, file) < ARCHIVE_WARN) {
7132 return (ARCHIVE_FATAL);
7134 file->boot = BOOT_CATALOG;
7135 file->content.size = LOGICAL_BLOCK_SIZE;
7136 isofile_add_entry(iso9660, file);
7138 isoent = isoent_new(file);
7139 if (isoent == NULL) {
7140 archive_set_error(&a->archive, ENOMEM,
7141 "Can't allocate memory");
7142 return (ARCHIVE_FATAL);
7144 isoent->virtual = 1;
7146 /* Add the "boot.catalog" entry into tree */
7147 if (isoent_tree(a, &isoent) != ARCHIVE_OK)
7148 return (ARCHIVE_FATAL);
7150 iso9660->el_torito.catalog = isoent;
7152 * Get a boot medai type.
7154 switch (iso9660->opt.boot_type) {
7156 case OPT_BOOT_TYPE_AUTO:
7157 /* Try detecting a media type of the boot image. */
7158 entry = iso9660->el_torito.boot->file->entry;
7159 if (archive_entry_size(entry) == FD_1_2M_SIZE)
7160 iso9660->el_torito.media_type =
7161 BOOT_MEDIA_1_2M_DISKETTE;
7162 else if (archive_entry_size(entry) == FD_1_44M_SIZE)
7163 iso9660->el_torito.media_type =
7164 BOOT_MEDIA_1_44M_DISKETTE;
7165 else if (archive_entry_size(entry) == FD_2_88M_SIZE)
7166 iso9660->el_torito.media_type =
7167 BOOT_MEDIA_2_88M_DISKETTE;
7169 /* We cannot decide whether the boot image is
7171 iso9660->el_torito.media_type =
7172 BOOT_MEDIA_NO_EMULATION;
7174 case OPT_BOOT_TYPE_NO_EMU:
7175 iso9660->el_torito.media_type = BOOT_MEDIA_NO_EMULATION;
7177 case OPT_BOOT_TYPE_HARD_DISK:
7178 iso9660->el_torito.media_type = BOOT_MEDIA_HARD_DISK;
7180 case OPT_BOOT_TYPE_FD:
7181 entry = iso9660->el_torito.boot->file->entry;
7182 if (archive_entry_size(entry) <= FD_1_2M_SIZE)
7183 iso9660->el_torito.media_type =
7184 BOOT_MEDIA_1_2M_DISKETTE;
7185 else if (archive_entry_size(entry) <= FD_1_44M_SIZE)
7186 iso9660->el_torito.media_type =
7187 BOOT_MEDIA_1_44M_DISKETTE;
7188 else if (archive_entry_size(entry) <= FD_2_88M_SIZE)
7189 iso9660->el_torito.media_type =
7190 BOOT_MEDIA_2_88M_DISKETTE;
7192 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7193 "Boot image file(``%s'') size is too big "
7195 iso9660->el_torito.boot_filename.s);
7196 return (ARCHIVE_FATAL);
7202 * Get a system type.
7203 * TODO: `El Torito' specification says "A copy of byte 5 from the
7204 * Partition Table found in the boot image".
7206 iso9660->el_torito.system_type = 0;
7211 if (iso9660->opt.publisher)
7212 archive_string_copy(&(iso9660->el_torito.id),
7213 &(iso9660->publisher_identifier));
7216 return (ARCHIVE_OK);
7220 * If a media type is floppy, return its image size.
7221 * otherwise return 0.
7224 fd_boot_image_size(int media_type)
7226 switch (media_type) {
7227 case BOOT_MEDIA_1_2M_DISKETTE:
7228 return (FD_1_2M_SIZE);
7229 case BOOT_MEDIA_1_44M_DISKETTE:
7230 return (FD_1_44M_SIZE);
7231 case BOOT_MEDIA_2_88M_DISKETTE:
7232 return (FD_2_88M_SIZE);
7239 * Make a boot catalog image data.
7242 make_boot_catalog(struct archive_write *a)
7244 struct iso9660 *iso9660 = a->format_data;
7245 unsigned char *block;
7249 block = wb_buffptr(a);
7250 memset(block, 0, LOGICAL_BLOCK_SIZE);
7258 p[1] = iso9660->el_torito.platform_id;
7262 if (archive_strlen(&(iso9660->el_torito.id)) > 0)
7263 strncpy((char *)p+4, iso9660->el_torito.id.s, 23);
7272 wp = (uint16_t *)block;
7273 while (wp < (uint16_t *)&block[32])
7274 sum += archive_le16dec(wp++);
7275 set_num_721(&block[28], (~sum) + 1);
7278 * Initial/Default Entry
7281 /* Boot Indicator */
7283 /* Boot media type */
7284 p[1] = iso9660->el_torito.media_type;
7286 if (iso9660->el_torito.media_type == BOOT_MEDIA_NO_EMULATION)
7287 set_num_721(&p[2], iso9660->el_torito.boot_load_seg);
7289 set_num_721(&p[2], 0);
7291 p[4] = iso9660->el_torito.system_type;
7295 if (iso9660->el_torito.media_type == BOOT_MEDIA_NO_EMULATION)
7296 set_num_721(&p[6], iso9660->el_torito.boot_load_size);
7298 set_num_721(&p[6], 1);
7301 iso9660->el_torito.boot->file->content.location);
7303 memset(&p[12], 0, 20);
7305 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
7309 setup_boot_information(struct archive_write *a)
7311 struct iso9660 *iso9660 = a->format_data;
7315 unsigned char buff[4096];
7317 np = iso9660->el_torito.boot;
7318 lseek(iso9660->temp_fd,
7319 np->file->content.offset_of_temp + 64, SEEK_SET);
7320 size = archive_entry_size(np->file->entry) - 64;
7322 archive_set_error(&a->archive, errno,
7323 "Boot file(%jd) is too small", (intmax_t)size + 64);
7324 return (ARCHIVE_FATAL);
7331 if (size > (int64_t)sizeof(buff))
7332 rsize = sizeof(buff);
7334 rsize = (size_t)size;
7336 rs = read(iso9660->temp_fd, buff, rsize);
7338 archive_set_error(&a->archive, errno,
7339 "Can't read temporary file(%jd)",
7341 return (ARCHIVE_FATAL);
7343 for (i = 0; i < rs; i += 4)
7344 sum += archive_le32dec(buff + i);
7347 /* Set the location of Primary Volume Descriptor. */
7348 set_num_731(buff, SYSTEM_AREA_BLOCK);
7349 /* Set the location of the boot file. */
7350 set_num_731(buff+4, np->file->content.location);
7351 /* Set the size of the boot file. */
7352 size = fd_boot_image_size(iso9660->el_torito.media_type);
7354 size = archive_entry_size(np->file->entry);
7355 set_num_731(buff+8, (uint32_t)size);
7356 /* Set the sum of the boot file. */
7357 set_num_731(buff+12, sum);
7358 /* Clear reserved bytes. */
7359 memset(buff+16, 0, 40);
7361 /* Overwrite the boot file. */
7362 lseek(iso9660->temp_fd,
7363 np->file->content.offset_of_temp + 8, SEEK_SET);
7364 return (write_to_temp(a, buff, 56));
7370 zisofs_init_zstream(struct archive_write *a)
7372 struct iso9660 *iso9660 = a->format_data;
7375 iso9660->zisofs.stream.next_in = NULL;
7376 iso9660->zisofs.stream.avail_in = 0;
7377 iso9660->zisofs.stream.total_in = 0;
7378 iso9660->zisofs.stream.total_out = 0;
7379 if (iso9660->zisofs.stream_valid)
7380 r = deflateReset(&(iso9660->zisofs.stream));
7382 r = deflateInit(&(iso9660->zisofs.stream),
7383 iso9660->zisofs.compression_level);
7384 iso9660->zisofs.stream_valid = 1;
7390 case Z_STREAM_ERROR:
7391 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7392 "Internal error initializing "
7393 "compression library: invalid setup parameter");
7394 return (ARCHIVE_FATAL);
7396 archive_set_error(&a->archive, ENOMEM,
7397 "Internal error initializing "
7398 "compression library");
7399 return (ARCHIVE_FATAL);
7400 case Z_VERSION_ERROR:
7401 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7402 "Internal error initializing "
7403 "compression library: invalid library version");
7404 return (ARCHIVE_FATAL);
7406 return (ARCHIVE_OK);
7409 #endif /* HAVE_ZLIB_H */
7412 zisofs_init(struct archive_write *a, struct isofile *file)
7414 struct iso9660 *iso9660 = a->format_data;
7417 size_t _ceil, bpsize;
7421 iso9660->zisofs.detect_magic = 0;
7422 iso9660->zisofs.making = 0;
7424 if (!iso9660->opt.rr || !iso9660->opt.zisofs)
7425 return (ARCHIVE_OK);
7427 if (archive_entry_size(file->entry) >= 24 &&
7428 archive_entry_size(file->entry) < MULTI_EXTENT_SIZE) {
7429 /* Acceptable file size for zisofs. */
7430 iso9660->zisofs.detect_magic = 1;
7431 iso9660->zisofs.magic_cnt = 0;
7433 if (!iso9660->zisofs.detect_magic)
7434 return (ARCHIVE_OK);
7437 /* The number of Logical Blocks which uncompressed data
7438 * will use in iso-image file is the same as the number of
7439 * Logical Blocks which zisofs(compressed) data will use
7440 * in ISO-image file. It won't reduce iso-image file size. */
7441 if (archive_entry_size(file->entry) <= LOGICAL_BLOCK_SIZE)
7442 return (ARCHIVE_OK);
7444 /* Initialize compression library */
7445 r = zisofs_init_zstream(a);
7446 if (r != ARCHIVE_OK)
7447 return (ARCHIVE_FATAL);
7449 /* Mark file->zisofs to create RRIP 'ZF' Use Entry. */
7450 file->zisofs.header_size = ZF_HEADER_SIZE >> 2;
7451 file->zisofs.log2_bs = ZF_LOG2_BS;
7452 file->zisofs.uncompressed_size =
7453 (uint32_t)archive_entry_size(file->entry);
7455 /* Calculate a size of Block Pointers of zisofs. */
7456 _ceil = (file->zisofs.uncompressed_size + ZF_BLOCK_SIZE -1)
7457 >> file->zisofs.log2_bs;
7458 iso9660->zisofs.block_pointers_cnt = (int)_ceil + 1;
7459 iso9660->zisofs.block_pointers_idx = 0;
7461 /* Ensure a buffer size used for Block Pointers */
7462 bpsize = iso9660->zisofs.block_pointers_cnt *
7463 sizeof(iso9660->zisofs.block_pointers[0]);
7464 if (iso9660->zisofs.block_pointers_allocated < bpsize) {
7465 free(iso9660->zisofs.block_pointers);
7466 iso9660->zisofs.block_pointers = malloc(bpsize);
7467 if (iso9660->zisofs.block_pointers == NULL) {
7468 archive_set_error(&a->archive, ENOMEM,
7469 "Can't allocate data");
7470 return (ARCHIVE_FATAL);
7472 iso9660->zisofs.block_pointers_allocated = bpsize;
7476 * Skip zisofs header and Block Pointers, which we will write
7477 * after all compressed data of a file written to the temporary
7480 tsize = ZF_HEADER_SIZE + bpsize;
7481 if (write_null(a, (size_t)tsize) != ARCHIVE_OK)
7482 return (ARCHIVE_FATAL);
7485 * Initialize some variables to make zisofs.
7487 archive_le32enc(&(iso9660->zisofs.block_pointers[0]),
7489 iso9660->zisofs.remaining = file->zisofs.uncompressed_size;
7490 iso9660->zisofs.making = 1;
7491 iso9660->zisofs.allzero = 1;
7492 iso9660->zisofs.block_offset = tsize;
7493 iso9660->zisofs.total_size = tsize;
7494 iso9660->cur_file->cur_content->size = tsize;
7497 return (ARCHIVE_OK);
7501 zisofs_detect_magic(struct archive_write *a, const void *buff, size_t s)
7503 struct iso9660 *iso9660 = a->format_data;
7504 struct isofile *file = iso9660->cur_file;
7505 const unsigned char *p, *endp;
7506 const unsigned char *magic_buff;
7507 uint32_t uncompressed_size;
7508 unsigned char header_size;
7509 unsigned char log2_bs;
7515 entry_size = archive_entry_size(file->entry);
7516 if ((int64_t)sizeof(iso9660->zisofs.magic_buffer) > entry_size)
7517 magic_max = (int)entry_size;
7519 magic_max = sizeof(iso9660->zisofs.magic_buffer);
7521 if (iso9660->zisofs.magic_cnt == 0 && s >= (size_t)magic_max)
7522 /* It's unnecessary we copy buffer. */
7525 if (iso9660->zisofs.magic_cnt < magic_max) {
7528 l = sizeof(iso9660->zisofs.magic_buffer)
7529 - iso9660->zisofs.magic_cnt;
7532 memcpy(iso9660->zisofs.magic_buffer
7533 + iso9660->zisofs.magic_cnt, buff, l);
7534 iso9660->zisofs.magic_cnt += (int)l;
7535 if (iso9660->zisofs.magic_cnt < magic_max)
7538 magic_buff = iso9660->zisofs.magic_buffer;
7540 iso9660->zisofs.detect_magic = 0;
7543 /* Check the magic code of zisofs. */
7544 if (memcmp(p, zisofs_magic, sizeof(zisofs_magic)) != 0)
7545 /* This is not zisofs file which made by mkzftree. */
7547 p += sizeof(zisofs_magic);
7549 /* Read a zisofs header. */
7550 uncompressed_size = archive_le32dec(p);
7553 if (uncompressed_size < 24 || header_size != 4 ||
7554 log2_bs > 30 || log2_bs < 7)
7555 return;/* Invalid or not supported header. */
7557 /* Calculate a size of Block Pointers of zisofs. */
7558 _ceil = (uncompressed_size +
7559 (ARCHIVE_LITERAL_LL(1) << log2_bs) -1) >> log2_bs;
7560 doff = (_ceil + 1) * 4 + 16;
7561 if (entry_size < (int64_t)doff)
7562 return;/* Invalid data. */
7564 /* Check every Block Pointer has valid value. */
7565 p = magic_buff + 16;
7566 endp = magic_buff + magic_max;
7567 while (_ceil && p + 8 <= endp) {
7568 bst = archive_le32dec(p);
7570 return;/* Invalid data. */
7572 bed = archive_le32dec(p);
7573 if (bed < bst || bed > entry_size)
7574 return;/* Invalid data. */
7579 file->zisofs.uncompressed_size = uncompressed_size;
7580 file->zisofs.header_size = header_size;
7581 file->zisofs.log2_bs = log2_bs;
7583 /* Disable making a zisofs image. */
7584 iso9660->zisofs.making = 0;
7590 * Compress data and write it to a temporary file.
7593 zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s)
7595 struct iso9660 *iso9660 = a->format_data;
7596 struct isofile *file = iso9660->cur_file;
7597 const unsigned char *b;
7599 size_t avail, csize;
7602 zstrm = &(iso9660->zisofs.stream);
7603 zstrm->next_out = wb_buffptr(a);
7604 zstrm->avail_out = (uInt)wb_remaining(a);
7605 b = (const unsigned char *)buff;
7607 avail = ZF_BLOCK_SIZE - zstrm->total_in;
7613 iso9660->zisofs.remaining -= avail;
7614 if (iso9660->zisofs.remaining <= 0)
7617 zstrm->next_in = (Bytef *)(uintptr_t)(const void *)b;
7618 zstrm->avail_in = (uInt)avail;
7621 * Check if current data block are all zero.
7623 if (iso9660->zisofs.allzero) {
7624 const unsigned char *nonzero = b;
7625 const unsigned char *nonzeroend = b + avail;
7627 while (nonzero < nonzeroend)
7629 iso9660->zisofs.allzero = 0;
7637 * If current data block are all zero, we do not use
7640 if (flush == Z_FINISH && iso9660->zisofs.allzero &&
7641 avail + zstrm->total_in == ZF_BLOCK_SIZE) {
7642 if (iso9660->zisofs.block_offset !=
7643 file->cur_content->size) {
7646 r = wb_set_offset(a,
7647 file->cur_content->offset_of_temp +
7648 iso9660->zisofs.block_offset);
7649 if (r != ARCHIVE_OK)
7651 diff = file->cur_content->size -
7652 iso9660->zisofs.block_offset;
7653 file->cur_content->size -= diff;
7654 iso9660->zisofs.total_size -= diff;
7656 zstrm->avail_in = 0;
7660 * Compress file data.
7662 while (zstrm->avail_in > 0) {
7663 csize = zstrm->total_out;
7664 r = deflate(zstrm, flush);
7668 csize = zstrm->total_out - csize;
7669 if (wb_consume(a, csize) != ARCHIVE_OK)
7670 return (ARCHIVE_FATAL);
7671 iso9660->zisofs.total_size += csize;
7672 iso9660->cur_file->cur_content->size += csize;
7673 zstrm->next_out = wb_buffptr(a);
7674 zstrm->avail_out = (uInt)wb_remaining(a);
7677 archive_set_error(&a->archive,
7679 "Compression failed:"
7680 " deflate() call returned status %d",
7682 return (ARCHIVE_FATAL);
7686 if (flush == Z_FINISH) {
7688 * Save the information of one zisofs block.
7690 iso9660->zisofs.block_pointers_idx ++;
7691 archive_le32enc(&(iso9660->zisofs.block_pointers[
7692 iso9660->zisofs.block_pointers_idx]),
7693 (uint32_t)iso9660->zisofs.total_size);
7694 r = zisofs_init_zstream(a);
7695 if (r != ARCHIVE_OK)
7696 return (ARCHIVE_FATAL);
7697 iso9660->zisofs.allzero = 1;
7698 iso9660->zisofs.block_offset = file->cur_content->size;
7702 return (ARCHIVE_OK);
7706 zisofs_finish_entry(struct archive_write *a)
7708 struct iso9660 *iso9660 = a->format_data;
7709 struct isofile *file = iso9660->cur_file;
7710 unsigned char buff[16];
7714 /* Direct temp file stream to zisofs temp file stream. */
7715 archive_entry_set_size(file->entry, iso9660->zisofs.total_size);
7718 * Save a file pointer which points the end of current zisofs data.
7720 tail = wb_offset(a);
7725 * +-----------------+----------------+-----------------+
7726 * | Header 16 bytes | Block Pointers | Compressed data |
7727 * +-----------------+----------------+-----------------+
7730 * 4 * (((Uncompressed file size + block_size -1) / block_size) + 1)
7732 * Write zisofs header.
7734 * +----+----+----+----+----+----+----+----+
7735 * | 37 | E4 | 53 | 96 | C9 | DB | D6 | 07 |
7736 * +----+----+----+----+----+----+----+----+
7739 * +------------------------+------------------+
7740 * | Uncompressed file size | header_size >> 2 |
7741 * +------------------------+------------------+
7744 * +-----------------+----------------+
7745 * | log2 block_size | Reserved(0000) |
7746 * +-----------------+----------------+
7749 memcpy(buff, zisofs_magic, 8);
7750 set_num_731(buff+8, file->zisofs.uncompressed_size);
7751 buff[12] = file->zisofs.header_size;
7752 buff[13] = file->zisofs.log2_bs;
7753 buff[14] = buff[15] = 0;/* Reserved */
7755 /* Move to the right position to write the header. */
7756 wb_set_offset(a, file->content.offset_of_temp);
7758 /* Write the header. */
7759 if (wb_write_to_temp(a, buff, 16) != ARCHIVE_OK)
7760 return (ARCHIVE_FATAL);
7763 * Write zisofs Block Pointers.
7765 s = iso9660->zisofs.block_pointers_cnt *
7766 sizeof(iso9660->zisofs.block_pointers[0]);
7767 if (wb_write_to_temp(a, iso9660->zisofs.block_pointers, s)
7769 return (ARCHIVE_FATAL);
7771 /* Set a file pointer back to the end of the temporary file. */
7772 wb_set_offset(a, tail);
7774 return (ARCHIVE_OK);
7778 zisofs_free(struct archive_write *a)
7780 struct iso9660 *iso9660 = a->format_data;
7781 int ret = ARCHIVE_OK;
7783 free(iso9660->zisofs.block_pointers);
7784 if (iso9660->zisofs.stream_valid &&
7785 deflateEnd(&(iso9660->zisofs.stream)) != Z_OK) {
7786 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7787 "Failed to clean up compressor");
7788 ret = ARCHIVE_FATAL;
7790 iso9660->zisofs.block_pointers = NULL;
7791 iso9660->zisofs.stream_valid = 0;
7795 struct zisofs_extract {
7796 int pz_log2_bs; /* Log2 of block size */
7797 uint64_t pz_uncompressed_size;
7798 size_t uncompressed_buffer_size;
7801 int header_passed:1;
7804 unsigned char *block_pointers;
7805 size_t block_pointers_size;
7806 size_t block_pointers_avail;
7808 uint32_t block_avail;
7815 zisofs_extract_init(struct archive_write *a, struct zisofs_extract *zisofs,
7816 const unsigned char *p, size_t bytes)
7818 size_t avail = bytes;
7819 size_t _ceil, xsize;
7821 /* Allocate block pointers buffer. */
7822 _ceil = (size_t)((zisofs->pz_uncompressed_size +
7823 (((int64_t)1) << zisofs->pz_log2_bs) - 1)
7824 >> zisofs->pz_log2_bs);
7825 xsize = (_ceil + 1) * 4;
7826 if (zisofs->block_pointers == NULL) {
7827 size_t alloc = ((xsize >> 10) + 1) << 10;
7828 zisofs->block_pointers = malloc(alloc);
7829 if (zisofs->block_pointers == NULL) {
7830 archive_set_error(&a->archive, ENOMEM,
7831 "No memory for zisofs decompression");
7832 return (ARCHIVE_FATAL);
7835 zisofs->block_pointers_size = xsize;
7837 /* Allocate uncompressed data buffer. */
7838 zisofs->uncompressed_buffer_size = (size_t)1UL << zisofs->pz_log2_bs;
7841 * Read the file header, and check the magic code of zisofs.
7843 if (!zisofs->header_passed) {
7846 archive_set_error(&a->archive,
7847 ARCHIVE_ERRNO_FILE_FORMAT,
7848 "Illegal zisofs file body");
7849 return (ARCHIVE_FATAL);
7852 if (memcmp(p, zisofs_magic, sizeof(zisofs_magic)) != 0)
7854 else if (archive_le32dec(p + 8) != zisofs->pz_uncompressed_size)
7856 else if (p[12] != 4 || p[13] != zisofs->pz_log2_bs)
7859 archive_set_error(&a->archive,
7860 ARCHIVE_ERRNO_FILE_FORMAT,
7861 "Illegal zisofs file body");
7862 return (ARCHIVE_FATAL);
7866 zisofs->header_passed = 1;
7870 * Read block pointers.
7872 if (zisofs->header_passed &&
7873 zisofs->block_pointers_avail < zisofs->block_pointers_size) {
7874 xsize = zisofs->block_pointers_size
7875 - zisofs->block_pointers_avail;
7878 memcpy(zisofs->block_pointers
7879 + zisofs->block_pointers_avail, p, xsize);
7880 zisofs->block_pointers_avail += xsize;
7882 if (zisofs->block_pointers_avail
7883 == zisofs->block_pointers_size) {
7884 /* We've got all block pointers and initialize
7885 * related variables. */
7886 zisofs->block_off = 0;
7887 zisofs->block_avail = 0;
7888 /* Complete a initialization */
7889 zisofs->initialized = 1;
7892 return ((ssize_t)avail);
7896 zisofs_extract(struct archive_write *a, struct zisofs_extract *zisofs,
7897 const unsigned char *p, size_t bytes)
7902 if (!zisofs->initialized) {
7903 ssize_t rs = zisofs_extract_init(a, zisofs, p, bytes);
7906 if (!zisofs->initialized) {
7907 /* We need more data. */
7908 zisofs->pz_offset += (uint32_t)bytes;
7917 * Get block offsets from block pointers.
7919 if (zisofs->block_avail == 0) {
7922 if (zisofs->block_off + 4 >= zisofs->block_pointers_size) {
7923 /* There isn't a pair of offsets. */
7924 archive_set_error(&a->archive,
7925 ARCHIVE_ERRNO_FILE_FORMAT,
7926 "Illegal zisofs block pointers");
7927 return (ARCHIVE_FATAL);
7929 bst = archive_le32dec(
7930 zisofs->block_pointers + zisofs->block_off);
7931 if (bst != zisofs->pz_offset + (bytes - avail)) {
7932 archive_set_error(&a->archive,
7933 ARCHIVE_ERRNO_FILE_FORMAT,
7934 "Illegal zisofs block pointers(cannot seek)");
7935 return (ARCHIVE_FATAL);
7937 bed = archive_le32dec(
7938 zisofs->block_pointers + zisofs->block_off + 4);
7940 archive_set_error(&a->archive,
7941 ARCHIVE_ERRNO_FILE_FORMAT,
7942 "Illegal zisofs block pointers");
7943 return (ARCHIVE_FATAL);
7945 zisofs->block_avail = bed - bst;
7946 zisofs->block_off += 4;
7948 /* Initialize compression library for new block. */
7949 if (zisofs->stream_valid)
7950 r = inflateReset(&zisofs->stream);
7952 r = inflateInit(&zisofs->stream);
7954 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7955 "Can't initialize zisofs decompression.");
7956 return (ARCHIVE_FATAL);
7958 zisofs->stream_valid = 1;
7959 zisofs->stream.total_in = 0;
7960 zisofs->stream.total_out = 0;
7964 * Make uncompressed data.
7966 if (zisofs->block_avail == 0) {
7968 * It's basically 32K bytes NUL data.
7973 size = zisofs->uncompressed_buffer_size;
7976 if (size > wb_remaining(a))
7977 wsize = wb_remaining(a);
7980 memset(wb, 0, wsize);
7981 r = wb_consume(a, wsize);
7987 zisofs->stream.next_in = (Bytef *)(uintptr_t)(const void *)p;
7988 if (avail > zisofs->block_avail)
7989 zisofs->stream.avail_in = zisofs->block_avail;
7991 zisofs->stream.avail_in = (uInt)avail;
7992 zisofs->stream.next_out = wb_buffptr(a);
7993 zisofs->stream.avail_out = (uInt)wb_remaining(a);
7995 r = inflate(&zisofs->stream, 0);
7997 case Z_OK: /* Decompressor made some progress.*/
7998 case Z_STREAM_END: /* Found end of stream. */
8001 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
8002 "zisofs decompression failed (%d)", r);
8003 return (ARCHIVE_FATAL);
8005 avail -= zisofs->stream.next_in - p;
8006 zisofs->block_avail -= (uint32_t)(zisofs->stream.next_in - p);
8007 r = wb_consume(a, wb_remaining(a) - zisofs->stream.avail_out);
8011 zisofs->pz_offset += (uint32_t)bytes;
8012 return (bytes - avail);
8016 zisofs_rewind_boot_file(struct archive_write *a)
8018 struct iso9660 *iso9660 = a->format_data;
8019 struct isofile *file;
8020 unsigned char *rbuff;
8022 size_t remaining, rbuff_size;
8023 struct zisofs_extract zext;
8024 int64_t read_offset, write_offset, new_offset;
8025 int fd, ret = ARCHIVE_OK;
8027 file = iso9660->el_torito.boot->file;
8029 * There is nothing to do if this boot file does not have
8032 if (file->zisofs.header_size == 0)
8033 return (ARCHIVE_OK);
8036 * Uncompress the zisofs'ed file contents.
8038 memset(&zext, 0, sizeof(zext));
8039 zext.pz_uncompressed_size = file->zisofs.uncompressed_size;
8040 zext.pz_log2_bs = file->zisofs.log2_bs;
8042 fd = iso9660->temp_fd;
8043 new_offset = wb_offset(a);
8044 read_offset = file->content.offset_of_temp;
8045 remaining = (size_t)file->content.size;
8046 if (remaining > 1024 * 32)
8047 rbuff_size = 1024 * 32;
8049 rbuff_size = remaining;
8051 rbuff = malloc(rbuff_size);
8052 if (rbuff == NULL) {
8053 archive_set_error(&a->archive, ENOMEM, "Can't allocate memory");
8054 return (ARCHIVE_FATAL);
8060 /* Get the current file pointer. */
8061 write_offset = lseek(fd, 0, SEEK_CUR);
8063 /* Change the file pointer to read. */
8064 lseek(fd, read_offset, SEEK_SET);
8067 if (rsize > remaining)
8069 rs = read(iso9660->temp_fd, rbuff, rsize);
8071 archive_set_error(&a->archive, errno,
8072 "Can't read temporary file(%jd)", (intmax_t)rs);
8073 ret = ARCHIVE_FATAL;
8079 /* Put the file pointer back to write. */
8080 lseek(fd, write_offset, SEEK_SET);
8082 r = zisofs_extract(a, &zext, rbuff, rs);
8089 if (ret == ARCHIVE_OK) {
8091 * Change the boot file content from zisofs'ed data
8094 file->content.offset_of_temp = new_offset;
8095 file->content.size = file->zisofs.uncompressed_size;
8096 archive_entry_set_size(file->entry, file->content.size);
8097 /* Set to be no zisofs. */
8098 file->zisofs.header_size = 0;
8099 file->zisofs.log2_bs = 0;
8100 file->zisofs.uncompressed_size = 0;
8101 r = wb_write_padding_to_temp(a, file->content.size);
8103 ret = ARCHIVE_FATAL;
8107 * Free the resource we used in this function only.
8110 free(zext.block_pointers);
8111 if (zext.stream_valid && inflateEnd(&(zext.stream)) != Z_OK) {
8112 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
8113 "Failed to clean up compressor");
8114 ret = ARCHIVE_FATAL;
8123 zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s)
8125 (void)buff; /* UNUSED */
8126 (void)s; /* UNUSED */
8127 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Programing error");
8128 return (ARCHIVE_FATAL);
8132 zisofs_rewind_boot_file(struct archive_write *a)
8134 struct iso9660 *iso9660 = a->format_data;
8136 if (iso9660->el_torito.boot->file->zisofs.header_size != 0) {
8137 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
8138 "We cannot extract the zisofs imaged boot file;"
8139 " this may not boot in being zisofs imaged");
8140 return (ARCHIVE_FAILED);
8142 return (ARCHIVE_OK);
8146 zisofs_finish_entry(struct archive_write *a)
8148 (void)a; /* UNUSED */
8149 return (ARCHIVE_OK);
8153 zisofs_free(struct archive_write *a)
8155 (void)a; /* UNUSED */
8156 return (ARCHIVE_OK);
8159 #endif /* HAVE_ZLIB_H */