]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/libarchive/libarchive/archive_write_set_format_iso9660.c
MFC r368207,368607:
[FreeBSD/stable/10.git] / contrib / libarchive / libarchive / archive_write_set_format_iso9660.c
1 /*-
2  * Copyright (c) 2009-2012 Michihiro NAKAJIMA
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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.
24  */
25
26 #include "archive_platform.h"
27
28 #ifdef HAVE_SYS_TYPES_H
29 #include <sys/types.h>
30 #endif
31 #ifdef HAVE_SYS_UTSNAME_H
32 #include <sys/utsname.h>
33 #endif
34 #ifdef HAVE_ERRNO_H
35 #include <errno.h>
36 #endif
37 #ifdef HAVE_LIMITS_H
38 #include <limits.h>
39 #endif
40 #include <stdio.h>
41 #include <stdarg.h>
42 #ifdef HAVE_STDLIB_H
43 #include <stdlib.h>
44 #endif
45 #include <time.h>
46 #ifdef HAVE_UNISTD_H
47 #include <unistd.h>
48 #endif
49 #ifdef HAVE_ZLIB_H
50 #include <zlib.h>
51 #endif
52
53 #include "archive.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"
60
61 #if defined(_WIN32) && !defined(__CYGWIN__)
62 #define getuid()                        0
63 #define getgid()                        0
64 #endif
65
66 /*#define DEBUG 1*/
67 #ifdef DEBUG
68 /* To compare to the ISO image file made by mkisofs. */
69 #define COMPAT_MKISOFS          1
70 #endif
71
72 #define LOGICAL_BLOCK_BITS                      11
73 #define LOGICAL_BLOCK_SIZE                      2048
74 #define PATH_TABLE_BLOCK_SIZE                   4096
75
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
84
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. */
89 #define MAX_DEPTH               8
90 #define RR_CE_SIZE              28              /* SUSP "CE" extension size */
91
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
98
99 static const char rrip_identifier[] =
100         "RRIP_1991A";
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)
113
114 static const unsigned char zisofs_magic[8] = {
115         0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07
116 };
117
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)
121
122 /*
123  * Manage extra records.
124  */
125 struct extr_rec {
126         int              location;
127         int              offset;
128         unsigned char    buf[LOGICAL_BLOCK_SIZE];
129         struct extr_rec *next;
130 };
131
132 struct ctl_extr_rec {
133         int              use_extr;
134         unsigned char   *bp;
135         struct isoent   *isoent;
136         unsigned char   *ce_ptr;
137         int              cur_len;
138         int              dr_len;
139         int              limit;
140         int              extr_off;
141         int              extr_loc;
142 };
143 #define DR_SAFETY       RR_CE_SIZE
144 #define DR_LIMIT        (254 - DR_SAFETY)
145
146 /*
147  * The relation of struct isofile and isoent and archive_entry.
148  *
149  * Primary volume tree  --> struct isoent
150  *                                |
151  *                                v
152  *                          struct isofile --> archive_entry
153  *                                ^
154  *                                |
155  * Joliet volume tree   --> struct isoent
156  *
157  * struct isoent has specific information for volume.
158  */
159
160 struct isofile {
161         /* Used for managing struct isofile list. */
162         struct isofile          *allnext;
163         struct isofile          *datanext;
164         /* Used for managing a hardlinked struct isofile list. */
165         struct isofile          *hlnext;
166         struct isofile          *hardlink_target;
167
168         struct archive_entry    *entry;
169
170         /*
171          * Used for making a directory tree.
172          */
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 */
179
180         /*
181          * Used for a Directory Record.
182          */
183         struct content {
184                 int64_t          offset_of_temp;
185                 int64_t          size;
186                 int              blocks;
187                 uint32_t         location;
188                 /*
189                  * One extent equals one content.
190                  * If this entry has multi extent, `next' variable points
191                  * next content data.
192                  */
193                 struct content  *next;          /* next content */
194         } content, *cur_content;
195         int                      write_content;
196
197         enum {
198                 NO = 0,
199                 BOOT_CATALOG,
200                 BOOT_IMAGE
201         } boot;
202
203         /*
204          * Used for a zisofs.
205          */
206         struct {
207                 unsigned char    header_size;
208                 unsigned char    log2_bs;
209                 uint32_t         uncompressed_size;
210         } zisofs;
211 };
212
213 struct isoent {
214         /* Keep `rbnode' at the first member of struct isoent. */
215         struct archive_rb_node   rbnode;
216
217         struct isofile          *file;
218
219         struct isoent           *parent;
220         /* A list of children.(use chnext) */
221         struct {
222                 struct isoent   *first;
223                 struct isoent   **last;
224                 int              cnt;
225         }                        children;
226         struct archive_rb_tree   rbtree;
227
228         /* A list of sub directories.(use drnext) */
229         struct {
230                 struct isoent   *first;
231                 struct isoent   **last;
232                 int              cnt;
233         }                        subdirs;
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;
240
241         /*
242          * Used for making a Directory Record.
243          */
244         int                      dir_number;
245         struct {
246                 int              vd;
247                 int              self;
248                 int              parent;
249                 int              normal;
250         }                        dr_len;
251         uint32_t                 dir_location;
252         int                      dir_block;
253
254         /*
255          * Identifier:
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.
266          */
267         char                    *identifier;
268         int                      ext_off;
269         int                      ext_len;
270         int                      id_len;
271         int                      mb_len;
272
273         /*
274          * Used for making a Rockridge extension.
275          * This is a part of Directory Records.
276          */
277         struct isoent           *rr_parent;
278         struct isoent           *rr_child;
279
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
284          * Extra Record.
285          */
286         struct {
287                 struct extr_rec *first;
288                 struct extr_rec **last;
289                 struct extr_rec *current;
290         }                        extr_rec_list;
291
292         signed int               virtual:1;
293         /* If set to one, this file type is a directory.
294          * A convenience flag to be used as
295          * "archive_entry_filetype(isoent->file->entry) == AE_IFDIR".
296          */
297         signed int               dir:1;
298 };
299
300 struct hardlink {
301         struct archive_rb_node   rbnode;
302         int                      nlink;
303         struct {
304                 struct isofile  *first;
305                 struct isofile  **last;
306         }                        file_list;
307 };
308
309 /*
310  * ISO writer options
311  */
312 struct iso_option {
313         /*
314          * Usage  : abstract-file=<value>
315          * Type   : string, max 37 bytes
316          * Default: Not specified
317          * COMPAT : mkisofs -abstract <value>
318          *
319          * Specifies Abstract Filename.
320          * This file shall be described in the Root Directory
321          * and containing a abstract statement.
322          */
323         unsigned int     abstract_file:1;
324 #define OPT_ABSTRACT_FILE_DEFAULT       0       /* Not specified */
325 #define ABSTRACT_FILE_SIZE              37
326
327         /*
328          * Usage  : application-id=<value>
329          * Type   : string, max 128 bytes
330          * Default: Not specified
331          * COMPAT : mkisofs -A/-appid <value>.
332          *
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
337          * application.
338          * This file shall be described in the Root Directory.
339          */
340         unsigned int     application_id:1;
341 #define OPT_APPLICATION_ID_DEFAULT      0       /* Use default identifier */
342 #define APPLICATION_IDENTIFIER_SIZE     128
343
344         /*
345          * Usage : !allow-vernum
346          * Type  : boolean
347          * Default: Enabled
348          *        : Violates the ISO9660 standard if disable.
349          * COMPAT: mkisofs -N
350          *
351          * Allow filenames to use version numbers.
352          */
353         unsigned int     allow_vernum:1;
354 #define OPT_ALLOW_VERNUM_DEFAULT        1       /* Enabled */
355
356         /*
357          * Usage  : biblio-file=<value>
358          * Type   : string, max 37 bytes
359          * Default: Not specified
360          * COMPAT : mkisofs -biblio <value>
361          *
362          * Specifies Bibliographic Filename.
363          * This file shall be described in the Root Directory
364          * and containing bibliographic records.
365          */
366         unsigned int     biblio_file:1;
367 #define OPT_BIBLIO_FILE_DEFAULT         0       /* Not specified */
368 #define BIBLIO_FILE_SIZE                37
369
370         /*
371          * Usage  : boot=<value>
372          * Type   : string
373          * Default: Not specified
374          * COMPAT : mkisofs -b/-eltorito-boot <value>
375          *
376          * Specifies "El Torito" boot image file to make
377          * a bootable CD.
378          */
379         unsigned int     boot:1;
380 #define OPT_BOOT_DEFAULT                0       /* Not specified */
381
382         /*
383          * Usage  : boot-catalog=<value>
384          * Type   : string
385          * Default: "boot.catalog"
386          * COMPAT : mkisofs -c/-eltorito-catalog <value>
387          *
388          * Specifies a fullpath of El Torito boot catalog.
389          */
390         unsigned int     boot_catalog:1;
391 #define OPT_BOOT_CATALOG_DEFAULT        0       /* Not specified */
392
393         /*
394          * Usage  : boot-info-table
395          * Type   : boolean
396          * Default: Disabled
397          * COMPAT : mkisofs -boot-info-table
398          *
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
402          * through offset 64.
403          */
404         unsigned int     boot_info_table:1;
405 #define OPT_BOOT_INFO_TABLE_DEFAULT     0       /* Disabled */
406
407         /*
408          * Usage  : boot-load-seg=<value>
409          * Type   : hexadecimal
410          * Default: Not specified
411          * COMPAT : mkisofs -boot-load-seg <value>
412          *
413          * Specifies a load segment for boot image.
414          * This is used with no-emulation mode.
415          */
416         unsigned int     boot_load_seg:1;
417 #define OPT_BOOT_LOAD_SEG_DEFAULT       0       /* Not specified */
418
419         /*
420          * Usage  : boot-load-size=<value>
421          * Type   : decimal
422          * Default: Not specified
423          * COMPAT : mkisofs -boot-load-size <value>
424          *
425          * Specifies a sector count for boot image.
426          * This is used with no-emulation mode.
427          */
428         unsigned int     boot_load_size:1;
429 #define OPT_BOOT_LOAD_SIZE_DEFAULT      0       /* Not specified */
430
431         /*
432          * Usage  : boot-type=<boot-media-type>
433          *        : 'no-emulation' : 'no emulation' image
434          *        :           'fd' : floppy disk image
435          *        :    'hard-disk' : hard disk image
436          * Type   : string
437          * Default: Auto detect
438          *        : We check a size of boot image;
439          *        : If the size is just 1.22M/1.44M/2.88M,
440          *        : we assume boot_type is 'fd';
441          *        : otherwise boot_type is 'no-emulation'.
442          * COMPAT :
443          *    boot=no-emulation
444          *      mkisofs -no-emul-boot
445          *    boot=fd
446          *      This is a default on the mkisofs.
447          *    boot=hard-disk
448          *      mkisofs -hard-disk-boot
449          *
450          * Specifies a type of "El Torito" boot image.
451          */
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
458
459         /*
460          * Usage  : compression-level=<value>
461          * Type   : decimal
462          * Default: Not specified
463          * COMPAT : NONE
464          *
465          * Specifies compression level for option zisofs=direct.
466          */
467         unsigned int     compression_level:1;
468 #define OPT_COMPRESSION_LEVEL_DEFAULT   0       /* Not specified */
469
470         /*
471          * Usage  : copyright-file=<value>
472          * Type   : string, max 37 bytes
473          * Default: Not specified
474          * COMPAT : mkisofs -copyright <value>
475          *
476          * Specifies Copyright Filename.
477          * This file shall be described in the Root Directory
478          * and containing a copyright statement.
479          */
480         unsigned int     copyright_file:1;
481 #define OPT_COPYRIGHT_FILE_DEFAULT      0       /* Not specified */
482 #define COPYRIGHT_FILE_SIZE             37
483
484         /*
485          * Usage  : gid=<value>
486          * Type   : decimal
487          * Default: Not specified
488          * COMPAT : mkisofs -gid <value>
489          *
490          * Specifies a group id to rewrite the group id of all files.
491          */
492         unsigned int     gid:1;
493 #define OPT_GID_DEFAULT                 0       /* Not specified */
494
495         /*
496          * Usage  : iso-level=[1234]
497          * Type   : decimal
498          * Default: 1
499          * COMPAT : mkisofs -iso-level <value>
500          *
501          * Specifies ISO9600 Level.
502          * Level 1: [DEFAULT]
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.
510          * Level 2:
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
518          *     d1-characters.
519          * Level 3:
520          *   - no limit of file size; use multi extent.
521          * Level 4:
522          *   - this level 4 simulates mkisofs option
523          *     '-iso-level 4';
524          *   - crate a enhanced volume as mkisofs doing;
525          *   - allow a File Name to have leading dot;
526          *   - allow a File Name to have all ASCII letters;
527          *   - allow a File Name to have multiple dots;
528          *   - allow more then 8 depths of directory trees;
529          *   - disable a version number to a File Name;
530          *   - disable a forced period to the tail of a File Name;
531          *   - the maximum length of files and directories is raised to 193.
532          *     if rockridge option is disabled, raised to 207.
533          */
534         unsigned int     iso_level:3;
535 #define OPT_ISO_LEVEL_DEFAULT           1       /* ISO Level 1 */
536
537         /*
538          * Usage  : joliet[=long]
539          *        : !joliet
540          *        :   Do not generate Joliet Volume and Records.
541          *        : joliet [DEFAULT]
542          *        :   Generates Joliet Volume and Directory Records.
543          *        :   [COMPAT: mkisofs -J/-joliet]
544          *        : joliet=long
545          *        :   The joliet filenames are up to 103 Unicode
546          *        :   characters.
547          *        :   This option breaks the Joliet specification.
548          *        :   [COMPAT: mkisofs -J -joliet-long]
549          * Type   : boolean/string
550          * Default: Enabled
551          * COMPAT : mkisofs -J / -joliet-long
552          *
553          * Generates Joliet Volume and Directory Records.
554          */
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
560
561         /*
562          * Usage  : !limit-depth
563          * Type   : boolean
564          * Default: Enabled
565          *        : Violates the ISO9660 standard if disable.
566          * COMPAT : mkisofs -D/-disable-deep-relocation
567          *
568          * The number of levels in hierarchy cannot exceed eight.
569          */
570         unsigned int     limit_depth:1;
571 #define OPT_LIMIT_DEPTH_DEFAULT         1       /* Enabled */
572
573         /*
574          * Usage  : !limit-dirs
575          * Type   : boolean
576          * Default: Enabled
577          *        : Violates the ISO9660 standard if disable.
578          * COMPAT : mkisofs -no-limit-pathtables
579          *
580          * Limits the number of directories less than 65536 due
581          * to the size of the Parent Directory Number of Path
582          * Table.
583          */
584         unsigned int     limit_dirs:1;
585 #define OPT_LIMIT_DIRS_DEFAULT          1       /* Enabled */
586
587         /*
588          * Usage  : !pad
589          * Type   : boolean
590          * Default: Enabled
591          * COMPAT : -pad/-no-pad
592          *
593          * Pads the end of the ISO image by null of 300Ki bytes.
594          */
595         unsigned int     pad:1;
596 #define OPT_PAD_DEFAULT                 1       /* Enabled */
597
598         /*
599          * Usage  : publisher=<value>
600          * Type   : string, max 128 bytes
601          * Default: Not specified
602          * COMPAT : mkisofs -publisher <value>
603          *
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.
609          */
610         unsigned int     publisher:1;
611 #define OPT_PUBLISHER_DEFAULT           0       /* Not specified */
612 #define PUBLISHER_IDENTIFIER_SIZE       128
613
614         /*
615          * Usage  : rockridge
616          *        : !rockridge
617          *        :    disable to generate SUSP and RR records.
618          *        : rockridge
619          *        :    the same as 'rockridge=useful'.
620          *        : rockridge=strict
621          *        :    generate SUSP and RR records.
622          *        :    [COMPAT: mkisofs -R]
623          *        : rockridge=useful [DEFAULT]
624          *        :    generate SUSP and RR records.
625          *        :    [COMPAT: mkisofs -r]
626          *        :    NOTE  Our rockridge=useful option does not set a zero
627          *        :          to uid and gid, you should use application
628          *        :          option such as --gid,--gname,--uid and --uname
629          *        :          bsdtar options instead.
630          * Type   : boolean/string
631          * Default: Enabled as rockridge=useful
632          * COMPAT : mkisofs -r / -R
633          *
634          * Generates SUSP and RR records.
635          */
636         unsigned int     rr:2;
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
641
642         /*
643          * Usage  : volume-id=<value>
644          * Type   : string, max 32 bytes
645          * Default: Not specified
646          * COMPAT : mkisofs -V <value>
647          *
648          * Specifies Volume Identifier.
649          */
650         unsigned int     volume_id:1;
651 #define OPT_VOLUME_ID_DEFAULT           0       /* Use default identifier */
652 #define VOLUME_IDENTIFIER_SIZE          32
653
654         /*
655          * Usage  : !zisofs [DEFAULT] 
656          *        :    Disable to generate RRIP 'ZF' extension.
657          *        : zisofs
658          *        :    Make files zisofs file and generate RRIP 'ZF'
659          *        :    extension. So you do not need mkzftree utility
660          *        :    for making zisofs.
661          *        :    When the file size is less than one Logical Block
662          *        :    size, that file will not zisofs'ed since it does
663          *        :    reduce an ISO-image size.
664          *        :
665          *        :    When you specify option 'boot=<boot-image>', that
666          *        :    'boot-image' file won't be converted to zisofs file.
667          * Type   : boolean
668          * Default: Disabled
669          *
670          * Generates RRIP 'ZF' System Use Entry.
671          */
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
676
677 };
678
679 struct iso9660 {
680         /* The creation time of ISO image. */
681         time_t                   birth_time;
682         /* A file stream of a temporary file, which file contents
683          * save to until ISO image can be created. */
684         int                      temp_fd;
685
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;
691
692         /* Temporary string buffer for Joliet extension. */ 
693         struct archive_string    utf16be;
694         struct archive_string    mbs;
695
696         struct archive_string_conv *sconv_to_utf16be;
697         struct archive_string_conv *sconv_from_utf16be;
698
699         /* A list of all of struct isofile entries. */
700         struct {
701                 struct isofile  *first;
702                 struct isofile  **last;
703         }                        all_file_list;
704
705         /* A list of struct isofile entries which have its
706          * contents and are not a directory, a hardlinked file
707          * and a symlink file. */
708         struct {
709                 struct isofile  *first;
710                 struct isofile  **last;
711         }                        data_file_list;
712
713         /* Used for managing to find hardlinking files. */
714         struct archive_rb_tree   hardlink_rbtree;
715
716         /* Used for making the Path Table Record. */
717         struct vdd {
718                 /* the root of entry tree. */
719                 struct isoent   *rootent;
720                 enum vdd_type {
721                         VDD_PRIMARY,
722                         VDD_JOLIET,
723                         VDD_ENHANCED
724                 } vdd_type;
725
726                 struct path_table {
727                         struct isoent           *first;
728                         struct isoent           **last;
729                         struct isoent           **sorted;
730                         int                      cnt;
731                 } *pathtbl;
732                 int                              max_depth;
733
734                 int              path_table_block;
735                 int              path_table_size;
736                 int              location_type_L_path_table;
737                 int              location_type_M_path_table;
738                 int              total_dir_block;
739         } primary, joliet;
740
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;
752
753         /* Used for making rockridge extensions. */
754         int                      location_rrip_er;
755
756         /* Used for making zisofs. */
757         struct {
758                 signed int       detect_magic:1;
759                 signed int       making:1;
760                 signed int       allzero:1;
761                 unsigned char    magic_buffer[64];
762                 int              magic_cnt;
763
764 #ifdef HAVE_ZLIB_H
765                 /*
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.
774                  */
775                 uint32_t        *block_pointers;
776                 size_t           block_pointers_allocated;
777                 int              block_pointers_cnt;
778                 int              block_pointers_idx;
779                 int64_t          total_size;
780                 int64_t          block_offset;
781
782                 z_stream         stream;
783                 int              stream_valid;
784                 int64_t          remaining;
785                 int              compression_level;
786 #endif
787         } zisofs;
788
789         struct isoent           *directories_too_deep;
790         int                      dircnt_max;
791
792         /* Write buffer. */
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;
799         enum {
800                 WB_TO_STREAM,
801                 WB_TO_TEMP
802         }                        wbuff_type;
803         int64_t                  wbuff_offset;
804         int64_t                  wbuff_written;
805         int64_t                  wbuff_tail;
806
807         /* 'El Torito' boot data. */
808         struct {
809                 /* boot catalog file */
810                 struct archive_string    catalog_filename;
811                 struct isoent           *catalog;
812                 /* boot image file */
813                 struct archive_string    boot_filename;
814                 struct isoent           *boot;
815
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
831         } el_torito;
832
833         struct iso_option        opt;
834 };
835
836 /*
837  * Types of Volume Descriptor
838  */
839 enum VD_type {
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     */
844 };
845
846 /*
847  * Types of Directory Record
848  */
849 enum dir_rec_type {
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.             */
854 };
855
856 /*
857  * Kinds of Volume Descriptor Character
858  */
859 enum vdc {
860         VDC_STD,
861         VDC_LOWERCASE,
862         VDC_UCS2,
863         VDC_UCS2_DIRECT
864 };
865
866 /*
867  * IDentifier Resolver.
868  * Used for resolving duplicated filenames.
869  */
870 struct idr {
871         struct idrent {
872                 struct archive_rb_node  rbnode;
873                 /* Used in wait_list. */
874                 struct idrent           *wnext;
875                 struct idrent           *avail;
876
877                 struct isoent           *isoent;
878                 int                      weight;
879                 int                      noff;
880                 int                      rename_num;
881         } *idrent_pool;
882
883         struct archive_rb_tree           rbtree;
884
885         struct {
886                 struct idrent           *first;
887                 struct idrent           **last;
888         } wait_list;
889
890         int                              pool_size;
891         int                              pool_idx;
892         int                              num_size;
893         int                              null_size;
894
895         char                             char_map[0x80];
896 };
897
898 enum char_type {
899         A_CHAR,
900         D_CHAR
901 };
902
903
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 *);
913
914 static void     get_system_identitier(char *, size_t);
915 static void     set_str(unsigned char *, const char *, size_t, char,
916                     const 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);
926
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,
938                     enum vdd_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);
944 #ifdef HAVE_ZLIB_H
945 static int      wb_set_offset(struct archive_write *, int64_t);
946 #endif
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,
952                     enum char_type);
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,
957                     struct vdd *);
958 static int      write_directory_descriptors(struct archive_write *,
959                     struct vdd *);
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 *);
963
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 *,
973                     struct isofile *);
974 static int      isofile_register_hardlink(struct archive_write *,
975                     struct isofile *);
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 *);
979
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 *,
990                     const void *);
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 *,
995                     int, struct vdd *);
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 *,
1005                     int);
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,
1009                     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 *,
1023                     const void *);
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 *,
1029                     const void *);
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 *,
1034                     struct isoent *);
1035 static int      isoent_create_boot_catalog(struct archive_write *,
1036                     struct isoent *);
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 *);
1040
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 *);
1049
1050 int
1051 archive_write_set_format_iso9660(struct archive *_a)
1052 {
1053         struct archive_write *a = (struct archive_write *)_a;
1054         struct iso9660 *iso9660;
1055
1056         archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
1057             ARCHIVE_STATE_NEW, "archive_write_set_format_iso9660");
1058
1059         /* If another format was already registered, unregister it. */
1060         if (a->format_free != NULL)
1061                 (a->format_free)(a);
1062
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);
1068         }
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));
1091
1092         /*
1093          * Init Identifiers used for PVD and SVD.
1094          */
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));
1105
1106         /*
1107          * Init El Torito bootable CD variables.
1108          */
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),
1113             "boot.catalog");
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;
1120
1121         /*
1122          * Init zisofs variables.
1123          */
1124 #ifdef HAVE_ZLIB_H
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));
1131 #endif
1132
1133         /*
1134          * Set default value of iso9660 options.
1135          */
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;
1157
1158         /* Create the root directory. */
1159         iso9660->primary.rootent =
1160             isoent_create_virtual_dir(a, iso9660, "");
1161         if (iso9660->primary.rootent == NULL) {
1162                 free(iso9660);
1163                 archive_set_error(&a->archive, ENOMEM,
1164                     "Can't allocate memory");
1165                 return (ARCHIVE_FATAL);
1166         }
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;
1174
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";
1185
1186         return (ARCHIVE_OK);
1187 }
1188
1189 static int
1190 get_str_opt(struct archive_write *a, struct archive_string *s,
1191     size_t maxsize, const char *key, const char *value)
1192 {
1193
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);
1199         }
1200         archive_strcpy(s, value);
1201         return (ARCHIVE_OK);
1202 }
1203
1204 static int
1205 get_num_opt(struct archive_write *a, int *num, int high, int low,
1206     const char *key, const char *value)
1207 {
1208         const char *p = value;
1209         int data = 0;
1210         int neg = 0;
1211
1212         if (p == NULL) {
1213                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1214                     "Invalid value(empty) for option ``%s''", key);
1215                 return (ARCHIVE_FATAL);
1216         }
1217         if (*p == '-') {
1218                 neg = 1;
1219                 p++;
1220         }
1221         while (*p) {
1222                 if (*p >= '0' && *p <= '9')
1223                         data = data * 10 + *p - '0';
1224                 else {
1225                         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1226                             "Invalid value for option ``%s''", key);
1227                         return (ARCHIVE_FATAL);
1228                 }
1229                 if (data > high) {
1230                         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1231                             "Invalid value(over %d) for "
1232                             "option ``%s''", high, key);
1233                         return (ARCHIVE_FATAL);
1234                 }
1235                 if (data < low) {
1236                         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1237                             "Invalid value(under %d) for "
1238                             "option ``%s''", low, key);
1239                         return (ARCHIVE_FATAL);
1240                 }
1241                 p++;
1242         }
1243         if (neg)
1244                 data *= -1;
1245         *num = data;
1246
1247         return (ARCHIVE_OK);
1248 }
1249
1250 static int
1251 iso9660_options(struct archive_write *a, const char *key, const char *value)
1252 {
1253         struct iso9660 *iso9660 = a->format_data;
1254         const char *p;
1255         int r;
1256
1257         switch (key[0]) {
1258         case 'a':
1259                 if (strcmp(key, "abstract-file") == 0) {
1260                         r = get_str_opt(a,
1261                             &(iso9660->abstract_file_identifier),
1262                             ABSTRACT_FILE_SIZE, key, value);
1263                         iso9660->opt.abstract_file = r == ARCHIVE_OK;
1264                         return (r);
1265                 }
1266                 if (strcmp(key, "application-id") == 0) {
1267                         r = get_str_opt(a,
1268                             &(iso9660->application_identifier),
1269                             APPLICATION_IDENTIFIER_SIZE, key, value);
1270                         iso9660->opt.application_id = r == ARCHIVE_OK;
1271                         return (r);
1272                 }
1273                 if (strcmp(key, "allow-vernum") == 0) {
1274                         iso9660->opt.allow_vernum = value != NULL;
1275                         return (ARCHIVE_OK);
1276                 }
1277                 break;
1278         case 'b':
1279                 if (strcmp(key, "biblio-file") == 0) {
1280                         r = get_str_opt(a,
1281                             &(iso9660->bibliographic_file_identifier),
1282                             BIBLIO_FILE_SIZE, key, value);
1283                         iso9660->opt.biblio_file = r == ARCHIVE_OK;
1284                         return (r);
1285                 }
1286                 if (strcmp(key, "boot") == 0) {
1287                         if (value == NULL)
1288                                 iso9660->opt.boot = 0;
1289                         else {
1290                                 iso9660->opt.boot = 1;
1291                                 archive_strcpy(
1292                                     &(iso9660->el_torito.boot_filename),
1293                                     value);
1294                         }
1295                         return (ARCHIVE_OK);
1296                 }
1297                 if (strcmp(key, "boot-catalog") == 0) {
1298                         r = get_str_opt(a,
1299                             &(iso9660->el_torito.catalog_filename),
1300                             1024, key, value);
1301                         iso9660->opt.boot_catalog = r == ARCHIVE_OK;
1302                         return (r);
1303                 }
1304                 if (strcmp(key, "boot-info-table") == 0) {
1305                         iso9660->opt.boot_info_table = value != NULL;
1306                         return (ARCHIVE_OK);
1307                 }
1308                 if (strcmp(key, "boot-load-seg") == 0) {
1309                         uint32_t seg;
1310
1311                         iso9660->opt.boot_load_seg = 0;
1312                         if (value == NULL)
1313                                 goto invalid_value;
1314                         seg = 0;
1315                         p = value;
1316                         if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
1317                                 p += 2;
1318                         while (*p) {
1319                                 if (seg)
1320                                         seg <<= 4;
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')
1326                                         seg += *p - '0';
1327                                 else
1328                                         goto invalid_value;
1329                                 if (seg > 0xffff) {
1330                                         archive_set_error(&a->archive,
1331                                             ARCHIVE_ERRNO_MISC,
1332                                             "Invalid value(over 0xffff) for "
1333                                             "option ``%s''", key);
1334                                         return (ARCHIVE_FATAL);
1335                                 }
1336                                 p++;
1337                         }
1338                         iso9660->el_torito.boot_load_seg = (uint16_t)seg;
1339                         iso9660->opt.boot_load_seg = 1;
1340                         return (ARCHIVE_OK);
1341                 }
1342                 if (strcmp(key, "boot-load-size") == 0) {
1343                         int num = 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);
1350                 }
1351                 if (strcmp(key, "boot-type") == 0) {
1352                         if (value == NULL)
1353                                 goto invalid_value;
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;
1360                         else
1361                                 goto invalid_value;
1362                         return (ARCHIVE_OK);
1363                 }
1364                 break;
1365         case 'c':
1366                 if (strcmp(key, "compression-level") == 0) {
1367 #ifdef HAVE_ZLIB_H
1368                         if (value == NULL ||
1369                             !(value[0] >= '0' && value[0] <= '9') ||
1370                             value[1] != '\0')
1371                                 goto invalid_value;
1372                         iso9660->zisofs.compression_level = value[0] - '0';
1373                         iso9660->opt.compression_level = 1;
1374                         return (ARCHIVE_OK);
1375 #else
1376                         archive_set_error(&a->archive,
1377                             ARCHIVE_ERRNO_MISC,
1378                             "Option ``%s'' "
1379                             "is not supported on this platform.", key);
1380                         return (ARCHIVE_FATAL);
1381 #endif
1382                 }
1383                 if (strcmp(key, "copyright-file") == 0) {
1384                         r = get_str_opt(a,
1385                             &(iso9660->copyright_file_identifier),
1386                             COPYRIGHT_FILE_SIZE, key, value);
1387                         iso9660->opt.copyright_file = r == ARCHIVE_OK;
1388                         return (r);
1389                 }
1390 #ifdef DEBUG
1391                 /* Specifies Volume creation date and time;
1392                  * year(4),month(2),day(2),hour(2),minute(2),second(2).
1393                  * e.g. "20090929033757"
1394                  */
1395                 if (strcmp(key, "creation") == 0) {
1396                         struct tm tm;
1397                         char buf[5];
1398
1399                         p = value;
1400                         if (p == NULL || strlen(p) < 14)
1401                                 goto invalid_value;
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);
1417                 }
1418 #endif
1419                 break;
1420         case 'i':
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);
1426                         }
1427                         goto invalid_value;
1428                 }
1429                 break;
1430         case 'j':
1431                 if (strcmp(key, "joliet") == 0) {
1432                         if (value == NULL)
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;
1438                         else
1439                                 goto invalid_value;
1440                         return (ARCHIVE_OK);
1441                 }
1442                 break;
1443         case 'l':
1444                 if (strcmp(key, "limit-depth") == 0) {
1445                         iso9660->opt.limit_depth = value != NULL;
1446                         return (ARCHIVE_OK);
1447                 }
1448                 if (strcmp(key, "limit-dirs") == 0) {
1449                         iso9660->opt.limit_dirs = value != NULL;
1450                         return (ARCHIVE_OK);
1451                 }
1452                 break;
1453         case 'p':
1454                 if (strcmp(key, "pad") == 0) {
1455                         iso9660->opt.pad = value != NULL;
1456                         return (ARCHIVE_OK);
1457                 }
1458                 if (strcmp(key, "publisher") == 0) {
1459                         r = get_str_opt(a,
1460                             &(iso9660->publisher_identifier),
1461                             PUBLISHER_IDENTIFIER_SIZE, key, value);
1462                         iso9660->opt.publisher = r == ARCHIVE_OK;
1463                         return (r);
1464                 }
1465                 break;
1466         case 'r':
1467                 if (strcmp(key, "rockridge") == 0 ||
1468                     strcmp(key, "Rockridge") == 0) {
1469                         if (value == NULL)
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;
1477                         else
1478                                 goto invalid_value;
1479                         return (ARCHIVE_OK);
1480                 }
1481                 break;
1482         case 'v':
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;
1487                         return (r);
1488                 }
1489                 break;
1490         case 'z':
1491                 if (strcmp(key, "zisofs") == 0) {
1492                         if (value == NULL)
1493                                 iso9660->opt.zisofs = OPT_ZISOFS_DISABLED;
1494                         else {
1495 #ifdef HAVE_ZLIB_H
1496                                 iso9660->opt.zisofs = OPT_ZISOFS_DIRECT;
1497 #else
1498                                 archive_set_error(&a->archive,
1499                                     ARCHIVE_ERRNO_MISC,
1500                                     "``zisofs'' "
1501                                     "is not supported on this platform.");
1502                                 return (ARCHIVE_FATAL);
1503 #endif
1504                         }
1505                         return (ARCHIVE_OK);
1506                 }
1507                 break;
1508         }
1509
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);
1514
1515 invalid_value:
1516         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1517             "Invalid value for option ``%s''", key);
1518         return (ARCHIVE_FAILED);
1519 }
1520
1521 static int
1522 iso9660_write_header(struct archive_write *a, struct archive_entry *entry)
1523 {
1524         struct iso9660 *iso9660;
1525         struct isofile *file;
1526         struct isoent *isoent;
1527         int r, ret = ARCHIVE_OK;
1528
1529         iso9660 = a->format_data;
1530
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);
1540         }
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,
1545                             ARCHIVE_ERRNO_MISC,
1546                             "Ignore over %lld bytes file. "
1547                             "This file too large.",
1548                             MULTI_EXTENT_SIZE);
1549                                 iso9660->cur_file = NULL;
1550                         return (ARCHIVE_WARN);
1551                 }
1552                 iso9660->need_multi_extent = 1;
1553         }
1554
1555         file = isofile_new(a, entry);
1556         if (file == NULL) {
1557                 archive_set_error(&a->archive, ENOMEM,
1558                     "Can't allocate data");
1559                 return (ARCHIVE_FATAL);
1560         }
1561         r = isofile_gen_utility_names(a, file);
1562         if (r < ARCHIVE_WARN) {
1563                 isofile_free(file);
1564                 return (r);
1565         }
1566         else if (r < ret)
1567                 ret = r;
1568
1569         /*
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.
1572          */
1573         if (archive_strlen(&(file->parentdir)) == 0 &&
1574             archive_strlen(&(file->basename)) == 0) {
1575                 isofile_free(file);
1576                 return (r);
1577         }
1578
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);
1585         }
1586         if (isoent->file->dircnt > iso9660->dircnt_max)
1587                 iso9660->dircnt_max = isoent->file->dircnt;
1588
1589         /* Add the current file into tree */
1590         r = isoent_tree(a, &isoent);
1591         if (r != ARCHIVE_OK)
1592                 return (r);
1593
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);
1599
1600         /* Non regular files contents are unneeded to be saved to
1601          * temporary files. */
1602         if (archive_entry_filetype(file->entry) != AE_IFREG)
1603                 return (ret);
1604
1605         /*
1606          * Set the current file to cur_file to read its contents.
1607          */
1608         iso9660->cur_file = file;
1609
1610         if (archive_entry_nlink(file->entry) > 1) {
1611                 r = isofile_register_hardlink(a, file);
1612                 if (r != ARCHIVE_OK)
1613                         return (ARCHIVE_FATAL);
1614         }
1615
1616         /*
1617          * Prepare to save the contents of the file.
1618          */
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);
1625                 }
1626         }
1627
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);
1632         if (r < ret)
1633                 ret = r;
1634         iso9660->bytes_remaining =  archive_entry_size(file->entry);
1635
1636         return (ret);
1637 }
1638
1639 static int
1640 write_to_temp(struct archive_write *a, const void *buff, size_t s)
1641 {
1642         struct iso9660 *iso9660 = a->format_data;
1643         ssize_t written;
1644         const unsigned char *b;
1645
1646         b = (const unsigned char *)buff;
1647         while (s) {
1648                 written = write(iso9660->temp_fd, b, s);
1649                 if (written < 0) {
1650                         archive_set_error(&a->archive, errno,
1651                             "Can't write to temporary file");
1652                         return (ARCHIVE_FATAL);
1653                 }
1654                 s -= written;
1655                 b += written;
1656         }
1657         return (ARCHIVE_OK);
1658 }
1659
1660 static int
1661 wb_write_to_temp(struct archive_write *a, const void *buff, size_t s)
1662 {
1663         const char *xp = buff;
1664         size_t xs = s;
1665
1666         /*
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.
1670          */
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);
1677                 if (xs == 0)
1678                         return (ARCHIVE_OK);
1679                 xp += s - xs;
1680         }
1681
1682         while (xs) {
1683                 size_t size = xs;
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);
1689                 xs -= size;
1690                 xp += size;
1691         }
1692         return (ARCHIVE_OK);
1693 }
1694
1695 static int
1696 wb_write_padding_to_temp(struct archive_write *a, int64_t csize)
1697 {
1698         size_t ns;
1699         int ret;
1700
1701         ns = (size_t)(csize % LOGICAL_BLOCK_SIZE);
1702         if (ns != 0)
1703                 ret = write_null(a, LOGICAL_BLOCK_SIZE - ns);
1704         else
1705                 ret = ARCHIVE_OK;
1706         return (ret);
1707 }
1708
1709 static ssize_t
1710 write_iso9660_data(struct archive_write *a, const void *buff, size_t s)
1711 {
1712         struct iso9660 *iso9660 = a->format_data;
1713         size_t ws;
1714
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);
1719         }
1720
1721         ws = s;
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;
1726                 size_t ts;
1727
1728                 ts = (size_t)(MULTI_EXTENT_SIZE - LOGICAL_BLOCK_SIZE -
1729                     iso9660->cur_file->cur_content->size);
1730
1731                 if (iso9660->zisofs.detect_magic)
1732                         zisofs_detect_magic(a, buff, ts);
1733
1734                 if (iso9660->zisofs.making) {
1735                         if (zisofs_write_to_temp(a, buff, ts) != ARCHIVE_OK)
1736                                 return (ARCHIVE_FATAL);
1737                 } else {
1738                         if (wb_write_to_temp(a, buff, ts) != ARCHIVE_OK)
1739                                 return (ARCHIVE_FATAL);
1740                         iso9660->cur_file->cur_content->size += ts;
1741                 }
1742
1743                 /* Write padding. */
1744                 if (wb_write_padding_to_temp(a,
1745                     iso9660->cur_file->cur_content->size) != ARCHIVE_OK)
1746                         return (ARCHIVE_FATAL);
1747
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);
1752
1753                 /*
1754                  * Make next extent.
1755                  */
1756                 ws -= ts;
1757                 buff = (const void *)(((const unsigned char *)buff) + ts);
1758                 /* Make a content for next extent. */
1759                 con = calloc(1, sizeof(*con));
1760                 if (con == NULL) {
1761                         archive_set_error(&a->archive, ENOMEM,
1762                             "Can't allocate content data");
1763                         return (ARCHIVE_FATAL);
1764                 }
1765                 con->offset_of_temp = wb_offset(a);
1766                 iso9660->cur_file->cur_content->next = con;
1767                 iso9660->cur_file->cur_content = con;
1768 #ifdef HAVE_ZLIB_H
1769                 iso9660->zisofs.block_offset = 0;
1770 #endif
1771         }
1772
1773         if (iso9660->zisofs.detect_magic)
1774                 zisofs_detect_magic(a, buff, ws);
1775
1776         if (iso9660->zisofs.making) {
1777                 if (zisofs_write_to_temp(a, buff, ws) != ARCHIVE_OK)
1778                         return (ARCHIVE_FATAL);
1779         } else {
1780                 if (wb_write_to_temp(a, buff, ws) != ARCHIVE_OK)
1781                         return (ARCHIVE_FATAL);
1782                 iso9660->cur_file->cur_content->size += ws;
1783         }
1784
1785         return (s);
1786 }
1787
1788 static ssize_t
1789 iso9660_write_data(struct archive_write *a, const void *buff, size_t s)
1790 {
1791         struct iso9660 *iso9660 = a->format_data;
1792         ssize_t r;
1793
1794         if (iso9660->cur_file == NULL)
1795                 return (0);
1796         if (archive_entry_filetype(iso9660->cur_file->entry) != AE_IFREG)
1797                 return (0);
1798         if (s > iso9660->bytes_remaining)
1799                 s = (size_t)iso9660->bytes_remaining;
1800         if (s == 0)
1801                 return (0);
1802
1803         r = write_iso9660_data(a, buff, s);
1804         if (r > 0)
1805                 iso9660->bytes_remaining -= r;
1806         return (r);
1807 }
1808
1809 static int
1810 iso9660_finish_entry(struct archive_write *a)
1811 {
1812         struct iso9660 *iso9660 = a->format_data;
1813
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);
1820
1821         /* If there are unwritten data, write null data instead. */
1822         while (iso9660->bytes_remaining > 0) {
1823                 size_t s;
1824
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;
1830         }
1831
1832         if (iso9660->zisofs.making && zisofs_finish_entry(a) != ARCHIVE_OK)
1833                 return (ARCHIVE_FATAL);
1834
1835         /* Write padding. */
1836         if (wb_write_padding_to_temp(a, iso9660->cur_file->cur_content->size)
1837             != ARCHIVE_OK)
1838                 return (ARCHIVE_FATAL);
1839
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);
1844
1845         /* Add the current file to data file list. */
1846         isofile_add_data_file(iso9660, iso9660->cur_file);
1847
1848         return (ARCHIVE_OK);
1849 }
1850
1851 static int
1852 iso9660_close(struct archive_write *a)
1853 {
1854         struct iso9660 *iso9660;
1855         int ret, blocks;
1856
1857         iso9660 = a->format_data;
1858
1859         /*
1860          * Write remaining data out to the temporary file.
1861          */
1862         if (wb_remaining(a) > 0) {
1863                 ret = wb_write_out(a);
1864                 if (ret < 0)
1865                         return (ret);
1866         }
1867
1868         /*
1869          * Preparations...
1870          */
1871 #ifdef DEBUG
1872         if (iso9660->birth_time == 0)
1873 #endif
1874                 time(&(iso9660->birth_time));
1875
1876         /*
1877          * Prepare a bootable ISO image.
1878          */
1879         if (iso9660->opt.boot) {
1880                 /* Find out the boot file entry. */
1881                 ret = isoent_find_out_boot_file(a, iso9660->primary.rootent);
1882                 if (ret < 0)
1883                         return (ret);
1884                 /* Reconvert the boot file from zisofs'ed form to
1885                  * plain form. */
1886                 ret = zisofs_rewind_boot_file(a);
1887                 if (ret < 0)
1888                         return (ret);
1889                 /* Write remaining data out to the temporary file. */
1890                 if (wb_remaining(a) > 0) {
1891                         ret = wb_write_out(a);
1892                         if (ret < 0)
1893                                 return (ret);
1894                 }
1895                 /* Create the boot catalog. */
1896                 ret = isoent_create_boot_catalog(a, iso9660->primary.rootent);
1897                 if (ret < 0)
1898                         return (ret);
1899         }
1900
1901         /*
1902          * Prepare joliet extensions.
1903          */
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);
1908                 if (ret < 0)
1909                         return (ret);
1910                 /* Make sure we have UTF-16BE converters.
1911                  * if there is no file entry, converters are still
1912                  * uninitialized. */
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);
1926                 }
1927         }
1928
1929         /*
1930          * Make Path Tables.
1931          */
1932         ret = isoent_make_path_table(a);
1933         if (ret < 0)
1934                 return (ret);
1935
1936         /*
1937          * Calculate a total volume size and setup all locations of
1938          * contents of an iso9660 image.
1939          */
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;
1950
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;
1961         }
1962
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;
1971         }
1972
1973         if (iso9660->opt.rr) {
1974                 iso9660->location_rrip_er = blocks;
1975                 blocks += RRIP_ER_BLOCK;
1976         }
1977
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);
1983                 if (ret < 0)
1984                         return (ret);
1985         }
1986
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;
1992
1993
1994         /*
1995          * Write an ISO 9660 image.
1996          */
1997
1998         /* Switch to start using wbuff as file buffer. */
1999         iso9660->wbuff_remaining = wb_buffmax();
2000         iso9660->wbuff_type = WB_TO_STREAM;
2001         iso9660->wbuff_offset = 0;
2002         iso9660->wbuff_written = 0;
2003         iso9660->wbuff_tail = 0;
2004
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);
2009
2010         /* Write Primary Volume Descriptor */
2011         ret = write_VD(a, &(iso9660->primary));
2012         if (ret != ARCHIVE_OK)
2013                 return (ARCHIVE_FATAL);
2014
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);
2020         }
2021
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);
2029         }
2030
2031         if (iso9660->opt.joliet) {
2032                 ret = write_VD(a, &(iso9660->joliet));
2033                 if (ret != ARCHIVE_OK)
2034                         return (ARCHIVE_FATAL);
2035         }
2036
2037         /* Write Volume Descriptor Set Terminator */
2038         ret = write_VD_terminator(a);
2039         if (ret != ARCHIVE_OK)
2040                 return (ARCHIVE_FATAL);
2041
2042         /* Write Non-ISO File System Information */
2043         ret = write_information_block(a);
2044         if (ret != ARCHIVE_OK)
2045                 return (ARCHIVE_FATAL);
2046
2047         /* Write Type L Path Table */
2048         ret = write_path_table(a, 0, &(iso9660->primary));
2049         if (ret != ARCHIVE_OK)
2050                 return (ARCHIVE_FATAL);
2051
2052         /* Write Type M Path Table */
2053         ret = write_path_table(a, 1, &(iso9660->primary));
2054         if (ret != ARCHIVE_OK)
2055                 return (ARCHIVE_FATAL);
2056
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);
2062
2063                 /* Write Type M Path Table */
2064                 ret = write_path_table(a, 1, &(iso9660->joliet));
2065                 if (ret != ARCHIVE_OK)
2066                         return (ARCHIVE_FATAL);
2067         }
2068
2069         /* Write Directory Descriptors */
2070         ret = write_directory_descriptors(a, &(iso9660->primary));
2071         if (ret != ARCHIVE_OK)
2072                 return (ARCHIVE_FATAL);
2073
2074         if (iso9660->opt.joliet) {
2075                 ret = write_directory_descriptors(a, &(iso9660->joliet));
2076                 if (ret != ARCHIVE_OK)
2077                         return (ARCHIVE_FATAL);
2078         }
2079
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);
2085         }
2086
2087         /* Write File Descriptors */
2088         ret = write_file_descriptors(a);
2089         if (ret != ARCHIVE_OK)
2090                 return (ARCHIVE_FATAL);
2091
2092         /* Write Padding  */
2093         if (iso9660->opt.pad) {
2094                 ret = write_null(a, PADDING_BLOCK * LOGICAL_BLOCK_SIZE);
2095                 if (ret != ARCHIVE_OK)
2096                         return (ARCHIVE_FATAL);
2097         }
2098
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);
2105         }
2106
2107         /* Write remaining data out. */
2108         ret = wb_write_out(a);
2109
2110         return (ret);
2111 }
2112
2113 static int
2114 iso9660_free(struct archive_write *a)
2115 {
2116         struct iso9660 *iso9660;
2117         int i, ret;
2118
2119         iso9660 = a->format_data;
2120
2121         /* Close the temporary file. */
2122         if (iso9660->temp_fd >= 0)
2123                 close(iso9660->temp_fd);
2124
2125         /* Free some stuff for zisofs operations. */
2126         ret = zisofs_free(a);
2127
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);
2133
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);
2139         }
2140
2141         /* Remove isofile entries. */
2142         isofile_free_all_entries(iso9660);
2143         isofile_free_hardlinks(iso9660);
2144
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));
2158
2159         free(iso9660);
2160         a->format_data = NULL;
2161
2162         return (ret);
2163 }
2164
2165 /*
2166  * Get the System Identifier
2167  */
2168 static void
2169 get_system_identitier(char *system_id, size_t size)
2170 {
2171 #if defined(HAVE_SYS_UTSNAME_H)
2172         struct utsname u;
2173
2174         uname(&u);
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';
2180 #else
2181         strncpy(system_id, "Unknown", size-1);
2182         system_id[size-1] = '\0';
2183 #endif
2184 }
2185
2186 static void
2187 set_str(unsigned char *p, const char *s, size_t l, char f, const char *map)
2188 {
2189         unsigned char c;
2190
2191         if (s == NULL)
2192                 s = "";
2193         while ((c = *s++) != 0 && l > 0) {
2194                 if (c >= 0x80 || map[c] == 0)
2195                  {
2196                         /* illegal character */
2197                         if (c >= 'a' && c <= 'z') {
2198                                 /* convert c from a-z to A-Z */
2199                                 c -= 0x20;
2200                         } else
2201                                 c = 0x5f;
2202                 }
2203                 *p++ = c;
2204                 l--;
2205         }
2206         /* If l isn't zero, fill p buffer by the character
2207          * which indicated by f. */
2208         if (l > 0)
2209                 memset(p , f, l);
2210 }
2211
2212 static inline int
2213 joliet_allowed_char(unsigned char high, unsigned char low)
2214 {
2215         int utf16 = (high << 8) | low;
2216
2217         if (utf16 <= 0x001F)
2218                 return (0);
2219
2220         switch (utf16) {
2221         case 0x002A: /* '*' */
2222         case 0x002F: /* '/' */
2223         case 0x003A: /* ':' */
2224         case 0x003B: /* ';' */
2225         case 0x003F: /* '?' */
2226         case 0x005C: /* '\' */
2227                 return (0);/* Not allowed. */
2228         }
2229         return (1);
2230 }
2231
2232 static int
2233 set_str_utf16be(struct archive_write *a, unsigned char *p, const char *s,
2234     size_t l, uint16_t uf, enum vdc vdc)
2235 {
2236         size_t size, i;
2237         int onepad;
2238
2239         if (s == NULL)
2240                 s = "";
2241         if (l & 0x01) {
2242                 onepad = 1;
2243                 l &= ~1;
2244         } else
2245                 onepad = 0;
2246         if (vdc == VDC_UCS2) {
2247                 struct iso9660 *iso9660 = a->format_data;
2248                 if (archive_strncpy_l(&iso9660->utf16be, s, strlen(s),
2249                     iso9660->sconv_to_utf16be) != 0 && errno == ENOMEM) {
2250                         archive_set_error(&a->archive, ENOMEM,
2251                             "Can't allocate memory for UTF-16BE");
2252                         return (ARCHIVE_FATAL);
2253                 }
2254                 size = iso9660->utf16be.length;
2255                 if (size > l)
2256                         size = l;
2257                 memcpy(p, iso9660->utf16be.s, size);
2258         } else {
2259                 const uint16_t *u16 = (const uint16_t *)s;
2260
2261                 size = 0;
2262                 while (*u16++)
2263                         size += 2;
2264                 if (size > l)
2265                         size = l;
2266                 memcpy(p, s, size);
2267         }
2268         for (i = 0; i < size; i += 2, p += 2) {
2269                 if (!joliet_allowed_char(p[0], p[1]))
2270                         archive_be16enc(p, 0x005F);/* '_' */
2271         }
2272         l -= size;
2273         while (l > 0) {
2274                 archive_be16enc(p, uf);
2275                 p += 2;
2276                 l -= 2;
2277         }
2278         if (onepad)
2279                 *p = 0;
2280         return (ARCHIVE_OK);
2281 }
2282
2283 static const char a_characters_map[0x80] = {
2284 /*  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F          */
2285     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
2286     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
2287     1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20-2F */
2288     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30-3F */
2289     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
2290     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
2291     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 60-6F */
2292     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 70-7F */
2293 };
2294
2295 static const char a1_characters_map[0x80] = {
2296 /*  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F          */
2297     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
2298     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
2299     1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20-2F */
2300     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30-3F */
2301     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
2302     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
2303     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60-6F */
2304     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,/* 70-7F */
2305 };
2306
2307 static const char d_characters_map[0x80] = {
2308 /*  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F          */
2309     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
2310     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
2311     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 20-2F */
2312     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,/* 30-3F */
2313     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
2314     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
2315     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 60-6F */
2316     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 70-7F */
2317 };
2318
2319 static const char d1_characters_map[0x80] = {
2320 /*  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F          */
2321     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */
2322     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */
2323     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 20-2F */
2324     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,/* 30-3F */
2325     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */
2326     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */
2327     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60-6F */
2328     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,/* 70-7F */
2329 };
2330
2331 static int
2332 set_str_a_characters_bp(struct archive_write *a, unsigned char *bp,
2333     int from, int to, const char *s, enum vdc vdc)
2334 {
2335         int r;
2336
2337         switch (vdc) {
2338         case VDC_STD:
2339                 set_str(bp+from, s, to - from + 1, 0x20,
2340                     a_characters_map);
2341                 r = ARCHIVE_OK;
2342                 break;
2343         case VDC_LOWERCASE:
2344                 set_str(bp+from, s, to - from + 1, 0x20,
2345                     a1_characters_map);
2346                 r = ARCHIVE_OK;
2347                 break;
2348         case VDC_UCS2:
2349         case VDC_UCS2_DIRECT:
2350                 r = set_str_utf16be(a, bp+from, s, to - from + 1,
2351                     0x0020, vdc);
2352                 break;
2353         default:
2354                 r = ARCHIVE_FATAL;
2355         }
2356         return (r);
2357 }
2358
2359 static int
2360 set_str_d_characters_bp(struct archive_write *a, unsigned char *bp,
2361     int from, int to, const char *s, enum  vdc vdc)
2362 {
2363         int r;
2364
2365         switch (vdc) {
2366         case VDC_STD:
2367                 set_str(bp+from, s, to - from + 1, 0x20,
2368                     d_characters_map);
2369                 r = ARCHIVE_OK;
2370                 break;
2371         case VDC_LOWERCASE:
2372                 set_str(bp+from, s, to - from + 1, 0x20,
2373                     d1_characters_map);
2374                 r = ARCHIVE_OK;
2375                 break;
2376         case VDC_UCS2:
2377         case VDC_UCS2_DIRECT:
2378                 r = set_str_utf16be(a, bp+from, s, to - from + 1,
2379                     0x0020, vdc);
2380                 break;
2381         default:
2382                 r = ARCHIVE_FATAL;
2383         }
2384         return (r);
2385 }
2386
2387 static void
2388 set_VD_bp(unsigned char *bp, enum VD_type type, unsigned char ver)
2389 {
2390
2391         /* Volume Descriptor Type */
2392         bp[1] = (unsigned char)type;
2393         /* Standard Identifier */
2394         memcpy(bp + 2, "CD001", 5);
2395         /* Volume Descriptor Version */
2396         bp[7] = ver;
2397 }
2398
2399 static inline void
2400 set_unused_field_bp(unsigned char *bp, int from, int to)
2401 {
2402         memset(bp + from, 0, to - from + 1);
2403 }
2404
2405 /*
2406  * 8-bit unsigned numerical values.
2407  * ISO9660 Standard 7.1.1
2408  */
2409 static inline void
2410 set_num_711(unsigned char *p, unsigned char value)
2411 {
2412         *p = value;
2413 }
2414
2415 /*
2416  * 8-bit signed numerical values.
2417  * ISO9660 Standard 7.1.2
2418  */
2419 static inline void
2420 set_num_712(unsigned char *p, char value)
2421 {
2422         *((char *)p) = value;
2423 }
2424
2425 /*
2426  * Least significant byte first.
2427  * ISO9660 Standard 7.2.1
2428  */
2429 static inline void
2430 set_num_721(unsigned char *p, uint16_t value)
2431 {
2432         archive_le16enc(p, value);
2433 }
2434
2435 /*
2436  * Most significant byte first.
2437  * ISO9660 Standard 7.2.2
2438  */
2439 static inline void
2440 set_num_722(unsigned char *p, uint16_t value)
2441 {
2442         archive_be16enc(p, value);
2443 }
2444
2445 /*
2446  * Both-byte orders.
2447  * ISO9660 Standard 7.2.3
2448  */
2449 static void
2450 set_num_723(unsigned char *p, uint16_t value)
2451 {
2452         archive_le16enc(p, value);
2453         archive_be16enc(p+2, value);
2454 }
2455
2456 /*
2457  * Least significant byte first.
2458  * ISO9660 Standard 7.3.1
2459  */
2460 static inline void
2461 set_num_731(unsigned char *p, uint32_t value)
2462 {
2463         archive_le32enc(p, value);
2464 }
2465
2466 /*
2467  * Most significant byte first.
2468  * ISO9660 Standard 7.3.2
2469  */
2470 static inline void
2471 set_num_732(unsigned char *p, uint32_t value)
2472 {
2473         archive_be32enc(p, value);
2474 }
2475
2476 /*
2477  * Both-byte orders.
2478  * ISO9660 Standard 7.3.3
2479  */
2480 static inline void
2481 set_num_733(unsigned char *p, uint32_t value)
2482 {
2483         archive_le32enc(p, value);
2484         archive_be32enc(p+4, value);
2485 }
2486
2487 static void
2488 set_digit(unsigned char *p, size_t s, int value)
2489 {
2490
2491         while (s--) {
2492                 p[s] = '0' + (value % 10);
2493                 value /= 10;
2494         }
2495 }
2496
2497 #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
2498 #define get_gmoffset(tm)        ((tm)->tm_gmtoff)
2499 #elif defined(HAVE_STRUCT_TM___TM_GMTOFF)
2500 #define get_gmoffset(tm)        ((tm)->__tm_gmtoff)
2501 #else
2502 static long
2503 get_gmoffset(struct tm *tm)
2504 {
2505         long offset;
2506
2507 #if defined(HAVE__GET_TIMEZONE)
2508         _get_timezone(&offset);
2509 #elif defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
2510         offset = _timezone;
2511 #else
2512         offset = timezone;
2513 #endif
2514         offset *= -1;
2515         if (tm->tm_isdst)
2516                 offset += 3600;
2517         return (offset);
2518 }
2519 #endif
2520
2521 static void
2522 get_tmfromtime(struct tm *tm, time_t *t)
2523 {
2524 #if HAVE_LOCALTIME_R
2525         tzset();
2526         localtime_r(t, tm);
2527 #elif HAVE__LOCALTIME64_S
2528         __time64_t tmp_t = (__time64_t) *t; //time_t may be shorter than 64 bits
2529         _localtime64_s(tm, &tmp_t);
2530 #else
2531         memcpy(tm, localtime(t), sizeof(*tm));
2532 #endif
2533 }
2534
2535 /*
2536  * Date and Time Format.
2537  * ISO9660 Standard 8.4.26.1
2538  */
2539 static void
2540 set_date_time(unsigned char *p, time_t t)
2541 {
2542         struct tm tm;
2543
2544         get_tmfromtime(&tm, &t);
2545         set_digit(p, 4, tm.tm_year + 1900);
2546         set_digit(p+4, 2, tm.tm_mon + 1);
2547         set_digit(p+6, 2, tm.tm_mday);
2548         set_digit(p+8, 2, tm.tm_hour);
2549         set_digit(p+10, 2, tm.tm_min);
2550         set_digit(p+12, 2, tm.tm_sec);
2551         set_digit(p+14, 2, 0);
2552         set_num_712(p+16, (char)(get_gmoffset(&tm)/(60*15)));
2553 }
2554
2555 static void
2556 set_date_time_null(unsigned char *p)
2557 {
2558         memset(p, (int)'0', 16);
2559         p[16] = 0;
2560 }
2561
2562 static void
2563 set_time_915(unsigned char *p, time_t t)
2564 {
2565         struct tm tm;
2566
2567         get_tmfromtime(&tm, &t);
2568         set_num_711(p+0, tm.tm_year);
2569         set_num_711(p+1, tm.tm_mon+1);
2570         set_num_711(p+2, tm.tm_mday);
2571         set_num_711(p+3, tm.tm_hour);
2572         set_num_711(p+4, tm.tm_min);
2573         set_num_711(p+5, tm.tm_sec);
2574         set_num_712(p+6, (char)(get_gmoffset(&tm)/(60*15)));
2575 }
2576
2577
2578 /*
2579  * Write SUSP "CE" System Use Entry.
2580  */
2581 static int
2582 set_SUSP_CE(unsigned char *p, int location, int offset, int size)
2583 {
2584         unsigned char *bp = p -1;
2585         /*  Extend the System Use Area
2586          *   "CE" Format:
2587          *               len  ver
2588          *    +----+----+----+----+-----------+-----------+
2589          *    | 'C'| 'E'| 1C | 01 | LOCATION1 | LOCATION2 |
2590          *    +----+----+----+----+-----------+-----------+
2591          *    0    1    2    3    4          12          20
2592          *    +-----------+
2593          *    | LOCATION3 |
2594          *    +-----------+
2595          *   20          28
2596          *   LOCATION1 : Location of Continuation of System Use Area.
2597          *   LOCATION2 : Offset to Start of Continuation.
2598          *   LOCATION3 : Length of the Continuation.
2599          */
2600
2601         bp[1] = 'C';
2602         bp[2] = 'E';
2603         bp[3] = RR_CE_SIZE;     /* length       */
2604         bp[4] = 1;              /* version      */
2605         set_num_733(bp+5, location);
2606         set_num_733(bp+13, offset);
2607         set_num_733(bp+21, size);
2608         return (RR_CE_SIZE);
2609 }
2610
2611 /*
2612  * The functions, which names are beginning with extra_, are used to
2613  * control extra records.
2614  * The maximum size of a Directory Record is 254. When a filename is
2615  * very long, all of RRIP data of a file won't stored to the Directory
2616  * Record and so remaining RRIP data store to an extra record instead.
2617  */
2618 static unsigned char *
2619 extra_open_record(unsigned char *bp, int dr_len, struct isoent *isoent,
2620     struct ctl_extr_rec *ctl)
2621 {
2622         ctl->bp = bp;
2623         if (bp != NULL)
2624                 bp += dr_len;
2625         ctl->use_extr = 0;
2626         ctl->isoent = isoent;
2627         ctl->ce_ptr = NULL;
2628         ctl->cur_len = ctl->dr_len = dr_len;
2629         ctl->limit = DR_LIMIT;
2630
2631         return (bp);
2632 }
2633
2634 static void
2635 extra_close_record(struct ctl_extr_rec *ctl, int ce_size)
2636 {
2637         int padding = 0;
2638
2639         if (ce_size > 0)
2640                 extra_tell_used_size(ctl, ce_size);
2641         /* Padding. */
2642         if (ctl->cur_len & 0x01) {
2643                 ctl->cur_len++;
2644                 if (ctl->bp != NULL)
2645                         ctl->bp[ctl->cur_len] = 0;
2646                 padding = 1;
2647         }
2648         if (ctl->use_extr) {
2649                 if (ctl->ce_ptr != NULL)
2650                         set_SUSP_CE(ctl->ce_ptr, ctl->extr_loc,
2651                             ctl->extr_off, ctl->cur_len - padding);
2652         } else
2653                 ctl->dr_len = ctl->cur_len;
2654 }
2655
2656 #define extra_space(ctl)        ((ctl)->limit - (ctl)->cur_len)
2657
2658 static unsigned char *
2659 extra_next_record(struct ctl_extr_rec *ctl, int length)
2660 {
2661         int cur_len = ctl->cur_len;/* save cur_len */
2662
2663         /* Close the current extra record or Directory Record. */
2664         extra_close_record(ctl, RR_CE_SIZE);
2665
2666         /* Get a next extra record. */
2667         ctl->use_extr = 1;
2668         if (ctl->bp != NULL) {
2669                 /* Storing data into an extra record. */
2670                 unsigned char *p;
2671
2672                 /* Save the pointer where a CE extension will be
2673                  * stored to. */
2674                 ctl->ce_ptr = &ctl->bp[cur_len+1];
2675                 p = extra_get_record(ctl->isoent,
2676                     &ctl->limit, &ctl->extr_off, &ctl->extr_loc);
2677                 ctl->bp = p - 1;/* the base of bp offset is 1. */
2678         } else
2679                 /* Calculating the size of an extra record. */
2680                 (void)extra_get_record(ctl->isoent,
2681                     &ctl->limit, NULL, NULL);
2682         ctl->cur_len = 0;
2683         /* Check if an extra record is almost full.
2684          * If so, get a next one. */
2685         if (extra_space(ctl) < length)
2686                 (void)extra_next_record(ctl, length);
2687
2688         return (ctl->bp);
2689 }
2690
2691 static inline struct extr_rec *
2692 extra_last_record(struct isoent *isoent)
2693 {
2694         if (isoent->extr_rec_list.first == NULL)
2695                 return (NULL);
2696         return ((struct extr_rec *)(void *)
2697                 ((char *)(isoent->extr_rec_list.last)
2698                     - offsetof(struct extr_rec, next)));
2699 }
2700
2701 static unsigned char *
2702 extra_get_record(struct isoent *isoent, int *space, int *off, int *loc)
2703 {
2704         struct extr_rec *rec;
2705
2706         isoent = isoent->parent;
2707         if (off != NULL) {
2708                 /* Storing data into an extra record. */
2709                 rec = isoent->extr_rec_list.current;
2710                 if (DR_SAFETY > LOGICAL_BLOCK_SIZE - rec->offset)
2711                         rec = rec->next;
2712         } else {
2713                 /* Calculating the size of an extra record. */
2714                 rec = extra_last_record(isoent);
2715                 if (rec == NULL ||
2716                     DR_SAFETY > LOGICAL_BLOCK_SIZE - rec->offset) {
2717                         rec = malloc(sizeof(*rec));
2718                         if (rec == NULL)
2719                                 return (NULL);
2720                         rec->location = 0;
2721                         rec->offset = 0;
2722                         /* Insert `rec` into the tail of isoent->extr_rec_list */
2723                         rec->next = NULL;
2724                         /*
2725                          * Note: testing isoent->extr_rec_list.last == NULL
2726                          * here is really unneeded since it has been already
2727                          * initialized at isoent_new function but Clang Static
2728                          * Analyzer claims that it is dereference of null
2729                          * pointer.
2730                          */
2731                         if (isoent->extr_rec_list.last == NULL)
2732                                 isoent->extr_rec_list.last =
2733                                         &(isoent->extr_rec_list.first);
2734                         *isoent->extr_rec_list.last = rec;
2735                         isoent->extr_rec_list.last = &(rec->next);
2736                 }
2737         }
2738         *space = LOGICAL_BLOCK_SIZE - rec->offset - DR_SAFETY;
2739         if (*space & 0x01)
2740                 *space -= 1;/* Keep padding space. */
2741         if (off != NULL)
2742                 *off = rec->offset;
2743         if (loc != NULL)
2744                 *loc = rec->location;
2745         isoent->extr_rec_list.current = rec;
2746
2747         return (&rec->buf[rec->offset]);
2748 }
2749
2750 static void
2751 extra_tell_used_size(struct ctl_extr_rec *ctl, int size)
2752 {
2753         struct isoent *isoent;
2754         struct extr_rec *rec;
2755
2756         if (ctl->use_extr) {
2757                 isoent = ctl->isoent->parent;
2758                 rec = isoent->extr_rec_list.current;
2759                 if (rec != NULL)
2760                         rec->offset += size;
2761         }
2762         ctl->cur_len += size;
2763 }
2764
2765 static int
2766 extra_setup_location(struct isoent *isoent, int location)
2767 {
2768         struct extr_rec *rec;
2769         int cnt;
2770
2771         cnt = 0;
2772         rec = isoent->extr_rec_list.first;
2773         isoent->extr_rec_list.current = rec;
2774         while (rec) {
2775                 cnt++;
2776                 rec->location = location++;
2777                 rec->offset = 0;
2778                 rec = rec->next;
2779         }
2780         return (cnt);
2781 }
2782
2783 /*
2784  * Create the RRIP entries.
2785  */
2786 static int
2787 set_directory_record_rr(unsigned char *bp, int dr_len,
2788     struct isoent *isoent, struct iso9660 *iso9660, enum dir_rec_type t)
2789 {
2790         /* Flags(BP 5) of the Rockridge "RR" System Use Field */
2791         unsigned char rr_flag;
2792 #define RR_USE_PX       0x01
2793 #define RR_USE_PN       0x02
2794 #define RR_USE_SL       0x04
2795 #define RR_USE_NM       0x08
2796 #define RR_USE_CL       0x10
2797 #define RR_USE_PL       0x20
2798 #define RR_USE_RE       0x40
2799 #define RR_USE_TF       0x80
2800         int length;
2801         struct ctl_extr_rec ctl;
2802         struct isoent *rr_parent, *pxent;
2803         struct isofile *file;
2804
2805         bp = extra_open_record(bp, dr_len, isoent, &ctl);
2806
2807         if (t == DIR_REC_PARENT) {
2808                 rr_parent = isoent->rr_parent;
2809                 pxent = isoent->parent;
2810                 if (rr_parent != NULL)
2811                         isoent = rr_parent;
2812                 else
2813                         isoent = isoent->parent;
2814         } else {
2815                 rr_parent = NULL;
2816                 pxent = isoent;
2817         }
2818         file = isoent->file;
2819
2820         if (t != DIR_REC_NORMAL) {
2821                 rr_flag = RR_USE_PX | RR_USE_TF;
2822                 if (rr_parent != NULL)
2823                         rr_flag |= RR_USE_PL;
2824         } else {
2825                 rr_flag = RR_USE_PX | RR_USE_NM | RR_USE_TF;
2826                 if (archive_entry_filetype(file->entry) == AE_IFLNK)
2827                         rr_flag |= RR_USE_SL;
2828                 if (isoent->rr_parent != NULL)
2829                         rr_flag |= RR_USE_RE;
2830                 if (isoent->rr_child != NULL)
2831                         rr_flag |= RR_USE_CL;
2832                 if (archive_entry_filetype(file->entry) == AE_IFCHR ||
2833                     archive_entry_filetype(file->entry) == AE_IFBLK)
2834                         rr_flag |= RR_USE_PN;
2835 #ifdef COMPAT_MKISOFS
2836                 /*
2837                  * mkisofs 2.01.01a63 records "RE" extension to
2838                  * the entry of "rr_moved" directory.
2839                  * I don't understand this behavior.
2840                  */
2841                 if (isoent->virtual &&
2842                     isoent->parent == iso9660->primary.rootent &&
2843                     strcmp(isoent->file->basename.s, "rr_moved") == 0)
2844                         rr_flag |= RR_USE_RE;
2845 #endif
2846         }
2847
2848         /* Write "SP" System Use Entry. */
2849         if (t == DIR_REC_SELF && isoent == isoent->parent) {
2850                 length = 7;
2851                 if (bp != NULL) {
2852                         bp[1] = 'S';
2853                         bp[2] = 'P';
2854                         bp[3] = length;
2855                         bp[4] = 1;      /* version      */
2856                         bp[5] = 0xBE;  /* Check Byte    */
2857                         bp[6] = 0xEF;  /* Check Byte    */
2858                         bp[7] = 0;
2859                         bp += length;
2860                 }
2861                 extra_tell_used_size(&ctl, length);
2862         }
2863
2864         /* Write "RR" System Use Entry. */
2865         length = 5;
2866         if (extra_space(&ctl) < length)
2867                 bp = extra_next_record(&ctl, length);
2868         if (bp != NULL) {
2869                 bp[1] = 'R';
2870                 bp[2] = 'R';
2871                 bp[3] = length;
2872                 bp[4] = 1;      /* version */
2873                 bp[5] = rr_flag;
2874                 bp += length;
2875         }
2876         extra_tell_used_size(&ctl, length);
2877
2878         /* Write "NM" System Use Entry. */
2879         if (rr_flag & RR_USE_NM) {
2880                 /*
2881                  *   "NM" Format:
2882                  *     e.g. a basename is 'foo'
2883                  *               len  ver  flg
2884                  *    +----+----+----+----+----+----+----+----+
2885                  *    | 'N'| 'M'| 08 | 01 | 00 | 'f'| 'o'| 'o'|
2886                  *    +----+----+----+----+----+----+----+----+
2887                  *    <----------------- len ----------------->
2888                  */
2889                 size_t nmlen = file->basename.length;
2890                 const char *nm = file->basename.s;
2891                 size_t nmmax;
2892
2893                 if (extra_space(&ctl) < 6)
2894                         bp = extra_next_record(&ctl, 6);
2895                 if (bp != NULL) {
2896                         bp[1] = 'N';
2897                         bp[2] = 'M';
2898                         bp[4] = 1;          /* version  */
2899                 }
2900                 nmmax = extra_space(&ctl);
2901                 if (nmmax > 0xff)
2902                         nmmax = 0xff;
2903                 while (nmlen + 5 > nmmax) {
2904                         length = (int)nmmax;
2905                         if (bp != NULL) {
2906                                 bp[3] = length;
2907                                 bp[5] = 0x01;/* Alternate Name continues
2908                                                * in next "NM" field */
2909                                 memcpy(bp+6, nm, length - 5);
2910                                 bp += length;
2911                         }
2912                         nmlen -= length - 5;
2913                         nm += length - 5;
2914                         extra_tell_used_size(&ctl, length);
2915                         if (extra_space(&ctl) < 6) {
2916                                 bp = extra_next_record(&ctl, 6);
2917                                 nmmax = extra_space(&ctl);
2918                                 if (nmmax > 0xff)
2919                                         nmmax = 0xff;
2920                         }
2921                         if (bp != NULL) {
2922                                 bp[1] = 'N';
2923                                 bp[2] = 'M';
2924                                 bp[4] = 1;    /* version */
2925                         }
2926                 }
2927                 length = 5 + (int)nmlen;
2928                 if (bp != NULL) {
2929                         bp[3] = length;
2930                         bp[5] = 0;
2931                         memcpy(bp+6, nm, nmlen);
2932                         bp += length;
2933                 }
2934                 extra_tell_used_size(&ctl, length);
2935         }
2936
2937         /* Write "PX" System Use Entry. */
2938         if (rr_flag & RR_USE_PX) {
2939                 /*
2940                  *   "PX" Format:
2941                  *               len  ver
2942                  *    +----+----+----+----+-----------+-----------+
2943                  *    | 'P'| 'X'| 2C | 01 | FILE MODE |   LINKS   |
2944                  *    +----+----+----+----+-----------+-----------+
2945                  *    0    1    2    3    4          12          20
2946                  *    +-----------+-----------+------------------+
2947                  *    |  USER ID  | GROUP ID  |FILE SERIAL NUMBER|
2948                  *    +-----------+-----------+------------------+
2949                  *   20          28          36                 44
2950                  */
2951                 length = 44;
2952                 if (extra_space(&ctl) < length)
2953                         bp = extra_next_record(&ctl, length);
2954                 if (bp != NULL) {
2955                         mode_t mode;
2956                         int64_t uid;
2957                         int64_t gid;
2958
2959                         mode = archive_entry_mode(file->entry);
2960                         uid = archive_entry_uid(file->entry);
2961                         gid = archive_entry_gid(file->entry);
2962                         if (iso9660->opt.rr == OPT_RR_USEFUL) {
2963                                 /*
2964                                  * This action is similar to mkisofs -r option
2965                                  * but our rockridge=useful option does not
2966                                  * set a zero to uid and gid.
2967                                  */
2968                                 /* set all read bit ON */
2969                                 mode |= 0444;
2970 #if !defined(_WIN32) && !defined(__CYGWIN__)
2971                                 if (mode & 0111)
2972 #endif
2973                                         /* set all exec bit ON */
2974                                         mode |= 0111;
2975                                 /* clear all write bits. */
2976                                 mode &= ~0222;
2977                                 /* clear setuid,setgid,sticky bits. */
2978                                 mode &= ~07000;
2979                         }
2980
2981                         bp[1] = 'P';
2982                         bp[2] = 'X';
2983                         bp[3] = length;
2984                         bp[4] = 1;      /* version      */
2985                         /* file mode */
2986                         set_num_733(bp+5, mode);
2987                         /* file links (stat.st_nlink) */
2988                         set_num_733(bp+13,
2989                             archive_entry_nlink(file->entry));
2990                         set_num_733(bp+21, (uint32_t)uid);
2991                         set_num_733(bp+29, (uint32_t)gid);
2992                         /* File Serial Number */
2993                         if (pxent->dir)
2994                                 set_num_733(bp+37, pxent->dir_location);
2995                         else if (file->hardlink_target != NULL)
2996                                 set_num_733(bp+37,
2997                                     file->hardlink_target->cur_content->location);
2998                         else
2999                                 set_num_733(bp+37,
3000                                     file->cur_content->location);
3001                         bp += length;
3002                 }
3003                 extra_tell_used_size(&ctl, length);
3004         }
3005
3006         /* Write "SL" System Use Entry. */
3007         if (rr_flag & RR_USE_SL) {
3008                 /*
3009                  *   "SL" Format:
3010                  *     e.g. a symbolic name is 'foo/bar'
3011                  *               len  ver  flg
3012                  *    +----+----+----+----+----+------------+
3013                  *    | 'S'| 'L'| 0F | 01 | 00 | components |
3014                  *    +----+----+----+----+----+-----+------+
3015                  *    0    1    2    3    4    5  ...|...  15
3016                  *    <----------------- len --------+------>
3017                  *    components :                   |
3018                  *     cflg clen                     |
3019                  *    +----+----+----+----+----+     |
3020                  *    | 00 | 03 | 'f'| 'o'| 'o'| <---+
3021                  *    +----+----+----+----+----+     |
3022                  *    5    6    7    8    9   10     |
3023                  *     cflg clen                     |
3024                  *    +----+----+----+----+----+     |
3025                  *    | 00 | 03 | 'b'| 'a'| 'r'| <---+
3026                  *    +----+----+----+----+----+
3027                  *   10   11   12   13   14   15
3028                  *
3029                  *    - cflg : flag of component
3030                  *    - clen : length of component
3031                  */
3032                 const char *sl;
3033                 char sl_last;
3034
3035                 if (extra_space(&ctl) < 7)
3036                         bp = extra_next_record(&ctl, 7);
3037                 sl = file->symlink.s;
3038                 sl_last = '\0';
3039                 if (bp != NULL) {
3040                         bp[1] = 'S';
3041                         bp[2] = 'L';
3042                         bp[4] = 1;      /* version      */
3043                 }
3044                 for (;;) {
3045                         unsigned char *nc, *cf,  *cl, cldmy = 0;
3046                         int sllen, slmax;
3047
3048                         slmax = extra_space(&ctl);
3049                         if (slmax > 0xff)
3050                                 slmax = 0xff;
3051                         if (bp != NULL)
3052                                 nc = &bp[6];
3053                         else
3054                                 nc = NULL;
3055                         cf = cl = NULL;
3056                         sllen = 0;
3057                         while (*sl && sllen + 11 < slmax) {
3058                                 if (sl_last == '\0' && sl[0] == '/') {
3059                                         /*
3060                                          *     flg  len
3061                                          *    +----+----+
3062                                          *    | 08 | 00 | ROOT component.
3063                                          *    +----+----+ ("/")
3064                                          *
3065                                          * Root component has to appear
3066                                          * at the first component only.
3067                                          */
3068                                         if (nc != NULL) {
3069                                                 cf = nc++;
3070                                                 *cf = 0x08; /* ROOT */
3071                                                 *nc++ = 0;
3072                                         }
3073                                         sllen += 2;
3074                                         sl++;
3075                                         sl_last = '/';
3076                                         cl = NULL;
3077                                         continue;
3078                                 }
3079                                 if (((sl_last == '\0' || sl_last == '/') &&
3080                                       sl[0] == '.' && sl[1] == '.' &&
3081                                      (sl[2] == '/' || sl[2] == '\0')) ||
3082                                     (sl[0] == '/' &&
3083                                       sl[1] == '.' && sl[2] == '.' &&
3084                                      (sl[3] == '/' || sl[3] == '\0'))) {
3085                                         /*
3086                                          *     flg  len
3087                                          *    +----+----+
3088                                          *    | 04 | 00 | PARENT component.
3089                                          *    +----+----+ ("..")
3090                                          */
3091                                         if (nc != NULL) {
3092                                                 cf = nc++;
3093                                                 *cf = 0x04; /* PARENT */
3094                                                 *nc++ = 0;
3095                                         }
3096                                         sllen += 2;
3097                                         if (sl[0] == '/')
3098                                                 sl += 3;/* skip "/.." */
3099                                         else
3100                                                 sl += 2;/* skip ".." */
3101                                         sl_last = '.';
3102                                         cl = NULL;
3103                                         continue;
3104                                 }
3105                                 if (((sl_last == '\0' || sl_last == '/') &&
3106                                       sl[0] == '.' &&
3107                                      (sl[1] == '/' || sl[1] == '\0')) ||
3108                                     (sl[0] == '/' && sl[1] == '.' &&
3109                                      (sl[2] == '/' || sl[2] == '\0'))) {
3110                                         /*
3111                                          *     flg  len
3112                                          *    +----+----+
3113                                          *    | 02 | 00 | CURRENT component.
3114                                          *    +----+----+ (".")
3115                                          */
3116                                         if (nc != NULL) {
3117                                                 cf = nc++;
3118                                                 *cf = 0x02; /* CURRENT */
3119                                                 *nc++ = 0;
3120                                         }
3121                                         sllen += 2;
3122                                         if (sl[0] == '/')
3123                                                 sl += 2;/* skip "/." */
3124                                         else
3125                                                 sl ++;  /* skip "." */
3126                                         sl_last = '.';
3127                                         cl = NULL;
3128                                         continue;
3129                                 }
3130                                 if (sl[0] == '/' || cl == NULL) {
3131                                         if (nc != NULL) {
3132                                                 cf = nc++;
3133                                                 *cf = 0;
3134                                                 cl = nc++;
3135                                                 *cl = 0;
3136                                         } else
3137                                                 cl = &cldmy;
3138                                         sllen += 2;
3139                                         if (sl[0] == '/') {
3140                                                 sl_last = *sl++;
3141                                                 continue;
3142                                         }
3143                                 }
3144                                 sl_last = *sl++;
3145                                 if (nc != NULL) {
3146                                         *nc++ = sl_last;
3147                                         (*cl) ++;
3148                                 }
3149                                 sllen++;
3150                         }
3151                         if (*sl) {
3152                                 length = 5 + sllen;
3153                                 if (bp != NULL) {
3154                                         /*
3155                                          * Mark flg as CONTINUE component.
3156                                          */
3157                                         *cf |= 0x01;
3158                                         /*
3159                                          *               len  ver  flg
3160                                          *    +----+----+----+----+----+-
3161                                          *    | 'S'| 'L'| XX | 01 | 01 |
3162                                          *    +----+----+----+----+----+-
3163                                          *                           ^
3164                                          *           continues in next "SL"
3165                                          */
3166                                         bp[3] = length;
3167                                         bp[5] = 0x01;/* This Symbolic Link
3168                                                       * continues in next
3169                                                       * "SL" field */
3170                                         bp += length;
3171                                 }
3172                                 extra_tell_used_size(&ctl, length);
3173                                 if (extra_space(&ctl) < 11)
3174                                         bp = extra_next_record(&ctl, 11);
3175                                 if (bp != NULL) {
3176                                         /* Next 'SL' */
3177                                         bp[1] = 'S';
3178                                         bp[2] = 'L';
3179                                         bp[4] = 1;    /* version */
3180                                 }
3181                         } else {
3182                                 length = 5 + sllen;
3183                                 if (bp != NULL) {
3184                                         bp[3] = length;
3185                                         bp[5] = 0;
3186                                         bp += length;
3187                                 }
3188                                 extra_tell_used_size(&ctl, length);
3189                                 break;
3190                         }
3191                 }
3192         }
3193
3194         /* Write "TF" System Use Entry. */
3195         if (rr_flag & RR_USE_TF) {
3196                 /*
3197                  *   "TF" Format:
3198                  *               len  ver
3199                  *    +----+----+----+----+-----+-------------+
3200                  *    | 'T'| 'F'| XX | 01 |FLAGS| TIME STAMPS |
3201                  *    +----+----+----+----+-----+-------------+
3202                  *    0    1    2    3    4     5            XX
3203                  *    TIME STAMPS : ISO 9660 Standard 9.1.5.
3204                  *                  If TF_LONG_FORM FLAGS is set,
3205                  *                  use ISO9660 Standard 8.4.26.1.
3206                  */
3207 #define TF_CREATION     0x01    /* Creation time recorded               */
3208 #define TF_MODIFY       0x02    /* Modification time recorded           */
3209 #define TF_ACCESS       0x04    /* Last Access time recorded            */
3210 #define TF_ATTRIBUTES   0x08    /* Last Attribute Change time recorded  */
3211 #define TF_BACKUP       0x10    /* Last Backup time recorded            */
3212 #define TF_EXPIRATION   0x20    /* Expiration time recorded             */
3213 #define TF_EFFECTIVE    0x40    /* Effective time recorded              */
3214 #define TF_LONG_FORM    0x80    /* ISO 9660 17-byte time format used    */
3215                 unsigned char tf_flags;
3216
3217                 length = 5;
3218                 tf_flags = 0;
3219 #ifndef COMPAT_MKISOFS
3220                 if (archive_entry_birthtime_is_set(file->entry) &&
3221                     archive_entry_birthtime(file->entry) <=
3222                     archive_entry_mtime(file->entry)) {
3223                         length += 7;
3224                         tf_flags |= TF_CREATION;
3225                 }
3226 #endif
3227                 if (archive_entry_mtime_is_set(file->entry)) {
3228                         length += 7;
3229                         tf_flags |= TF_MODIFY;
3230                 }
3231                 if (archive_entry_atime_is_set(file->entry)) {
3232                         length += 7;
3233                         tf_flags |= TF_ACCESS;
3234                 }
3235                 if (archive_entry_ctime_is_set(file->entry)) {
3236                         length += 7;
3237                         tf_flags |= TF_ATTRIBUTES;
3238                 }
3239                 if (extra_space(&ctl) < length)
3240                         bp = extra_next_record(&ctl, length);
3241                 if (bp != NULL) {
3242                         bp[1] = 'T';
3243                         bp[2] = 'F';
3244                         bp[3] = length;
3245                         bp[4] = 1;      /* version      */
3246                         bp[5] = tf_flags;
3247                         bp += 5;
3248                         /* Creation time */
3249                         if (tf_flags & TF_CREATION) {
3250                                 set_time_915(bp+1,
3251                                     archive_entry_birthtime(file->entry));
3252                                 bp += 7;
3253                         }
3254                         /* Modification time */
3255                         if (tf_flags & TF_MODIFY) {
3256                                 set_time_915(bp+1,
3257                                     archive_entry_mtime(file->entry));
3258                                 bp += 7;
3259                         }
3260                         /* Last Access time */
3261                         if (tf_flags & TF_ACCESS) {
3262                                 set_time_915(bp+1,
3263                                     archive_entry_atime(file->entry));
3264                                 bp += 7;
3265                         }
3266                         /* Last Attribute Change time */
3267                         if (tf_flags & TF_ATTRIBUTES) {
3268                                 set_time_915(bp+1,
3269                                     archive_entry_ctime(file->entry));
3270                                 bp += 7;
3271                         }
3272                 }
3273                 extra_tell_used_size(&ctl, length);
3274         }
3275
3276         /* Write "RE" System Use Entry. */
3277         if (rr_flag & RR_USE_RE) {
3278                 /*
3279                  *   "RE" Format:
3280                  *               len  ver
3281                  *    +----+----+----+----+
3282                  *    | 'R'| 'E'| 04 | 01 |
3283                  *    +----+----+----+----+
3284                  *    0    1    2    3    4
3285                  */
3286                 length = 4;
3287                 if (extra_space(&ctl) < length)
3288                         bp = extra_next_record(&ctl, length);
3289                 if (bp != NULL) {
3290                         bp[1] = 'R';
3291                         bp[2] = 'E';
3292                         bp[3] = length;
3293                         bp[4] = 1;      /* version      */
3294                         bp += length;
3295                 }
3296                 extra_tell_used_size(&ctl, length);
3297         }
3298
3299         /* Write "PL" System Use Entry. */
3300         if (rr_flag & RR_USE_PL) {
3301                 /*
3302                  *   "PL" Format:
3303                  *               len  ver
3304                  *    +----+----+----+----+------------+
3305                  *    | 'P'| 'L'| 0C | 01 | *LOCATION  |
3306                  *    +----+----+----+----+------------+
3307                  *    0    1    2    3    4           12
3308                  *    *LOCATION: location of parent directory
3309                  */
3310                 length = 12;
3311                 if (extra_space(&ctl) < length)
3312                         bp = extra_next_record(&ctl, length);
3313                 if (bp != NULL) {
3314                         bp[1] = 'P';
3315                         bp[2] = 'L';
3316                         bp[3] = length;
3317                         bp[4] = 1;      /* version      */
3318                         set_num_733(bp + 5,
3319                             rr_parent->dir_location);
3320                         bp += length;
3321                 }
3322                 extra_tell_used_size(&ctl, length);
3323         }
3324
3325         /* Write "CL" System Use Entry. */
3326         if (rr_flag & RR_USE_CL) {
3327                 /*
3328                  *   "CL" Format:
3329                  *               len  ver
3330                  *    +----+----+----+----+------------+
3331                  *    | 'C'| 'L'| 0C | 01 | *LOCATION  |
3332                  *    +----+----+----+----+------------+
3333                  *    0    1    2    3    4           12
3334                  *    *LOCATION: location of child directory
3335                  */
3336                 length = 12;
3337                 if (extra_space(&ctl) < length)
3338                         bp = extra_next_record(&ctl, length);
3339                 if (bp != NULL) {
3340                         bp[1] = 'C';
3341                         bp[2] = 'L';
3342                         bp[3] = length;
3343                         bp[4] = 1;      /* version      */
3344                         set_num_733(bp + 5,
3345                             isoent->rr_child->dir_location);
3346                         bp += length;
3347                 }
3348                 extra_tell_used_size(&ctl, length);
3349         }
3350
3351         /* Write "PN" System Use Entry. */
3352         if (rr_flag & RR_USE_PN) {
3353                 /*
3354                  *   "PN" Format:
3355                  *               len  ver
3356                  *    +----+----+----+----+------------+------------+
3357                  *    | 'P'| 'N'| 14 | 01 | dev_t high | dev_t low  |
3358                  *    +----+----+----+----+------------+------------+
3359                  *    0    1    2    3    4           12           20
3360                  */
3361                 length = 20;
3362                 if (extra_space(&ctl) < length)
3363                         bp = extra_next_record(&ctl, length);
3364                 if (bp != NULL) {
3365                         uint64_t dev;
3366
3367                         bp[1] = 'P';
3368                         bp[2] = 'N';
3369                         bp[3] = length;
3370                         bp[4] = 1;      /* version      */
3371                         dev = (uint64_t)archive_entry_rdev(file->entry);
3372                         set_num_733(bp + 5, (uint32_t)(dev >> 32));
3373                         set_num_733(bp + 13, (uint32_t)(dev & 0xFFFFFFFF));
3374                         bp += length;
3375                 }
3376                 extra_tell_used_size(&ctl, length);
3377         }
3378
3379         /* Write "ZF" System Use Entry. */
3380         if (file->zisofs.header_size) {
3381                 /*
3382                  *   "ZF" Format:
3383                  *               len  ver
3384                  *    +----+----+----+----+----+----+-------------+
3385                  *    | 'Z'| 'F'| 10 | 01 | 'p'| 'z'| Header Size |
3386                  *    +----+----+----+----+----+----+-------------+
3387                  *    0    1    2    3    4    5    6             7
3388                  *    +--------------------+-------------------+
3389                  *    | Log2 of block Size | Uncompressed Size |
3390                  *    +--------------------+-------------------+
3391                  *    7                    8                   16
3392                  */
3393                 length = 16;
3394                 if (extra_space(&ctl) < length)
3395                         bp = extra_next_record(&ctl, length);
3396                 if (bp != NULL) {
3397                         bp[1] = 'Z';
3398                         bp[2] = 'F';
3399                         bp[3] = length;
3400                         bp[4] = 1;      /* version      */
3401                         bp[5] = 'p';
3402                         bp[6] = 'z';
3403                         bp[7] = file->zisofs.header_size;
3404                         bp[8] = file->zisofs.log2_bs;
3405                         set_num_733(bp + 9, file->zisofs.uncompressed_size);
3406                         bp += length;
3407                 }
3408                 extra_tell_used_size(&ctl, length);
3409         }
3410
3411         /* Write "CE" System Use Entry. */
3412         if (t == DIR_REC_SELF && isoent == isoent->parent) {
3413                 length = RR_CE_SIZE;
3414                 if (bp != NULL)
3415                         set_SUSP_CE(bp+1, iso9660->location_rrip_er,
3416                             0, RRIP_ER_SIZE);
3417                 extra_tell_used_size(&ctl, length);
3418         }
3419
3420         extra_close_record(&ctl, 0);
3421
3422         return (ctl.dr_len);
3423 }
3424
3425 /*
3426  * Write data of a Directory Record or calculate writing bytes itself.
3427  * If parameter `p' is NULL, calculates the size of writing data, which
3428  * a Directory Record needs to write, then it saved and return
3429  * the calculated size.
3430  * Parameter `n' is a remaining size of buffer. when parameter `p' is
3431  * not NULL, check whether that `n' is not less than the saved size.
3432  * if that `n' is small, return zero.
3433  *
3434  * This format of the Directory Record is according to
3435  * ISO9660 Standard 9.1
3436  */
3437 static int
3438 set_directory_record(unsigned char *p, size_t n, struct isoent *isoent,
3439     struct iso9660 *iso9660, enum dir_rec_type t,
3440     enum vdd_type vdd_type)
3441 {
3442         unsigned char *bp;
3443         size_t dr_len;
3444         size_t fi_len;
3445
3446         if (p != NULL) {
3447                 /*
3448                  * Check whether a write buffer size is less than the
3449                  * saved size which is needed to write this Directory
3450                  * Record.
3451                  */
3452                 switch (t) {
3453                 case DIR_REC_VD:
3454                         dr_len = isoent->dr_len.vd; break;
3455                 case DIR_REC_SELF:
3456                         dr_len = isoent->dr_len.self; break;
3457                 case DIR_REC_PARENT:
3458                         dr_len = isoent->dr_len.parent; break;
3459                 case DIR_REC_NORMAL:
3460                 default:
3461                         dr_len = isoent->dr_len.normal; break;
3462                 }
3463                 if (dr_len > n)
3464                         return (0);/* Needs more buffer size. */
3465         }
3466
3467         if (t == DIR_REC_NORMAL && isoent->identifier != NULL)
3468                 fi_len = isoent->id_len;
3469         else
3470                 fi_len = 1;
3471
3472         if (p != NULL) {
3473                 struct isoent *xisoent;
3474                 struct isofile *file;
3475                 unsigned char flag;
3476
3477                 if (t == DIR_REC_PARENT)
3478                         xisoent = isoent->parent;
3479                 else
3480                         xisoent = isoent;
3481                 file = isoent->file;
3482                 if (file->hardlink_target != NULL)
3483                         file = file->hardlink_target;
3484                 /* Make a file flag. */
3485                 if (xisoent->dir)
3486                         flag = FILE_FLAG_DIRECTORY;
3487                 else {
3488                         if (file->cur_content->next != NULL)
3489                                 flag = FILE_FLAG_MULTI_EXTENT;
3490                         else
3491                                 flag = 0;
3492                 }
3493
3494                 bp = p -1;
3495                 /* Extended Attribute Record Length */
3496                 set_num_711(bp+2, 0);
3497                 /* Location of Extent */
3498                 if (xisoent->dir)
3499                         set_num_733(bp+3, xisoent->dir_location);
3500                 else
3501                         set_num_733(bp+3, file->cur_content->location);
3502                 /* Data Length */
3503                 if (xisoent->dir)
3504                         set_num_733(bp+11,
3505                             xisoent->dir_block * LOGICAL_BLOCK_SIZE);
3506                 else
3507                         set_num_733(bp+11, (uint32_t)file->cur_content->size);
3508                 /* Recording Date and Time */
3509                 /* NOTE:
3510                  *  If a file type is symbolic link, you are seeing this
3511                  *  field value is different from a value mkisofs makes.
3512                  *  libarchive uses lstat to get this one, but it
3513                  *  seems mkisofs uses stat to get.
3514                  */
3515                 set_time_915(bp+19,
3516                     archive_entry_mtime(xisoent->file->entry));
3517                 /* File Flags */
3518                 bp[26] = flag;
3519                 /* File Unit Size */
3520                 set_num_711(bp+27, 0);
3521                 /* Interleave Gap Size */
3522                 set_num_711(bp+28, 0);
3523                 /* Volume Sequence Number */
3524                 set_num_723(bp+29, iso9660->volume_sequence_number);
3525                 /* Length of File Identifier */
3526                 set_num_711(bp+33, (unsigned char)fi_len);
3527                 /* File Identifier */
3528                 switch (t) {
3529                 case DIR_REC_VD:
3530                 case DIR_REC_SELF:
3531                         set_num_711(bp+34, 0);
3532                         break;
3533                 case DIR_REC_PARENT:
3534                         set_num_711(bp+34, 1);
3535                         break;
3536                 case DIR_REC_NORMAL:
3537                         if (isoent->identifier != NULL)
3538                                 memcpy(bp+34, isoent->identifier, fi_len);
3539                         else
3540                                 set_num_711(bp+34, 0);
3541                         break;
3542                 }
3543         } else
3544                 bp = NULL;
3545         dr_len = 33 + fi_len;
3546         /* Padding Field */
3547         if (dr_len & 0x01) {
3548                 dr_len ++;
3549                 if (p != NULL)
3550                         bp[dr_len] = 0;
3551         }
3552
3553         /* Volume Descriptor does not record extension. */
3554         if (t == DIR_REC_VD) {
3555                 if (p != NULL)
3556                         /* Length of Directory Record */
3557                         set_num_711(p, (unsigned char)dr_len);
3558                 else
3559                         isoent->dr_len.vd = (int)dr_len;
3560                 return ((int)dr_len);
3561         }
3562
3563         /* Rockridge */
3564         if (iso9660->opt.rr && vdd_type != VDD_JOLIET)
3565                 dr_len = set_directory_record_rr(bp, (int)dr_len,
3566                     isoent, iso9660, t);
3567
3568         if (p != NULL)
3569                 /* Length of Directory Record */
3570                 set_num_711(p, (unsigned char)dr_len);
3571         else {
3572                 /*
3573                  * Save the size which is needed to write this
3574                  * Directory Record.
3575                  */
3576                 switch (t) {
3577                 case DIR_REC_VD:
3578                         /* This case does not come, but compiler
3579                          * complains that DIR_REC_VD not handled
3580                          *  in switch ....  */
3581                         break;
3582                 case DIR_REC_SELF:
3583                         isoent->dr_len.self = (int)dr_len; break;
3584                 case DIR_REC_PARENT:
3585                         isoent->dr_len.parent = (int)dr_len; break;
3586                 case DIR_REC_NORMAL:
3587                         isoent->dr_len.normal = (int)dr_len; break;
3588                 }
3589         }
3590
3591         return ((int)dr_len);
3592 }
3593
3594 /*
3595  * Calculate the size of a directory record.
3596  */
3597 static inline int
3598 get_dir_rec_size(struct iso9660 *iso9660, struct isoent *isoent,
3599     enum dir_rec_type t, enum vdd_type vdd_type)
3600 {
3601
3602         return (set_directory_record(NULL, SIZE_MAX,
3603             isoent, iso9660, t, vdd_type));
3604 }
3605
3606 /*
3607  * Manage to write ISO-image data with wbuff to reduce calling
3608  * __archive_write_output() for performance.
3609  */
3610
3611
3612 static inline unsigned char *
3613 wb_buffptr(struct archive_write *a)
3614 {
3615         struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3616
3617         return (&(iso9660->wbuff[sizeof(iso9660->wbuff)
3618                 - iso9660->wbuff_remaining]));
3619 }
3620
3621 static int
3622 wb_write_out(struct archive_write *a)
3623 {
3624         struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3625         size_t wsize, nw;
3626         int r;
3627
3628         wsize = sizeof(iso9660->wbuff) - iso9660->wbuff_remaining;
3629         nw = wsize % LOGICAL_BLOCK_SIZE;
3630         if (iso9660->wbuff_type == WB_TO_STREAM)
3631                 r = __archive_write_output(a, iso9660->wbuff, wsize - nw);
3632         else
3633                 r = write_to_temp(a, iso9660->wbuff, wsize - nw);
3634         /* Increase the offset. */
3635         iso9660->wbuff_offset += wsize - nw;
3636         if (iso9660->wbuff_offset > iso9660->wbuff_written)
3637                 iso9660->wbuff_written = iso9660->wbuff_offset;
3638         iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
3639         if (nw) {
3640                 iso9660->wbuff_remaining -= nw;
3641                 memmove(iso9660->wbuff, iso9660->wbuff + wsize - nw, nw);
3642         }
3643         return (r);
3644 }
3645
3646 static int
3647 wb_consume(struct archive_write *a, size_t size)
3648 {
3649         struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3650
3651         if (size > iso9660->wbuff_remaining ||
3652             iso9660->wbuff_remaining == 0) {
3653                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
3654                     "Internal Programming error: iso9660:wb_consume()"
3655                     " size=%jd, wbuff_remaining=%jd",
3656                     (intmax_t)size, (intmax_t)iso9660->wbuff_remaining);
3657                 return (ARCHIVE_FATAL);
3658         }
3659         iso9660->wbuff_remaining -= size;
3660         if (iso9660->wbuff_remaining < LOGICAL_BLOCK_SIZE)
3661                 return (wb_write_out(a));
3662         return (ARCHIVE_OK);
3663 }
3664
3665 #ifdef HAVE_ZLIB_H
3666
3667 static int
3668 wb_set_offset(struct archive_write *a, int64_t off)
3669 {
3670         struct iso9660 *iso9660 = (struct iso9660 *)a->format_data;
3671         int64_t used, ext_bytes;
3672
3673         if (iso9660->wbuff_type != WB_TO_TEMP) {
3674                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
3675                     "Internal Programming error: iso9660:wb_set_offset()");
3676                 return (ARCHIVE_FATAL);
3677         }
3678
3679         used = sizeof(iso9660->wbuff) - iso9660->wbuff_remaining;
3680         if (iso9660->wbuff_offset + used > iso9660->wbuff_tail)
3681                 iso9660->wbuff_tail = iso9660->wbuff_offset + used;
3682         if (iso9660->wbuff_offset < iso9660->wbuff_written) {
3683                 if (used > 0 &&
3684                     write_to_temp(a, iso9660->wbuff, (size_t)used) != ARCHIVE_OK)
3685                         return (ARCHIVE_FATAL);
3686                 iso9660->wbuff_offset = iso9660->wbuff_written;
3687                 lseek(iso9660->temp_fd, iso9660->wbuff_offset, SEEK_SET);
3688                 iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
3689                 used = 0;
3690         }
3691         if (off < iso9660->wbuff_offset) {
3692                 /*
3693                  * Write out waiting data.
3694                  */
3695                 if (used > 0) {
3696                         if (wb_write_out(a) != ARCHIVE_OK)
3697                                 return (ARCHIVE_FATAL);
3698                 }
3699                 lseek(iso9660->temp_fd, off, SEEK_SET);
3700                 iso9660->wbuff_offset = off;
3701                 iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
3702         } else if (off <= iso9660->wbuff_tail) {
3703                 iso9660->wbuff_remaining = (size_t)
3704                     (sizeof(iso9660->wbuff) - (off - iso9660->wbuff_offset));
3705         } else {
3706                 ext_bytes = off - iso9660->wbuff_tail;
3707                 iso9660->wbuff_remaining = (size_t)(sizeof(iso9660->wbuff)
3708                    - (iso9660->wbuff_tail - iso9660->wbuff_offset));
3709                 while (ext_bytes >= (int64_t)iso9660->wbuff_remaining) {
3710                         if (write_null(a, (size_t)iso9660->wbuff_remaining)
3711                             != ARCHIVE_OK)
3712                                 return (ARCHIVE_FATAL);
3713                         ext_bytes -= iso9660->wbuff_remaining;
3714                 }
3715                 if (ext_bytes > 0) {
3716                         if (write_null(a, (size_t)ext_bytes) != ARCHIVE_OK)
3717                                 return (ARCHIVE_FATAL);
3718                 }
3719         }
3720         return (ARCHIVE_OK);
3721 }
3722
3723 #endif /* HAVE_ZLIB_H */
3724
3725 static int
3726 write_null(struct archive_write *a, size_t size)
3727 {
3728         size_t remaining;
3729         unsigned char *p, *old;
3730         int r;
3731
3732         remaining = wb_remaining(a);
3733         p = wb_buffptr(a);
3734         if (size <= remaining) {
3735                 memset(p, 0, size);
3736                 return (wb_consume(a, size));
3737         }
3738         memset(p, 0, remaining);
3739         r = wb_consume(a, remaining);
3740         if (r != ARCHIVE_OK)
3741                 return (r);
3742         size -= remaining;
3743         old = p;
3744         p = wb_buffptr(a);
3745         memset(p, 0, old - p);
3746         remaining = wb_remaining(a);
3747         while (size) {
3748                 size_t wsize = size;
3749
3750                 if (wsize > remaining)
3751                         wsize = remaining;
3752                 r = wb_consume(a, wsize);
3753                 if (r != ARCHIVE_OK)
3754                         return (r);
3755                 size -= wsize;
3756         }
3757         return (ARCHIVE_OK);
3758 }
3759
3760 /*
3761  * Write Volume Descriptor Set Terminator
3762  */
3763 static int
3764 write_VD_terminator(struct archive_write *a)
3765 {
3766         unsigned char *bp;
3767
3768         bp = wb_buffptr(a) -1;
3769         set_VD_bp(bp, VDT_TERMINATOR, 1);
3770         set_unused_field_bp(bp, 8, LOGICAL_BLOCK_SIZE);
3771
3772         return (wb_consume(a, LOGICAL_BLOCK_SIZE));
3773 }
3774
3775 static int
3776 set_file_identifier(unsigned char *bp, int from, int to, enum vdc vdc,
3777     struct archive_write *a, struct vdd *vdd, struct archive_string *id,
3778     const char *label, int leading_under, enum char_type char_type)
3779 {
3780         char identifier[256];
3781         struct isoent *isoent;
3782         const char *ids;
3783         size_t len;
3784         int r;
3785
3786         if (id->length > 0 && leading_under && id->s[0] != '_') {
3787                 if (char_type == A_CHAR)
3788                         r = set_str_a_characters_bp(a, bp, from, to, id->s, vdc);
3789                 else
3790                         r = set_str_d_characters_bp(a, bp, from, to, id->s, vdc);
3791         } else if (id->length > 0) {
3792                 ids = id->s;
3793                 if (leading_under)
3794                         ids++;
3795                 isoent = isoent_find_entry(vdd->rootent, ids);
3796                 if (isoent == NULL) {
3797                         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
3798                             "Not Found %s `%s'.",
3799                             label, ids);
3800                         return (ARCHIVE_FATAL);
3801                 }
3802                 len = isoent->ext_off + isoent->ext_len;
3803                 if (vdd->vdd_type == VDD_JOLIET) {
3804                         if (len > sizeof(identifier)-2)
3805                                 len = sizeof(identifier)-2;
3806                 } else {
3807                         if (len > sizeof(identifier)-1)
3808                                 len = sizeof(identifier)-1;
3809                 }
3810                 memcpy(identifier, isoent->identifier, len);
3811                 identifier[len] = '\0';
3812                 if (vdd->vdd_type == VDD_JOLIET) {
3813                         identifier[len+1] = 0;
3814                         vdc = VDC_UCS2_DIRECT;
3815                 }
3816                 if (char_type == A_CHAR)
3817                         r = set_str_a_characters_bp(a, bp, from, to,
3818                             identifier, vdc);
3819                 else
3820                         r = set_str_d_characters_bp(a, bp, from, to,
3821                             identifier, vdc);
3822         } else {
3823                 if (char_type == A_CHAR)
3824                         r = set_str_a_characters_bp(a, bp, from, to, NULL, vdc);
3825                 else
3826                         r = set_str_d_characters_bp(a, bp, from, to, NULL, vdc);
3827         }
3828         return (r);
3829 }
3830
3831 /*
3832  * Write Primary/Supplementary Volume Descriptor
3833  */
3834 static int
3835 write_VD(struct archive_write *a, struct vdd *vdd)
3836 {
3837         struct iso9660 *iso9660;
3838         unsigned char *bp;
3839         uint16_t volume_set_size = 1;
3840         char identifier[256];
3841         enum VD_type vdt;
3842         enum vdc vdc;
3843         unsigned char vd_ver, fst_ver;
3844         int r;
3845
3846         iso9660 = a->format_data;
3847         switch (vdd->vdd_type) {
3848         case VDD_JOLIET:
3849                 vdt = VDT_SUPPLEMENTARY;
3850                 vd_ver = fst_ver = 1;
3851                 vdc = VDC_UCS2;
3852                 break;
3853         case VDD_ENHANCED:
3854                 vdt = VDT_SUPPLEMENTARY;
3855                 vd_ver = fst_ver = 2;
3856                 vdc = VDC_LOWERCASE;
3857                 break;
3858         case VDD_PRIMARY:
3859         default:
3860                 vdt = VDT_PRIMARY;
3861                 vd_ver = fst_ver = 1;
3862 #ifdef COMPAT_MKISOFS
3863                 vdc = VDC_LOWERCASE;
3864 #else
3865                 vdc = VDC_STD;
3866 #endif
3867                 break;
3868         }
3869
3870         bp = wb_buffptr(a) -1;
3871         /* Volume Descriptor Type */
3872         set_VD_bp(bp, vdt, vd_ver);
3873         /* Unused Field */
3874         set_unused_field_bp(bp, 8, 8);
3875         /* System Identifier */
3876         get_system_identitier(identifier, sizeof(identifier));
3877         r = set_str_a_characters_bp(a, bp, 9, 40, identifier, vdc);
3878         if (r != ARCHIVE_OK)
3879                 return (r);
3880         /* Volume Identifier */
3881         r = set_str_d_characters_bp(a, bp, 41, 72,
3882             iso9660->volume_identifier.s, vdc);
3883         if (r != ARCHIVE_OK)
3884                 return (r);
3885         /* Unused Field */
3886         set_unused_field_bp(bp, 73, 80);
3887         /* Volume Space Size */
3888         set_num_733(bp+81, iso9660->volume_space_size);
3889         if (vdd->vdd_type == VDD_JOLIET) {
3890                 /* Escape Sequences */
3891                 bp[89] = 0x25;/* UCS-2 Level 3 */
3892                 bp[90] = 0x2F;
3893                 bp[91] = 0x45;
3894                 memset(bp + 92, 0, 120 - 92 + 1);
3895         } else {
3896                 /* Unused Field */
3897                 set_unused_field_bp(bp, 89, 120);
3898         }
3899         /* Volume Set Size */
3900         set_num_723(bp+121, volume_set_size);
3901         /* Volume Sequence Number */
3902         set_num_723(bp+125, iso9660->volume_sequence_number);
3903         /* Logical Block Size */
3904         set_num_723(bp+129, LOGICAL_BLOCK_SIZE);
3905         /* Path Table Size */
3906         set_num_733(bp+133, vdd->path_table_size);
3907         /* Location of Occurrence of Type L Path Table */
3908         set_num_731(bp+141, vdd->location_type_L_path_table);
3909         /* Location of Optional Occurrence of Type L Path Table */
3910         set_num_731(bp+145, 0);
3911         /* Location of Occurrence of Type M Path Table */
3912         set_num_732(bp+149, vdd->location_type_M_path_table);
3913         /* Location of Optional Occurrence of Type M Path Table */
3914         set_num_732(bp+153, 0);
3915         /* Directory Record for Root Directory(BP 157 to 190) */
3916         set_directory_record(bp+157, 190-157+1, vdd->rootent,
3917             iso9660, DIR_REC_VD, vdd->vdd_type);
3918         /* Volume Set Identifier */
3919         r = set_str_d_characters_bp(a, bp, 191, 318, "", vdc);
3920         if (r != ARCHIVE_OK)
3921                 return (r);
3922         /* Publisher Identifier */
3923         r = set_file_identifier(bp, 319, 446, vdc, a, vdd,
3924             &(iso9660->publisher_identifier),
3925             "Publisher File", 1, A_CHAR);
3926         if (r != ARCHIVE_OK)
3927                 return (r);
3928         /* Data Preparer Identifier */
3929         r = set_file_identifier(bp, 447, 574, vdc, a, vdd,
3930             &(iso9660->data_preparer_identifier),
3931             "Data Preparer File", 1, A_CHAR);
3932         if (r != ARCHIVE_OK)
3933                 return (r);
3934         /* Application Identifier */
3935         r = set_file_identifier(bp, 575, 702, vdc, a, vdd,
3936             &(iso9660->application_identifier),
3937             "Application File", 1, A_CHAR);
3938         if (r != ARCHIVE_OK)
3939                 return (r);
3940         /* Copyright File Identifier */
3941         r = set_file_identifier(bp, 703, 739, vdc, a, vdd,
3942             &(iso9660->copyright_file_identifier),
3943             "Copyright File", 0, D_CHAR);
3944         if (r != ARCHIVE_OK)
3945                 return (r);
3946         /* Abstract File Identifier */
3947         r = set_file_identifier(bp, 740, 776, vdc, a, vdd,
3948             &(iso9660->abstract_file_identifier),
3949             "Abstract File", 0, D_CHAR);
3950         if (r != ARCHIVE_OK)
3951                 return (r);
3952         /* Bibliographic File Identifier */
3953         r = set_file_identifier(bp, 777, 813, vdc, a, vdd,
3954             &(iso9660->bibliographic_file_identifier),
3955             "Bibliongraphic File", 0, D_CHAR);
3956         if (r != ARCHIVE_OK)
3957                 return (r);
3958         /* Volume Creation Date and Time */
3959         set_date_time(bp+814, iso9660->birth_time);
3960         /* Volume Modification Date and Time */
3961         set_date_time(bp+831, iso9660->birth_time);
3962         /* Volume Expiration Date and Time(obsolete) */
3963         set_date_time_null(bp+848);
3964         /* Volume Effective Date and Time */
3965         set_date_time(bp+865, iso9660->birth_time);
3966         /* File Structure Version */
3967         bp[882] = fst_ver;
3968         /* Reserved */
3969         bp[883] = 0;
3970         /* Application Use */
3971         memset(bp + 884, 0x20, 1395 - 884 + 1);
3972         /* Reserved */
3973         set_unused_field_bp(bp, 1396, LOGICAL_BLOCK_SIZE);
3974
3975         return (wb_consume(a, LOGICAL_BLOCK_SIZE));
3976 }
3977
3978 /*
3979  * Write Boot Record Volume Descriptor
3980  */
3981 static int
3982 write_VD_boot_record(struct archive_write *a)
3983 {
3984         struct iso9660 *iso9660;
3985         unsigned char *bp;
3986
3987         iso9660 = a->format_data;
3988         bp = wb_buffptr(a) -1;
3989         /* Volume Descriptor Type */
3990         set_VD_bp(bp, VDT_BOOT_RECORD, 1);
3991         /* Boot System Identifier */
3992         memcpy(bp+8, "EL TORITO SPECIFICATION", 23);
3993         set_unused_field_bp(bp, 8+23, 39);
3994         /* Unused */
3995         set_unused_field_bp(bp, 40, 71);
3996         /* Absolute pointer to first sector of Boot Catalog */
3997         set_num_731(bp+72,
3998             iso9660->el_torito.catalog->file->content.location);
3999         /* Unused */
4000         set_unused_field_bp(bp, 76, LOGICAL_BLOCK_SIZE);
4001
4002         return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4003 }
4004
4005 enum keytype {
4006         KEY_FLG,
4007         KEY_STR,
4008         KEY_INT,
4009         KEY_HEX
4010 };
4011 static void
4012 set_option_info(struct archive_string *info, int *opt, const char *key,
4013     enum keytype type,  ...)
4014 {
4015         va_list ap;
4016         char prefix;
4017         const char *s;
4018         int d;
4019
4020         prefix = (*opt==0)? ' ':',';
4021         va_start(ap, type);
4022         switch (type) {
4023         case KEY_FLG:
4024                 d = va_arg(ap, int);
4025                 archive_string_sprintf(info, "%c%s%s",
4026                     prefix, (d == 0)?"!":"", key);
4027                 break;
4028         case KEY_STR:
4029                 s = va_arg(ap, const char *);
4030                 archive_string_sprintf(info, "%c%s=%s",
4031                     prefix, key, s);
4032                 break;
4033         case KEY_INT:
4034                 d = va_arg(ap, int);
4035                 archive_string_sprintf(info, "%c%s=%d",
4036                     prefix, key, d);
4037                 break;
4038         case KEY_HEX:
4039                 d = va_arg(ap, int);
4040                 archive_string_sprintf(info, "%c%s=%x",
4041                     prefix, key, d);
4042                 break;
4043         }
4044         va_end(ap);
4045
4046         *opt = 1;
4047 }
4048
4049 /*
4050  * Make Non-ISO File System Information
4051  */
4052 static int
4053 write_information_block(struct archive_write *a)
4054 {
4055         struct iso9660 *iso9660;
4056         char buf[128];
4057         const char *v;
4058         int opt, r;
4059         struct archive_string info;
4060         size_t info_size = LOGICAL_BLOCK_SIZE *
4061                                NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK;
4062
4063         iso9660 = (struct iso9660 *)a->format_data;
4064         if (info_size > wb_remaining(a)) {
4065                 r = wb_write_out(a);
4066                 if (r != ARCHIVE_OK)
4067                         return (r);
4068         }
4069         archive_string_init(&info);
4070         if (archive_string_ensure(&info, info_size) == NULL) {
4071                 archive_set_error(&a->archive, ENOMEM,
4072                     "Can't allocate memory");
4073                 return (ARCHIVE_FATAL);
4074         }
4075         memset(info.s, 0, info_size);
4076         opt = 0;
4077 #if defined(HAVE__CTIME64_S)
4078         {
4079                 __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits
4080                 _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp));
4081         }
4082 #elif defined(HAVE_CTIME_R)
4083         ctime_r(&(iso9660->birth_time), buf);
4084 #else
4085         strncpy(buf, ctime(&(iso9660->birth_time)), sizeof(buf)-1);
4086         buf[sizeof(buf)-1] = '\0';
4087 #endif
4088         archive_string_sprintf(&info,
4089             "INFO %s%s", buf, archive_version_string());
4090         if (iso9660->opt.abstract_file != OPT_ABSTRACT_FILE_DEFAULT)
4091                 set_option_info(&info, &opt, "abstract-file",
4092                     KEY_STR, iso9660->abstract_file_identifier.s);
4093         if (iso9660->opt.application_id != OPT_APPLICATION_ID_DEFAULT)
4094                 set_option_info(&info, &opt, "application-id",
4095                     KEY_STR, iso9660->application_identifier.s);
4096         if (iso9660->opt.allow_vernum != OPT_ALLOW_VERNUM_DEFAULT)
4097                 set_option_info(&info, &opt, "allow-vernum",
4098                     KEY_FLG, iso9660->opt.allow_vernum);
4099         if (iso9660->opt.biblio_file != OPT_BIBLIO_FILE_DEFAULT)
4100                 set_option_info(&info, &opt, "biblio-file",
4101                     KEY_STR, iso9660->bibliographic_file_identifier.s);
4102         if (iso9660->opt.boot != OPT_BOOT_DEFAULT)
4103                 set_option_info(&info, &opt, "boot",
4104                     KEY_STR, iso9660->el_torito.boot_filename.s);
4105         if (iso9660->opt.boot_catalog != OPT_BOOT_CATALOG_DEFAULT)
4106                 set_option_info(&info, &opt, "boot-catalog",
4107                     KEY_STR, iso9660->el_torito.catalog_filename.s);
4108         if (iso9660->opt.boot_info_table != OPT_BOOT_INFO_TABLE_DEFAULT)
4109                 set_option_info(&info, &opt, "boot-info-table",
4110                     KEY_FLG, iso9660->opt.boot_info_table);
4111         if (iso9660->opt.boot_load_seg != OPT_BOOT_LOAD_SEG_DEFAULT)
4112                 set_option_info(&info, &opt, "boot-load-seg",
4113                     KEY_HEX, iso9660->el_torito.boot_load_seg);
4114         if (iso9660->opt.boot_load_size != OPT_BOOT_LOAD_SIZE_DEFAULT)
4115                 set_option_info(&info, &opt, "boot-load-size",
4116                     KEY_INT, iso9660->el_torito.boot_load_size);
4117         if (iso9660->opt.boot_type != OPT_BOOT_TYPE_DEFAULT) {
4118                 v = "no-emulation";
4119                 if (iso9660->opt.boot_type == OPT_BOOT_TYPE_FD)
4120                         v = "fd";
4121                 if (iso9660->opt.boot_type == OPT_BOOT_TYPE_HARD_DISK)
4122                         v = "hard-disk";
4123                 set_option_info(&info, &opt, "boot-type",
4124                     KEY_STR, v);
4125         }
4126 #ifdef HAVE_ZLIB_H
4127         if (iso9660->opt.compression_level != OPT_COMPRESSION_LEVEL_DEFAULT)
4128                 set_option_info(&info, &opt, "compression-level",
4129                     KEY_INT, iso9660->zisofs.compression_level);
4130 #endif
4131         if (iso9660->opt.copyright_file != OPT_COPYRIGHT_FILE_DEFAULT)
4132                 set_option_info(&info, &opt, "copyright-file",
4133                     KEY_STR, iso9660->copyright_file_identifier.s);
4134         if (iso9660->opt.iso_level != OPT_ISO_LEVEL_DEFAULT)
4135                 set_option_info(&info, &opt, "iso-level",
4136                     KEY_INT, iso9660->opt.iso_level);
4137         if (iso9660->opt.joliet != OPT_JOLIET_DEFAULT) {
4138                 if (iso9660->opt.joliet == OPT_JOLIET_LONGNAME)
4139                         set_option_info(&info, &opt, "joliet",
4140                             KEY_STR, "long");
4141                 else
4142                         set_option_info(&info, &opt, "joliet",
4143                             KEY_FLG, iso9660->opt.joliet);
4144         }
4145         if (iso9660->opt.limit_depth != OPT_LIMIT_DEPTH_DEFAULT)
4146                 set_option_info(&info, &opt, "limit-depth",
4147                     KEY_FLG, iso9660->opt.limit_depth);
4148         if (iso9660->opt.limit_dirs != OPT_LIMIT_DIRS_DEFAULT)
4149                 set_option_info(&info, &opt, "limit-dirs",
4150                     KEY_FLG, iso9660->opt.limit_dirs);
4151         if (iso9660->opt.pad != OPT_PAD_DEFAULT)
4152                 set_option_info(&info, &opt, "pad",
4153                     KEY_FLG, iso9660->opt.pad);
4154         if (iso9660->opt.publisher != OPT_PUBLISHER_DEFAULT)
4155                 set_option_info(&info, &opt, "publisher",
4156                     KEY_STR, iso9660->publisher_identifier.s);
4157         if (iso9660->opt.rr != OPT_RR_DEFAULT) {
4158                 if (iso9660->opt.rr == OPT_RR_DISABLED)
4159                         set_option_info(&info, &opt, "rockridge",
4160                             KEY_FLG, iso9660->opt.rr);
4161                 else if (iso9660->opt.rr == OPT_RR_STRICT)
4162                         set_option_info(&info, &opt, "rockridge",
4163                             KEY_STR, "strict");
4164                 else if (iso9660->opt.rr == OPT_RR_USEFUL)
4165                         set_option_info(&info, &opt, "rockridge",
4166                             KEY_STR, "useful");
4167         }
4168         if (iso9660->opt.volume_id != OPT_VOLUME_ID_DEFAULT)
4169                 set_option_info(&info, &opt, "volume-id",
4170                     KEY_STR, iso9660->volume_identifier.s);
4171         if (iso9660->opt.zisofs != OPT_ZISOFS_DEFAULT)
4172                 set_option_info(&info, &opt, "zisofs",
4173                     KEY_FLG, iso9660->opt.zisofs);
4174
4175         memcpy(wb_buffptr(a), info.s, info_size);
4176         archive_string_free(&info);
4177         return (wb_consume(a, info_size));
4178 }
4179
4180 static int
4181 write_rr_ER(struct archive_write *a)
4182 {
4183         unsigned char *p;
4184
4185         p = wb_buffptr(a);
4186
4187         memset(p, 0, LOGICAL_BLOCK_SIZE);
4188         p[0] = 'E';
4189         p[1] = 'R';
4190         p[3] = 0x01;
4191         p[2] = RRIP_ER_SIZE;
4192         p[4] = RRIP_ER_ID_SIZE;
4193         p[5] = RRIP_ER_DSC_SIZE;
4194         p[6] = RRIP_ER_SRC_SIZE;
4195         p[7] = 0x01;
4196         memcpy(&p[8], rrip_identifier, p[4]);
4197         memcpy(&p[8+p[4]], rrip_descriptor, p[5]);
4198         memcpy(&p[8+p[4]+p[5]], rrip_source, p[6]);
4199
4200         return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4201 }
4202
4203 static void
4204 calculate_path_table_size(struct vdd *vdd)
4205 {
4206         int depth, size;
4207         struct path_table *pt;
4208
4209         pt = vdd->pathtbl;
4210         size = 0;
4211         for (depth = 0; depth < vdd->max_depth; depth++) {
4212                 struct isoent **ptbl;
4213                 int i, cnt;
4214
4215                 if ((cnt = pt[depth].cnt) == 0)
4216                         break;
4217
4218                 ptbl = pt[depth].sorted;
4219                 for (i = 0; i < cnt; i++) {
4220                         int len;
4221
4222                         if (ptbl[i]->identifier == NULL)
4223                                 len = 1; /* root directory */
4224                         else
4225                                 len = ptbl[i]->id_len;
4226                         if (len & 0x01)
4227                                 len++; /* Padding Field */
4228                         size += 8 + len;
4229                 }
4230         }
4231         vdd->path_table_size = size;
4232         vdd->path_table_block =
4233             ((size + PATH_TABLE_BLOCK_SIZE -1) /
4234             PATH_TABLE_BLOCK_SIZE) *
4235             (PATH_TABLE_BLOCK_SIZE / LOGICAL_BLOCK_SIZE);
4236 }
4237
4238 static int
4239 _write_path_table(struct archive_write *a, int type_m, int depth,
4240     struct vdd *vdd)
4241 {
4242         unsigned char *bp, *wb;
4243         struct isoent **ptbl;
4244         size_t wbremaining;
4245         int i, r, wsize;
4246
4247         if (vdd->pathtbl[depth].cnt == 0)
4248                 return (0);
4249
4250         wsize = 0;
4251         wb = wb_buffptr(a);
4252         wbremaining = wb_remaining(a);
4253         bp = wb - 1;
4254         ptbl = vdd->pathtbl[depth].sorted;
4255         for (i = 0; i < vdd->pathtbl[depth].cnt; i++) {
4256                 struct isoent *np;
4257                 size_t len;
4258
4259                 np = ptbl[i];
4260                 if (np->identifier == NULL)
4261                         len = 1; /* root directory */
4262                 else
4263                         len = np->id_len;
4264                 if (wbremaining - ((bp+1) - wb) < (len + 1 + 8)) {
4265                         r = wb_consume(a, (bp+1) - wb);
4266                         if (r < 0)
4267                                 return (r);
4268                         wb = wb_buffptr(a);
4269                         wbremaining = wb_remaining(a);
4270                         bp = wb -1;
4271                 }
4272                 /* Length of Directory Identifier */
4273                 set_num_711(bp+1, (unsigned char)len);
4274                 /* Extended Attribute Record Length */
4275                 set_num_711(bp+2, 0);
4276                 /* Location of Extent */
4277                 if (type_m)
4278                         set_num_732(bp+3, np->dir_location);
4279                 else
4280                         set_num_731(bp+3, np->dir_location);
4281                 /* Parent Directory Number */
4282                 if (type_m)
4283                         set_num_722(bp+7, np->parent->dir_number);
4284                 else
4285                         set_num_721(bp+7, np->parent->dir_number);
4286                 /* Directory Identifier */
4287                 if (np->identifier == NULL)
4288                         bp[9] = 0;
4289                 else
4290                         memcpy(&bp[9], np->identifier, len);
4291                 if (len & 0x01) {
4292                         /* Padding Field */
4293                         bp[9+len] = 0;
4294                         len++;
4295                 }
4296                 wsize += 8 + (int)len;
4297                 bp += 8 + len;
4298         }
4299         if ((bp + 1) > wb) {
4300                 r = wb_consume(a, (bp+1)-wb);
4301                 if (r < 0)
4302                         return (r);
4303         }
4304         return (wsize);
4305 }
4306
4307 static int
4308 write_path_table(struct archive_write *a, int type_m, struct vdd *vdd)
4309 {
4310         int depth, r;
4311         size_t path_table_size;
4312
4313         r = ARCHIVE_OK;
4314         path_table_size = 0;
4315         for (depth = 0; depth < vdd->max_depth; depth++) {
4316                 r = _write_path_table(a, type_m, depth, vdd);
4317                 if (r < 0)
4318                         return (r);
4319                 path_table_size += r;
4320         }
4321
4322         /* Write padding data. */
4323         path_table_size = path_table_size % PATH_TABLE_BLOCK_SIZE;
4324         if (path_table_size > 0)
4325                 r = write_null(a, PATH_TABLE_BLOCK_SIZE - path_table_size);
4326         return (r);
4327 }
4328
4329 static int
4330 calculate_directory_descriptors(struct iso9660 *iso9660, struct vdd *vdd,
4331     struct isoent *isoent, int depth)
4332 {
4333         struct isoent **enttbl;
4334         int bs, block, i;
4335
4336         block = 1;
4337         bs = get_dir_rec_size(iso9660, isoent, DIR_REC_SELF, vdd->vdd_type);
4338         bs += get_dir_rec_size(iso9660, isoent, DIR_REC_PARENT, vdd->vdd_type);
4339
4340         if (isoent->children.cnt <= 0 || (vdd->vdd_type != VDD_JOLIET &&
4341             !iso9660->opt.rr && depth + 1 >= vdd->max_depth))
4342                 return (block);
4343
4344         enttbl = isoent->children_sorted;
4345         for (i = 0; i < isoent->children.cnt; i++) {
4346                 struct isoent *np = enttbl[i];
4347                 struct isofile *file;
4348
4349                 file = np->file;
4350                 if (file->hardlink_target != NULL)
4351                         file = file->hardlink_target;
4352                 file->cur_content = &(file->content);
4353                 do {
4354                         int dr_l;
4355
4356                         dr_l = get_dir_rec_size(iso9660, np, DIR_REC_NORMAL,
4357                             vdd->vdd_type);
4358                         if ((bs + dr_l) > LOGICAL_BLOCK_SIZE) {
4359                                 block ++;
4360                                 bs = dr_l;
4361                         } else
4362                                 bs += dr_l;
4363                         file->cur_content = file->cur_content->next;
4364                 } while (file->cur_content != NULL);
4365         }
4366         return (block);
4367 }
4368
4369 static int
4370 _write_directory_descriptors(struct archive_write *a, struct vdd *vdd,
4371     struct isoent *isoent, int depth)
4372 {
4373         struct iso9660 *iso9660 = a->format_data;
4374         struct isoent **enttbl;
4375         unsigned char *p, *wb;
4376         int i, r;
4377         int dr_l;
4378
4379         p = wb = wb_buffptr(a);
4380 #define WD_REMAINING    (LOGICAL_BLOCK_SIZE - (p - wb))
4381         p += set_directory_record(p, WD_REMAINING, isoent,
4382             iso9660, DIR_REC_SELF, vdd->vdd_type);
4383         p += set_directory_record(p, WD_REMAINING, isoent,
4384             iso9660, DIR_REC_PARENT, vdd->vdd_type);
4385
4386         if (isoent->children.cnt <= 0 || (vdd->vdd_type != VDD_JOLIET &&
4387             !iso9660->opt.rr && depth + 1 >= vdd->max_depth)) {
4388                 memset(p, 0, WD_REMAINING);
4389                 return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4390         }
4391
4392         enttbl = isoent->children_sorted;
4393         for (i = 0; i < isoent->children.cnt; i++) {
4394                 struct isoent *np = enttbl[i];
4395                 struct isofile *file = np->file;
4396
4397                 if (file->hardlink_target != NULL)
4398                         file = file->hardlink_target;
4399                 file->cur_content = &(file->content);
4400                 do {
4401                         dr_l = set_directory_record(p, WD_REMAINING,
4402                             np, iso9660, DIR_REC_NORMAL,
4403                             vdd->vdd_type);
4404                         if (dr_l == 0) {
4405                                 memset(p, 0, WD_REMAINING);
4406                                 r = wb_consume(a, LOGICAL_BLOCK_SIZE);
4407                                 if (r < 0)
4408                                         return (r);
4409                                 p = wb = wb_buffptr(a);
4410                                 dr_l = set_directory_record(p,
4411                                     WD_REMAINING, np, iso9660,
4412                                     DIR_REC_NORMAL, vdd->vdd_type);
4413                         }
4414                         p += dr_l;
4415                         file->cur_content = file->cur_content->next;
4416                 } while (file->cur_content != NULL);
4417         }
4418         memset(p, 0, WD_REMAINING);
4419         return (wb_consume(a, LOGICAL_BLOCK_SIZE));
4420 }
4421
4422 static int
4423 write_directory_descriptors(struct archive_write *a, struct vdd *vdd)
4424 {
4425         struct isoent *np;
4426         int depth, r;
4427
4428         depth = 0;
4429         np = vdd->rootent;
4430         do {
4431                 struct extr_rec *extr;
4432
4433                 r = _write_directory_descriptors(a, vdd, np, depth);
4434                 if (r < 0)
4435                         return (r);
4436                 if (vdd->vdd_type != VDD_JOLIET) {
4437                         /*
4438                          * This extract record is used by SUSP,RRIP.
4439                          * Not for joliet.
4440                          */
4441                         for (extr = np->extr_rec_list.first;
4442                             extr != NULL;
4443                             extr = extr->next) {
4444                                 unsigned char *wb;
4445
4446                                 wb = wb_buffptr(a);
4447                                 memcpy(wb, extr->buf, extr->offset);
4448                                 memset(wb + extr->offset, 0,
4449                                     LOGICAL_BLOCK_SIZE - extr->offset);
4450                                 r = wb_consume(a, LOGICAL_BLOCK_SIZE);
4451                                 if (r < 0)
4452                                         return (r);
4453                         }
4454                 }
4455
4456                 if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) {
4457                         /* Enter to sub directories. */
4458                         np = np->subdirs.first;
4459                         depth++;
4460                         continue;
4461                 }
4462                 while (np != np->parent) {
4463                         if (np->drnext == NULL) {
4464                                 /* Return to the parent directory. */
4465                                 np = np->parent;
4466                                 depth--;
4467                         } else {
4468                                 np = np->drnext;
4469                                 break;
4470                         }
4471                 }
4472         } while (np != np->parent);
4473
4474         return (ARCHIVE_OK);
4475 }
4476
4477 /*
4478  * Read file contents from the temporary file, and write it.
4479  */
4480 static int
4481 write_file_contents(struct archive_write *a, int64_t offset, int64_t size)
4482 {
4483         struct iso9660 *iso9660 = a->format_data;
4484         int r;
4485
4486         lseek(iso9660->temp_fd, offset, SEEK_SET);
4487
4488         while (size) {
4489                 size_t rsize;
4490                 ssize_t rs;
4491                 unsigned char *wb;
4492
4493                 wb = wb_buffptr(a);
4494                 rsize = wb_remaining(a);
4495                 if (rsize > (size_t)size)
4496                         rsize = (size_t)size;
4497                 rs = read(iso9660->temp_fd, wb, rsize);
4498                 if (rs <= 0) {
4499                         archive_set_error(&a->archive, errno,
4500                             "Can't read temporary file(%jd)", (intmax_t)rs);
4501                         return (ARCHIVE_FATAL);
4502                 }
4503                 size -= rs;
4504                 r = wb_consume(a, rs);
4505                 if (r < 0)
4506                         return (r);
4507         }
4508         return (ARCHIVE_OK);
4509 }
4510
4511 static int
4512 write_file_descriptors(struct archive_write *a)
4513 {
4514         struct iso9660 *iso9660 = a->format_data;
4515         struct isofile *file;
4516         int64_t blocks, offset;
4517         int r;
4518
4519         blocks = 0;
4520         offset = 0;
4521
4522         /* Make the boot catalog contents, and write it. */
4523         if (iso9660->el_torito.catalog != NULL) {
4524                 r = make_boot_catalog(a);
4525                 if (r < 0)
4526                         return (r);
4527         }
4528
4529         /* Write the boot file contents. */
4530         if (iso9660->el_torito.boot != NULL) {
4531                 file = iso9660->el_torito.boot->file;
4532                 blocks = file->content.blocks;
4533                 offset = file->content.offset_of_temp;
4534                 if (offset != 0) {
4535                         r = write_file_contents(a, offset,
4536                             blocks << LOGICAL_BLOCK_BITS);
4537                         if (r < 0)
4538                                 return (r);
4539                         blocks = 0;
4540                         offset = 0;
4541                 }
4542         }
4543
4544         /* Write out all file contents. */
4545         for (file = iso9660->data_file_list.first;
4546             file != NULL; file = file->datanext) {
4547
4548                 if (!file->write_content)
4549                         continue;
4550
4551                 if ((offset + (blocks << LOGICAL_BLOCK_BITS)) <
4552                      file->content.offset_of_temp) {
4553                         if (blocks > 0) {
4554                                 r = write_file_contents(a, offset,
4555                                     blocks << LOGICAL_BLOCK_BITS);
4556                                 if (r < 0)
4557                                         return (r);
4558                         }
4559                         blocks = 0;
4560                         offset = file->content.offset_of_temp;
4561                 }
4562
4563                 file->cur_content = &(file->content);
4564                 do {
4565                         blocks += file->cur_content->blocks;
4566                         /* Next fragment */
4567                         file->cur_content = file->cur_content->next;
4568                 } while (file->cur_content != NULL);
4569         }
4570
4571         /* Flush out remaining blocks. */
4572         if (blocks > 0) {
4573                 r = write_file_contents(a, offset,
4574                     blocks << LOGICAL_BLOCK_BITS);
4575                 if (r < 0)
4576                         return (r);
4577         }
4578
4579         return (ARCHIVE_OK);
4580 }
4581
4582 static void
4583 isofile_init_entry_list(struct iso9660 *iso9660)
4584 {
4585         iso9660->all_file_list.first = NULL;
4586         iso9660->all_file_list.last = &(iso9660->all_file_list.first);
4587 }
4588
4589 static void
4590 isofile_add_entry(struct iso9660 *iso9660, struct isofile *file)
4591 {
4592         file->allnext = NULL;
4593         *iso9660->all_file_list.last = file;
4594         iso9660->all_file_list.last = &(file->allnext);
4595 }
4596
4597 static void
4598 isofile_free_all_entries(struct iso9660 *iso9660)
4599 {
4600         struct isofile *file, *file_next;
4601
4602         file = iso9660->all_file_list.first;
4603         while (file != NULL) {
4604                 file_next = file->allnext;
4605                 isofile_free(file);
4606                 file = file_next;
4607         }
4608 }
4609
4610 static void
4611 isofile_init_entry_data_file_list(struct iso9660 *iso9660)
4612 {
4613         iso9660->data_file_list.first = NULL;
4614         iso9660->data_file_list.last = &(iso9660->data_file_list.first);
4615 }
4616
4617 static void
4618 isofile_add_data_file(struct iso9660 *iso9660, struct isofile *file)
4619 {
4620         file->datanext = NULL;
4621         *iso9660->data_file_list.last = file;
4622         iso9660->data_file_list.last = &(file->datanext);
4623 }
4624
4625
4626 static struct isofile *
4627 isofile_new(struct archive_write *a, struct archive_entry *entry)
4628 {
4629         struct isofile *file;
4630
4631         file = calloc(1, sizeof(*file));
4632         if (file == NULL)
4633                 return (NULL);
4634
4635         if (entry != NULL)
4636                 file->entry = archive_entry_clone(entry);
4637         else
4638                 file->entry = archive_entry_new2(&a->archive);
4639         if (file->entry == NULL) {
4640                 free(file);
4641                 return (NULL);
4642         }
4643         archive_string_init(&(file->parentdir));
4644         archive_string_init(&(file->basename));
4645         archive_string_init(&(file->basename_utf16));
4646         archive_string_init(&(file->symlink));
4647         file->cur_content = &(file->content);
4648
4649         return (file);
4650 }
4651
4652 static void
4653 isofile_free(struct isofile *file)
4654 {
4655         struct content *con, *tmp;
4656
4657         con = file->content.next;
4658         while (con != NULL) {
4659                 tmp = con;
4660                 con = con->next;
4661                 free(tmp);
4662         }
4663         archive_entry_free(file->entry);
4664         archive_string_free(&(file->parentdir));
4665         archive_string_free(&(file->basename));
4666         archive_string_free(&(file->basename_utf16));
4667         archive_string_free(&(file->symlink));
4668         free(file);
4669 }
4670
4671 #if defined(_WIN32) || defined(__CYGWIN__)
4672 static int
4673 cleanup_backslash_1(char *p)
4674 {
4675         int mb, dos;
4676
4677         mb = dos = 0;
4678         while (*p) {
4679                 if (*(unsigned char *)p > 127)
4680                         mb = 1;
4681                 if (*p == '\\') {
4682                         /* If we have not met any multi-byte characters,
4683                          * we can replace '\' with '/'. */
4684                         if (!mb)
4685                                 *p = '/';
4686                         dos = 1;
4687                 }
4688                 p++;
4689         }
4690         if (!mb || !dos)
4691                 return (0);
4692         return (-1);
4693 }
4694
4695 static void
4696 cleanup_backslash_2(wchar_t *p)
4697 {
4698
4699         /* Convert a path-separator from '\' to  '/' */
4700         while (*p != L'\0') {
4701                 if (*p == L'\\')
4702                         *p = L'/';
4703                 p++;
4704         }
4705 }
4706 #endif
4707
4708 /*
4709  * Generate a parent directory name and a base name from a pathname.
4710  */
4711 static int
4712 isofile_gen_utility_names(struct archive_write *a, struct isofile *file)
4713 {
4714         struct iso9660 *iso9660;
4715         const char *pathname;
4716         char *p, *dirname, *slash;
4717         size_t len;
4718         int ret = ARCHIVE_OK;
4719
4720         iso9660 = a->format_data;
4721
4722         archive_string_empty(&(file->parentdir));
4723         archive_string_empty(&(file->basename));
4724         archive_string_empty(&(file->basename_utf16));
4725         archive_string_empty(&(file->symlink));
4726
4727         pathname =  archive_entry_pathname(file->entry);
4728         if (pathname == NULL || pathname[0] == '\0') {/* virtual root */
4729                 file->dircnt = 0;
4730                 return (ret);
4731         }
4732
4733         /*
4734          * Make a UTF-16BE basename if Joliet extension enabled.
4735          */
4736         if (iso9660->opt.joliet) {
4737                 const char *u16, *ulast;
4738                 size_t u16len, ulen_last;
4739
4740                 if (iso9660->sconv_to_utf16be == NULL) {
4741                         iso9660->sconv_to_utf16be =
4742                             archive_string_conversion_to_charset(
4743                                 &(a->archive), "UTF-16BE", 1);
4744                         if (iso9660->sconv_to_utf16be == NULL)
4745                                 /* Couldn't allocate memory */
4746                                 return (ARCHIVE_FATAL);
4747                         iso9660->sconv_from_utf16be =
4748                             archive_string_conversion_from_charset(
4749                                 &(a->archive), "UTF-16BE", 1);
4750                         if (iso9660->sconv_from_utf16be == NULL)
4751                                 /* Couldn't allocate memory */
4752                                 return (ARCHIVE_FATAL);
4753                 }
4754
4755                 /*
4756                  * Convert a filename to UTF-16BE.
4757                  */
4758                 if (0 > archive_entry_pathname_l(file->entry, &u16, &u16len,
4759                     iso9660->sconv_to_utf16be)) {
4760                         if (errno == ENOMEM) {
4761                                 archive_set_error(&a->archive, ENOMEM,
4762                                     "Can't allocate memory for UTF-16BE");
4763                                 return (ARCHIVE_FATAL);
4764                         }
4765                         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
4766                             "A filename cannot be converted to UTF-16BE;"
4767                             "You should disable making Joliet extension");
4768                         ret = ARCHIVE_WARN;
4769                 }
4770
4771                 /*
4772                  * Make sure a path separator is not in the last;
4773                  * Remove trailing '/'.
4774                  */
4775                 while (u16len >= 2) {
4776 #if defined(_WIN32) || defined(__CYGWIN__)
4777                         if (u16[u16len-2] == 0 &&
4778                             (u16[u16len-1] == '/' || u16[u16len-1] == '\\'))
4779 #else
4780                         if (u16[u16len-2] == 0 && u16[u16len-1] == '/')
4781 #endif
4782                         {
4783                                 u16len -= 2;
4784                         } else
4785                                 break;
4786                 }
4787
4788                 /*
4789                  * Find a basename in UTF-16BE.
4790                  */
4791                 ulast = u16;
4792                 u16len >>= 1;
4793                 ulen_last = u16len;
4794                 while (u16len > 0) {
4795 #if defined(_WIN32) || defined(__CYGWIN__)
4796                         if (u16[0] == 0 && (u16[1] == '/' || u16[1] == '\\'))
4797 #else
4798                         if (u16[0] == 0 && u16[1] == '/')
4799 #endif
4800                         {
4801                                 ulast = u16 + 2;
4802                                 ulen_last = u16len -1;
4803                         }
4804                         u16 += 2;
4805                         u16len --;
4806                 }
4807                 ulen_last <<= 1;
4808                 if (archive_string_ensure(&(file->basename_utf16),
4809                     ulen_last) == NULL) {
4810                         archive_set_error(&a->archive, ENOMEM,
4811                             "Can't allocate memory for UTF-16BE");
4812                         return (ARCHIVE_FATAL);
4813                 }
4814
4815                 /*
4816                  * Set UTF-16BE basename.
4817                  */
4818                 memcpy(file->basename_utf16.s, ulast, ulen_last);
4819                 file->basename_utf16.length = ulen_last;
4820         }
4821
4822         archive_strcpy(&(file->parentdir), pathname);
4823 #if defined(_WIN32) || defined(__CYGWIN__)
4824         /*
4825          * Convert a path-separator from '\' to  '/'
4826          */
4827         if (cleanup_backslash_1(file->parentdir.s) != 0) {
4828                 const wchar_t *wp = archive_entry_pathname_w(file->entry);
4829                 struct archive_wstring ws;
4830
4831                 if (wp != NULL) {
4832                         int r;
4833                         archive_string_init(&ws);
4834                         archive_wstrcpy(&ws, wp);
4835                         cleanup_backslash_2(ws.s);
4836                         archive_string_empty(&(file->parentdir));
4837                         r = archive_string_append_from_wcs(&(file->parentdir),
4838                             ws.s, ws.length);
4839                         archive_wstring_free(&ws);
4840                         if (r < 0 && errno == ENOMEM) {
4841                                 archive_set_error(&a->archive, ENOMEM,
4842                                     "Can't allocate memory");
4843                                 return (ARCHIVE_FATAL);
4844                         }
4845                 }
4846         }
4847 #endif
4848
4849         len = file->parentdir.length;
4850         p = dirname = file->parentdir.s;
4851
4852         /*
4853          * Remove leading '/', '../' and './' elements
4854          */
4855         while (*p) {
4856                 if (p[0] == '/') {
4857                         p++;
4858                         len--;
4859                 } else if (p[0] != '.')
4860                         break;
4861                 else if (p[1] == '.' && p[2] == '/') {
4862                         p += 3;
4863                         len -= 3;
4864                 } else if (p[1] == '/' || (p[1] == '.' && p[2] == '\0')) {
4865                         p += 2;
4866                         len -= 2;
4867                 } else if (p[1] == '\0') {
4868                         p++;
4869                         len--;
4870                 } else
4871                         break;
4872         }
4873         if (p != dirname) {
4874                 memmove(dirname, p, len+1);
4875                 p = dirname;
4876         }
4877         /*
4878          * Remove "/","/." and "/.." elements from tail.
4879          */
4880         while (len > 0) {
4881                 size_t ll = len;
4882
4883                 if (len > 0 && p[len-1] == '/') {
4884                         p[len-1] = '\0';
4885                         len--;
4886                 }
4887                 if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
4888                         p[len-2] = '\0';
4889                         len -= 2;
4890                 }
4891                 if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
4892                     p[len-1] == '.') {
4893                         p[len-3] = '\0';
4894                         len -= 3;
4895                 }
4896                 if (ll == len)
4897                         break;
4898         }
4899         while (*p) {
4900                 if (p[0] == '/') {
4901                         if (p[1] == '/')
4902                                 /* Convert '//' --> '/' */
4903                                 strcpy(p, p+1);
4904                         else if (p[1] == '.' && p[2] == '/')
4905                                 /* Convert '/./' --> '/' */
4906                                 strcpy(p, p+2);
4907                         else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
4908                                 /* Convert 'dir/dir1/../dir2/'
4909                                  *     --> 'dir/dir2/'
4910                                  */
4911                                 char *rp = p -1;
4912                                 while (rp >= dirname) {
4913                                         if (*rp == '/')
4914                                                 break;
4915                                         --rp;
4916                                 }
4917                                 if (rp > dirname) {
4918                                         strcpy(rp, p+3);
4919                                         p = rp;
4920                                 } else {
4921                                         strcpy(dirname, p+4);
4922                                         p = dirname;
4923                                 }
4924                         } else
4925                                 p++;
4926                 } else
4927                         p++;
4928         }
4929         p = dirname;
4930         len = strlen(p);
4931
4932         if (archive_entry_filetype(file->entry) == AE_IFLNK) {
4933                 /* Convert symlink name too. */
4934                 pathname = archive_entry_symlink(file->entry);
4935                 archive_strcpy(&(file->symlink),  pathname);
4936 #if defined(_WIN32) || defined(__CYGWIN__)
4937                 /*
4938                  * Convert a path-separator from '\' to  '/'
4939                  */
4940                 if (archive_strlen(&(file->symlink)) > 0 &&
4941                     cleanup_backslash_1(file->symlink.s) != 0) {
4942                         const wchar_t *wp =
4943                             archive_entry_symlink_w(file->entry);
4944                         struct archive_wstring ws;
4945
4946                         if (wp != NULL) {
4947                                 int r;
4948                                 archive_string_init(&ws);
4949                                 archive_wstrcpy(&ws, wp);
4950                                 cleanup_backslash_2(ws.s);
4951                                 archive_string_empty(&(file->symlink));
4952                                 r = archive_string_append_from_wcs(
4953                                     &(file->symlink),
4954                                     ws.s, ws.length);
4955                                 archive_wstring_free(&ws);
4956                                 if (r < 0 && errno == ENOMEM) {
4957                                         archive_set_error(&a->archive, ENOMEM,
4958                                             "Can't allocate memory");
4959                                         return (ARCHIVE_FATAL);
4960                                 }
4961                         }
4962                 }
4963 #endif
4964         }
4965         /*
4966          * - Count up directory elements.
4967          * - Find out the position which points the last position of
4968          *   path separator('/').
4969          */
4970         slash = NULL;
4971         file->dircnt = 0;
4972         for (; *p != '\0'; p++)
4973                 if (*p == '/') {
4974                         slash = p;
4975                         file->dircnt++;
4976                 }
4977         if (slash == NULL) {
4978                 /* The pathname doesn't have a parent directory. */
4979                 file->parentdir.length = len;
4980                 archive_string_copy(&(file->basename), &(file->parentdir));
4981                 archive_string_empty(&(file->parentdir));
4982                 *file->parentdir.s = '\0';
4983                 return (ret);
4984         }
4985
4986         /* Make a basename from dirname and slash */
4987         *slash  = '\0';
4988         file->parentdir.length = slash - dirname;
4989         archive_strcpy(&(file->basename),  slash + 1);
4990         if (archive_entry_filetype(file->entry) == AE_IFDIR)
4991                 file->dircnt ++;
4992         return (ret);
4993 }
4994
4995 /*
4996  * Register a entry to get a hardlink target.
4997  */
4998 static int
4999 isofile_register_hardlink(struct archive_write *a, struct isofile *file)
5000 {
5001         struct iso9660 *iso9660 = a->format_data;
5002         struct hardlink *hl;
5003         const char *pathname;
5004
5005         archive_entry_set_nlink(file->entry, 1);
5006         pathname = archive_entry_hardlink(file->entry);
5007         if (pathname == NULL) {
5008                 /* This `file` is a hardlink target. */
5009                 hl = malloc(sizeof(*hl));
5010                 if (hl == NULL) {
5011                         archive_set_error(&a->archive, ENOMEM,
5012                             "Can't allocate memory");
5013                         return (ARCHIVE_FATAL);
5014                 }
5015                 hl->nlink = 1;
5016                 /* A hardlink target must be the first position. */
5017                 file->hlnext = NULL;
5018                 hl->file_list.first = file;
5019                 hl->file_list.last = &(file->hlnext);
5020                 __archive_rb_tree_insert_node(&(iso9660->hardlink_rbtree),
5021                     (struct archive_rb_node *)hl);
5022         } else {
5023                 hl = (struct hardlink *)__archive_rb_tree_find_node(
5024                     &(iso9660->hardlink_rbtree), pathname);
5025                 if (hl != NULL) {
5026                         /* Insert `file` entry into the tail. */
5027                         file->hlnext = NULL;
5028                         *hl->file_list.last = file;
5029                         hl->file_list.last = &(file->hlnext);
5030                         hl->nlink++;
5031                 }
5032                 archive_entry_unset_size(file->entry);
5033         }
5034
5035         return (ARCHIVE_OK);
5036 }
5037
5038 /*
5039  * Hardlinked files have to have the same location of extent.
5040  * We have to find out hardlink target entries for the entries
5041  * which have a hardlink target name.
5042  */
5043 static void
5044 isofile_connect_hardlink_files(struct iso9660 *iso9660)
5045 {
5046         struct archive_rb_node *n;
5047         struct hardlink *hl;
5048         struct isofile *target, *nf;
5049
5050         ARCHIVE_RB_TREE_FOREACH(n, &(iso9660->hardlink_rbtree)) {
5051                 hl = (struct hardlink *)n;
5052
5053                 /* The first entry must be a hardlink target. */
5054                 target = hl->file_list.first;
5055                 archive_entry_set_nlink(target->entry, hl->nlink);
5056                 /* Set a hardlink target to reference entries. */
5057                 for (nf = target->hlnext;
5058                     nf != NULL; nf = nf->hlnext) {
5059                         nf->hardlink_target = target;
5060                         archive_entry_set_nlink(nf->entry, hl->nlink);
5061                 }
5062         }
5063 }
5064
5065 static int
5066 isofile_hd_cmp_node(const struct archive_rb_node *n1,
5067     const struct archive_rb_node *n2)
5068 {
5069         const struct hardlink *h1 = (const struct hardlink *)n1;
5070         const struct hardlink *h2 = (const struct hardlink *)n2;
5071
5072         return (strcmp(archive_entry_pathname(h1->file_list.first->entry),
5073                        archive_entry_pathname(h2->file_list.first->entry)));
5074 }
5075
5076 static int
5077 isofile_hd_cmp_key(const struct archive_rb_node *n, const void *key)
5078 {
5079         const struct hardlink *h = (const struct hardlink *)n;
5080
5081         return (strcmp(archive_entry_pathname(h->file_list.first->entry),
5082                        (const char *)key));
5083 }
5084
5085 static void
5086 isofile_init_hardlinks(struct iso9660 *iso9660)
5087 {
5088         static const struct archive_rb_tree_ops rb_ops = {
5089                 isofile_hd_cmp_node, isofile_hd_cmp_key,
5090         };
5091
5092         __archive_rb_tree_init(&(iso9660->hardlink_rbtree), &rb_ops);
5093 }
5094
5095 static void
5096 isofile_free_hardlinks(struct iso9660 *iso9660)
5097 {
5098         struct archive_rb_node *n, *tmp;
5099
5100         ARCHIVE_RB_TREE_FOREACH_SAFE(n, &(iso9660->hardlink_rbtree), tmp) {
5101                 __archive_rb_tree_remove_node(&(iso9660->hardlink_rbtree), n);
5102                 free(n);
5103         }
5104 }
5105
5106 static struct isoent *
5107 isoent_new(struct isofile *file)
5108 {
5109         struct isoent *isoent;
5110         static const struct archive_rb_tree_ops rb_ops = {
5111                 isoent_cmp_node, isoent_cmp_key,
5112         };
5113
5114         isoent = calloc(1, sizeof(*isoent));
5115         if (isoent == NULL)
5116                 return (NULL);
5117         isoent->file = file;
5118         isoent->children.first = NULL;
5119         isoent->children.last = &(isoent->children.first);
5120         __archive_rb_tree_init(&(isoent->rbtree), &rb_ops);
5121         isoent->subdirs.first = NULL;
5122         isoent->subdirs.last = &(isoent->subdirs.first);
5123         isoent->extr_rec_list.first = NULL;
5124         isoent->extr_rec_list.last = &(isoent->extr_rec_list.first);
5125         isoent->extr_rec_list.current = NULL;
5126         if (archive_entry_filetype(file->entry) == AE_IFDIR)
5127                 isoent->dir = 1;
5128
5129         return (isoent);
5130 }
5131
5132 static inline struct isoent *
5133 isoent_clone(struct isoent *src)
5134 {
5135         return (isoent_new(src->file));
5136 }
5137
5138 static void
5139 _isoent_free(struct isoent *isoent)
5140 {
5141         struct extr_rec *er, *er_next;
5142
5143         free(isoent->children_sorted);
5144         free(isoent->identifier);
5145         er = isoent->extr_rec_list.first;
5146         while (er != NULL) {
5147                 er_next = er->next;
5148                 free(er);
5149                 er = er_next;
5150         }
5151         free(isoent);
5152 }
5153
5154 static void
5155 isoent_free_all(struct isoent *isoent)
5156 {
5157         struct isoent *np, *np_temp;
5158
5159         if (isoent == NULL)
5160                 return;
5161         np = isoent;
5162         for (;;) {
5163                 if (np->dir) {
5164                         if (np->children.first != NULL) {
5165                                 /* Enter to sub directories. */
5166                                 np = np->children.first;
5167                                 continue;
5168                         }
5169                 }
5170                 for (;;) {
5171                         np_temp = np;
5172                         if (np->chnext == NULL) {
5173                                 /* Return to the parent directory. */
5174                                 np = np->parent;
5175                                 _isoent_free(np_temp);
5176                                 if (np == np_temp)
5177                                         return;
5178                         } else {
5179                                 np = np->chnext;
5180                                 _isoent_free(np_temp);
5181                                 break;
5182                         }
5183                 }
5184         }
5185 }
5186
5187 static struct isoent *
5188 isoent_create_virtual_dir(struct archive_write *a, struct iso9660 *iso9660, const char *pathname)
5189 {
5190         struct isofile *file;
5191         struct isoent *isoent;
5192
5193         file = isofile_new(a, NULL);
5194         if (file == NULL)
5195                 return (NULL);
5196         archive_entry_set_pathname(file->entry, pathname);
5197         archive_entry_unset_mtime(file->entry);
5198         archive_entry_unset_atime(file->entry);
5199         archive_entry_unset_ctime(file->entry);
5200         archive_entry_set_uid(file->entry, getuid());
5201         archive_entry_set_gid(file->entry, getgid());
5202         archive_entry_set_mode(file->entry, 0555 | AE_IFDIR);
5203         archive_entry_set_nlink(file->entry, 2);
5204         if (isofile_gen_utility_names(a, file) < ARCHIVE_WARN) {
5205                 isofile_free(file);
5206                 return (NULL);
5207         }
5208         isofile_add_entry(iso9660, file);
5209
5210         isoent = isoent_new(file);
5211         if (isoent == NULL)
5212                 return (NULL);
5213         isoent->dir = 1;
5214         isoent->virtual = 1;
5215
5216         return (isoent);
5217 }
5218
5219 static int
5220 isoent_cmp_node(const struct archive_rb_node *n1,
5221     const struct archive_rb_node *n2)
5222 {
5223         const struct isoent *e1 = (const struct isoent *)n1;
5224         const struct isoent *e2 = (const struct isoent *)n2;
5225
5226         return (strcmp(e1->file->basename.s, e2->file->basename.s));
5227 }
5228
5229 static int
5230 isoent_cmp_key(const struct archive_rb_node *n, const void *key)
5231 {
5232         const struct isoent *e = (const struct isoent *)n;
5233
5234         return (strcmp(e->file->basename.s, (const char *)key));
5235 }
5236
5237 static int
5238 isoent_add_child_head(struct isoent *parent, struct isoent *child)
5239 {
5240
5241         if (!__archive_rb_tree_insert_node(
5242             &(parent->rbtree), (struct archive_rb_node *)child))
5243                 return (0);
5244         if ((child->chnext = parent->children.first) == NULL)
5245                 parent->children.last = &(child->chnext);
5246         parent->children.first = child;
5247         parent->children.cnt++;
5248         child->parent = parent;
5249
5250         /* Add a child to a sub-directory chain */
5251         if (child->dir) {
5252                 if ((child->drnext = parent->subdirs.first) == NULL)
5253                         parent->subdirs.last = &(child->drnext);
5254                 parent->subdirs.first = child;
5255                 parent->subdirs.cnt++;
5256                 child->parent = parent;
5257         } else
5258                 child->drnext = NULL;
5259         return (1);
5260 }
5261
5262 static int
5263 isoent_add_child_tail(struct isoent *parent, struct isoent *child)
5264 {
5265
5266         if (!__archive_rb_tree_insert_node(
5267             &(parent->rbtree), (struct archive_rb_node *)child))
5268                 return (0);
5269         child->chnext = NULL;
5270         *parent->children.last = child;
5271         parent->children.last = &(child->chnext);
5272         parent->children.cnt++;
5273         child->parent = parent;
5274
5275         /* Add a child to a sub-directory chain */
5276         child->drnext = NULL;
5277         if (child->dir) {
5278                 *parent->subdirs.last = child;
5279                 parent->subdirs.last = &(child->drnext);
5280                 parent->subdirs.cnt++;
5281                 child->parent = parent;
5282         }
5283         return (1);
5284 }
5285
5286 static void
5287 isoent_remove_child(struct isoent *parent, struct isoent *child)
5288 {
5289         struct isoent *ent;
5290
5291         /* Remove a child entry from children chain. */
5292         ent = parent->children.first;
5293         while (ent->chnext != child)
5294                 ent = ent->chnext;
5295         if ((ent->chnext = ent->chnext->chnext) == NULL)
5296                 parent->children.last = &(ent->chnext);
5297         parent->children.cnt--;
5298
5299         if (child->dir) {
5300                 /* Remove a child entry from sub-directory chain. */
5301                 ent = parent->subdirs.first;
5302                 while (ent->drnext != child)
5303                         ent = ent->drnext;
5304                 if ((ent->drnext = ent->drnext->drnext) == NULL)
5305                         parent->subdirs.last = &(ent->drnext);
5306                 parent->subdirs.cnt--;
5307         }
5308
5309         __archive_rb_tree_remove_node(&(parent->rbtree),
5310             (struct archive_rb_node *)child);
5311 }
5312
5313 static int
5314 isoent_clone_tree(struct archive_write *a, struct isoent **nroot,
5315     struct isoent *root)
5316 {
5317         struct isoent *np, *xroot, *newent;
5318
5319         np = root;
5320         xroot = NULL;
5321         do {
5322                 newent = isoent_clone(np);
5323                 if (newent == NULL) {
5324                         archive_set_error(&a->archive, ENOMEM,
5325                             "Can't allocate memory");
5326                         return (ARCHIVE_FATAL);
5327                 }
5328                 if (xroot == NULL) {
5329                         *nroot = xroot = newent;
5330                         newent->parent = xroot;
5331                 } else
5332                         isoent_add_child_tail(xroot, newent);
5333                 if (np->dir && np->children.first != NULL) {
5334                         /* Enter to sub directories. */
5335                         np = np->children.first;
5336                         xroot = newent;
5337                         continue;
5338                 }
5339                 while (np != np->parent) {
5340                         if (np->chnext == NULL) {
5341                                 /* Return to the parent directory. */
5342                                 np = np->parent;
5343                                 xroot = xroot->parent;
5344                         } else {
5345                                 np = np->chnext;
5346                                 break;
5347                         }
5348                 }
5349         } while (np != np->parent);
5350
5351         return (ARCHIVE_OK);
5352 }
5353
5354 /*
5355  * Setup directory locations.
5356  */
5357 static void
5358 isoent_setup_directory_location(struct iso9660 *iso9660, int location,
5359     struct vdd *vdd)
5360 {
5361         struct isoent *np;
5362         int depth;
5363
5364         vdd->total_dir_block = 0;
5365         depth = 0;
5366         np = vdd->rootent;
5367         do {
5368                 int block;
5369
5370                 np->dir_block = calculate_directory_descriptors(
5371                     iso9660, vdd, np, depth);
5372                 vdd->total_dir_block += np->dir_block;
5373                 np->dir_location = location;
5374                 location += np->dir_block;
5375                 block = extra_setup_location(np, location);
5376                 vdd->total_dir_block += block;
5377                 location += block;
5378
5379                 if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) {
5380                         /* Enter to sub directories. */
5381                         np = np->subdirs.first;
5382                         depth++;
5383                         continue;
5384                 }
5385                 while (np != np->parent) {
5386                         if (np->drnext == NULL) {
5387                                 /* Return to the parent directory. */
5388                                 np = np->parent;
5389                                 depth--;
5390                         } else {
5391                                 np = np->drnext;
5392                                 break;
5393                         }
5394                 }
5395         } while (np != np->parent);
5396 }
5397
5398 static void
5399 _isoent_file_location(struct iso9660 *iso9660, struct isoent *isoent,
5400     int *symlocation)
5401 {
5402         struct isoent **children;
5403         int n;
5404
5405         if (isoent->children.cnt == 0)
5406                 return;
5407
5408         children = isoent->children_sorted;
5409         for (n = 0; n < isoent->children.cnt; n++) {
5410                 struct isoent *np;
5411                 struct isofile *file;
5412
5413                 np = children[n];
5414                 if (np->dir)
5415                         continue;
5416                 if (np == iso9660->el_torito.boot)
5417                         continue;
5418                 file = np->file;
5419                 if (file->boot || file->hardlink_target != NULL)
5420                         continue;
5421                 if (archive_entry_filetype(file->entry) == AE_IFLNK ||
5422                     file->content.size == 0) {
5423                         /*
5424                          * Do not point a valid location.
5425                          * Make sure entry is not hardlink file.
5426                          */
5427                         file->content.location = (*symlocation)--;
5428                         continue;
5429                 }
5430
5431                 file->write_content = 1;
5432         }
5433 }
5434
5435 /*
5436  * Setup file locations.
5437  */
5438 static void
5439 isoent_setup_file_location(struct iso9660 *iso9660, int location)
5440 {
5441         struct isoent *isoent;
5442         struct isoent *np;
5443         struct isofile *file;
5444         size_t size;
5445         int block;
5446         int depth;
5447         int joliet;
5448         int symlocation;
5449         int total_block;
5450
5451         iso9660->total_file_block = 0;
5452         if ((isoent = iso9660->el_torito.catalog) != NULL) {
5453                 isoent->file->content.location = location;
5454                 block = (int)((archive_entry_size(isoent->file->entry) +
5455                     LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS);
5456                 location += block;
5457                 iso9660->total_file_block += block;
5458         }
5459         if ((isoent = iso9660->el_torito.boot) != NULL) {
5460                 isoent->file->content.location = location;
5461                 size = fd_boot_image_size(iso9660->el_torito.media_type);
5462                 if (size == 0)
5463                         size = (size_t)archive_entry_size(isoent->file->entry);
5464                 block = ((int)size + LOGICAL_BLOCK_SIZE -1)
5465                     >> LOGICAL_BLOCK_BITS;
5466                 location += block;
5467                 iso9660->total_file_block += block;
5468                 isoent->file->content.blocks = block;
5469         }
5470
5471         depth = 0;
5472         symlocation = -16;
5473         if (!iso9660->opt.rr && iso9660->opt.joliet) {
5474                 joliet = 1;
5475                 np = iso9660->joliet.rootent;
5476         } else {
5477                 joliet = 0;
5478                 np = iso9660->primary.rootent;
5479         }
5480         do {
5481                 _isoent_file_location(iso9660, np, &symlocation);
5482
5483                 if (np->subdirs.first != NULL &&
5484                     (joliet ||
5485                     ((iso9660->opt.rr == OPT_RR_DISABLED &&
5486                       depth + 2 < iso9660->primary.max_depth) ||
5487                      (iso9660->opt.rr &&
5488                       depth + 1 < iso9660->primary.max_depth)))) {
5489                         /* Enter to sub directories. */
5490                         np = np->subdirs.first;
5491                         depth++;
5492                         continue;
5493                 }
5494                 while (np != np->parent) {
5495                         if (np->drnext == NULL) {
5496                                 /* Return to the parent directory. */
5497                                 np = np->parent;
5498                                 depth--;
5499                         } else {
5500                                 np = np->drnext;
5501                                 break;
5502                         }
5503                 }
5504         } while (np != np->parent);
5505
5506         total_block = 0;
5507         for (file = iso9660->data_file_list.first;
5508             file != NULL; file = file->datanext) {
5509
5510                 if (!file->write_content)
5511                         continue;
5512
5513                 file->cur_content = &(file->content);
5514                 do {
5515                         file->cur_content->location = location;
5516                         location += file->cur_content->blocks;
5517                         total_block += file->cur_content->blocks;
5518                         /* Next fragment */
5519                         file->cur_content = file->cur_content->next;
5520                 } while (file->cur_content != NULL);
5521         }
5522         iso9660->total_file_block += total_block;
5523 }
5524
5525 static int
5526 get_path_component(char *name, size_t n, const char *fn)
5527 {
5528         char *p;
5529         size_t l;
5530
5531         p = strchr(fn, '/');
5532         if (p == NULL) {
5533                 if ((l = strlen(fn)) == 0)
5534                         return (0);
5535         } else
5536                 l = p - fn;
5537         if (l > n -1)
5538                 return (-1);
5539         memcpy(name, fn, l);
5540         name[l] = '\0';
5541
5542         return ((int)l);
5543 }
5544
5545 /*
5546  * Add a new entry into the tree.
5547  */
5548 static int
5549 isoent_tree(struct archive_write *a, struct isoent **isoentpp)
5550 {
5551 #if defined(_WIN32) && !defined(__CYGWIN__)
5552         char name[_MAX_FNAME];/* Included null terminator size. */
5553 #elif defined(NAME_MAX) && NAME_MAX >= 255
5554         char name[NAME_MAX+1];
5555 #else
5556         char name[256];
5557 #endif
5558         struct iso9660 *iso9660 = a->format_data;
5559         struct isoent *dent, *isoent, *np;
5560         struct isofile *f1, *f2;
5561         const char *fn, *p;
5562         int l;
5563
5564         isoent = *isoentpp;
5565         dent = iso9660->primary.rootent;
5566         if (isoent->file->parentdir.length > 0)
5567                 fn = p = isoent->file->parentdir.s;
5568         else
5569                 fn = p = "";
5570
5571         /*
5572          * If the path of the parent directory of `isoent' entry is
5573          * the same as the path of `cur_dirent', add isoent to
5574          * `cur_dirent'.
5575          */
5576         if (archive_strlen(&(iso9660->cur_dirstr))
5577               == archive_strlen(&(isoent->file->parentdir)) &&
5578             strcmp(iso9660->cur_dirstr.s, fn) == 0) {
5579                 if (!isoent_add_child_tail(iso9660->cur_dirent, isoent)) {
5580                         np = (struct isoent *)__archive_rb_tree_find_node(
5581                             &(iso9660->cur_dirent->rbtree),
5582                             isoent->file->basename.s);
5583                         goto same_entry;
5584                 }
5585                 return (ARCHIVE_OK);
5586         }
5587
5588         for (;;) {
5589                 l = get_path_component(name, sizeof(name), fn);
5590                 if (l == 0) {
5591                         np = NULL;
5592                         break;
5593                 }
5594                 if (l < 0) {
5595                         archive_set_error(&a->archive,
5596                             ARCHIVE_ERRNO_MISC,
5597                             "A name buffer is too small");
5598                         _isoent_free(isoent);
5599                         return (ARCHIVE_FATAL);
5600                 }
5601
5602                 np = isoent_find_child(dent, name);
5603                 if (np == NULL || fn[0] == '\0')
5604                         break;
5605
5606                 /* Find next subdirectory. */
5607                 if (!np->dir) {
5608                         /* NOT Directory! */
5609                         archive_set_error(&a->archive,
5610                             ARCHIVE_ERRNO_MISC,
5611                             "`%s' is not directory, we cannot insert `%s' ",
5612                             archive_entry_pathname(np->file->entry),
5613                             archive_entry_pathname(isoent->file->entry));
5614                         _isoent_free(isoent);
5615                         *isoentpp = NULL;
5616                         return (ARCHIVE_FAILED);
5617                 }
5618                 fn += l;
5619                 if (fn[0] == '/')
5620                         fn++;
5621                 dent = np;
5622         }
5623         if (np == NULL) {
5624                 /*
5625                  * Create virtual parent directories.
5626                  */
5627                 while (fn[0] != '\0') {
5628                         struct isoent *vp;
5629                         struct archive_string as;
5630
5631                         archive_string_init(&as);
5632                         archive_strncat(&as, p, fn - p + l);
5633                         if (as.s[as.length-1] == '/') {
5634                                 as.s[as.length-1] = '\0';
5635                                 as.length--;
5636                         }
5637                         vp = isoent_create_virtual_dir(a, iso9660, as.s);
5638                         if (vp == NULL) {
5639                                 archive_string_free(&as);
5640                                 archive_set_error(&a->archive, ENOMEM,
5641                                     "Can't allocate memory");
5642                                 _isoent_free(isoent);
5643                                 *isoentpp = NULL;
5644                                 return (ARCHIVE_FATAL);
5645                         }
5646                         archive_string_free(&as);
5647
5648                         if (vp->file->dircnt > iso9660->dircnt_max)
5649                                 iso9660->dircnt_max = vp->file->dircnt;
5650                         isoent_add_child_tail(dent, vp);
5651                         np = vp;
5652
5653                         fn += l;
5654                         if (fn[0] == '/')
5655                                 fn++;
5656                         l = get_path_component(name, sizeof(name), fn);
5657                         if (l < 0) {
5658                                 archive_string_free(&as);
5659                                 archive_set_error(&a->archive,
5660                                     ARCHIVE_ERRNO_MISC,
5661                                     "A name buffer is too small");
5662                                 _isoent_free(isoent);
5663                                 *isoentpp = NULL;
5664                                 return (ARCHIVE_FATAL);
5665                         }
5666                         dent = np;
5667                 }
5668
5669                 /* Found out the parent directory where isoent can be
5670                  * inserted. */
5671                 iso9660->cur_dirent = dent;
5672                 archive_string_empty(&(iso9660->cur_dirstr));
5673                 archive_string_ensure(&(iso9660->cur_dirstr),
5674                     archive_strlen(&(dent->file->parentdir)) +
5675                     archive_strlen(&(dent->file->basename)) + 2);
5676                 if (archive_strlen(&(dent->file->parentdir)) +
5677                     archive_strlen(&(dent->file->basename)) == 0)
5678                         iso9660->cur_dirstr.s[0] = 0;
5679                 else {
5680                         if (archive_strlen(&(dent->file->parentdir)) > 0) {
5681                                 archive_string_copy(&(iso9660->cur_dirstr),
5682                                     &(dent->file->parentdir));
5683                                 archive_strappend_char(&(iso9660->cur_dirstr), '/');
5684                         }
5685                         archive_string_concat(&(iso9660->cur_dirstr),
5686                             &(dent->file->basename));
5687                 }
5688
5689                 if (!isoent_add_child_tail(dent, isoent)) {
5690                         np = (struct isoent *)__archive_rb_tree_find_node(
5691                             &(dent->rbtree), isoent->file->basename.s);
5692                         goto same_entry;
5693                 }
5694                 return (ARCHIVE_OK);
5695         }
5696
5697 same_entry:
5698         /*
5699          * We have already has the entry the filename of which is
5700          * the same.
5701          */
5702         f1 = np->file;
5703         f2 = isoent->file;
5704
5705         /* If the file type of entries is different,
5706          * we cannot handle it. */
5707         if (archive_entry_filetype(f1->entry) !=
5708             archive_entry_filetype(f2->entry)) {
5709                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
5710                     "Found duplicate entries `%s' and its file type is "
5711                     "different",
5712                     archive_entry_pathname(f1->entry));
5713                 _isoent_free(isoent);
5714                 *isoentpp = NULL;
5715                 return (ARCHIVE_FAILED);
5716         }
5717
5718         /* Swap file entries. */
5719         np->file = f2;
5720         isoent->file = f1;
5721         np->virtual = 0;
5722
5723         _isoent_free(isoent);
5724         *isoentpp = np;
5725         return (ARCHIVE_OK);
5726 }
5727
5728 /*
5729  * Find a entry from `isoent'
5730  */
5731 static struct isoent *
5732 isoent_find_child(struct isoent *isoent, const char *child_name)
5733 {
5734         struct isoent *np;
5735
5736         np = (struct isoent *)__archive_rb_tree_find_node(
5737             &(isoent->rbtree), child_name);
5738         return (np);
5739 }
5740
5741 /*
5742  * Find a entry full-path of which is specified by `fn' parameter,
5743  * in the tree.
5744  */
5745 static struct isoent *
5746 isoent_find_entry(struct isoent *rootent, const char *fn)
5747 {
5748 #if defined(_WIN32) && !defined(__CYGWIN__)
5749         char name[_MAX_FNAME];/* Included null terminator size. */
5750 #elif defined(NAME_MAX) && NAME_MAX >= 255
5751         char name[NAME_MAX+1];
5752 #else
5753         char name[256];
5754 #endif
5755         struct isoent *isoent, *np;
5756         int l;
5757
5758         isoent = rootent;
5759         np = NULL;
5760         for (;;) {
5761                 l = get_path_component(name, sizeof(name), fn);
5762                 if (l == 0)
5763                         break;
5764                 fn += l;
5765                 if (fn[0] == '/')
5766                         fn++;
5767
5768                 np = isoent_find_child(isoent, name);
5769                 if (np == NULL)
5770                         break;
5771                 if (fn[0] == '\0')
5772                         break;/* We found out the entry */
5773
5774                 /* Try sub directory. */
5775                 isoent = np;
5776                 np = NULL;
5777                 if (!isoent->dir)
5778                         break;/* Not directory */
5779         }
5780
5781         return (np);
5782 }
5783
5784 /*
5785  * Following idr_* functions are used for resolving duplicated filenames
5786  * and unreceivable filenames to generate ISO9660/Joliet Identifiers.
5787  */
5788
5789 static void
5790 idr_relaxed_filenames(char *map)
5791 {
5792         int i;
5793
5794         for (i = 0x21; i <= 0x2F; i++)
5795                 map[i] = 1;
5796         for (i = 0x3A; i <= 0x41; i++)
5797                 map[i] = 1;
5798         for (i = 0x5B; i <= 0x5E; i++)
5799                 map[i] = 1;
5800         map[0x60] = 1;
5801         for (i = 0x7B; i <= 0x7E; i++)
5802                 map[i] = 1;
5803 }
5804
5805 static void
5806 idr_init(struct iso9660 *iso9660, struct vdd *vdd, struct idr *idr)
5807 {
5808
5809         idr->idrent_pool = NULL;
5810         idr->pool_size = 0;
5811         if (vdd->vdd_type != VDD_JOLIET) {
5812                 if (iso9660->opt.iso_level <= 3) {
5813                         memcpy(idr->char_map, d_characters_map,
5814                             sizeof(idr->char_map));
5815                 } else {
5816                         memcpy(idr->char_map, d1_characters_map,
5817                             sizeof(idr->char_map));
5818                         idr_relaxed_filenames(idr->char_map);
5819                 }
5820         }
5821 }
5822
5823 static void
5824 idr_cleanup(struct idr *idr)
5825 {
5826         free(idr->idrent_pool);
5827 }
5828
5829 static int
5830 idr_ensure_poolsize(struct archive_write *a, struct idr *idr,
5831     int cnt)
5832 {
5833
5834         if (idr->pool_size < cnt) {
5835                 void *p;
5836                 const int bk = (1 << 7) - 1;
5837                 int psize;
5838
5839                 psize = (cnt + bk) & ~bk;
5840                 p = realloc(idr->idrent_pool, sizeof(struct idrent) * psize);
5841                 if (p == NULL) {
5842                         archive_set_error(&a->archive, ENOMEM,
5843                             "Can't allocate memory");
5844                         return (ARCHIVE_FATAL);
5845                 }
5846                 idr->idrent_pool = (struct idrent *)p;
5847                 idr->pool_size = psize;
5848         }
5849         return (ARCHIVE_OK);
5850 }
5851
5852 static int
5853 idr_start(struct archive_write *a, struct idr *idr, int cnt, int ffmax,
5854     int num_size, int null_size, const struct archive_rb_tree_ops *rbt_ops)
5855 {
5856         int r;
5857
5858         (void)ffmax; /* UNUSED */
5859
5860         r = idr_ensure_poolsize(a, idr, cnt);
5861         if (r != ARCHIVE_OK)
5862                 return (r);
5863         __archive_rb_tree_init(&(idr->rbtree), rbt_ops);
5864         idr->wait_list.first = NULL;
5865         idr->wait_list.last = &(idr->wait_list.first);
5866         idr->pool_idx = 0;
5867         idr->num_size = num_size;
5868         idr->null_size = null_size;
5869         return (ARCHIVE_OK);
5870 }
5871
5872 static void
5873 idr_register(struct idr *idr, struct isoent *isoent, int weight, int noff)
5874 {
5875         struct idrent *idrent, *n;
5876
5877         idrent = &(idr->idrent_pool[idr->pool_idx++]);
5878         idrent->wnext = idrent->avail = NULL;
5879         idrent->isoent = isoent;
5880         idrent->weight = weight;
5881         idrent->noff = noff;
5882         idrent->rename_num = 0;
5883
5884         if (!__archive_rb_tree_insert_node(&(idr->rbtree), &(idrent->rbnode))) {
5885                 n = (struct idrent *)__archive_rb_tree_find_node(
5886                     &(idr->rbtree), idrent->isoent);
5887                 if (n != NULL) {
5888                         /* this `idrent' needs to rename. */
5889                         idrent->avail = n;
5890                         *idr->wait_list.last = idrent;
5891                         idr->wait_list.last = &(idrent->wnext);
5892                 }
5893         }
5894 }
5895
5896 static void
5897 idr_extend_identifier(struct idrent *wnp, int numsize, int nullsize)
5898 {
5899         unsigned char *p;
5900         int wnp_ext_off;
5901
5902         wnp_ext_off = wnp->isoent->ext_off;
5903         if (wnp->noff + numsize != wnp_ext_off) {
5904                 p = (unsigned char *)wnp->isoent->identifier;
5905                 /* Extend the filename; foo.c --> foo___.c */
5906                 memmove(p + wnp->noff + numsize, p + wnp_ext_off,
5907                     wnp->isoent->ext_len + nullsize);
5908                 wnp->isoent->ext_off = wnp_ext_off = wnp->noff + numsize;
5909                 wnp->isoent->id_len = wnp_ext_off + wnp->isoent->ext_len;
5910         }
5911 }
5912
5913 static void
5914 idr_resolve(struct idr *idr, void (*fsetnum)(unsigned char *p, int num))
5915 {
5916         struct idrent *n;
5917         unsigned char *p;
5918
5919         for (n = idr->wait_list.first; n != NULL; n = n->wnext) {
5920                 idr_extend_identifier(n, idr->num_size, idr->null_size);
5921                 p = (unsigned char *)n->isoent->identifier + n->noff;
5922                 do {
5923                         fsetnum(p, n->avail->rename_num++);
5924                 } while (!__archive_rb_tree_insert_node(
5925                     &(idr->rbtree), &(n->rbnode)));
5926         }
5927 }
5928
5929 static void
5930 idr_set_num(unsigned char *p, int num)
5931 {
5932         static const char xdig[] = {
5933                 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
5934                 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
5935                 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
5936                 'U', 'V', 'W', 'X', 'Y', 'Z'
5937         };
5938
5939         num %= sizeof(xdig) * sizeof(xdig) * sizeof(xdig);
5940         p[0] = xdig[(num / (sizeof(xdig) * sizeof(xdig)))];
5941         num %= sizeof(xdig) * sizeof(xdig);
5942         p[1] = xdig[ (num / sizeof(xdig))];
5943         num %= sizeof(xdig);
5944         p[2] = xdig[num];
5945 }
5946
5947 static void
5948 idr_set_num_beutf16(unsigned char *p, int num)
5949 {
5950         static const uint16_t xdig[] = {
5951                 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
5952                 0x0036, 0x0037, 0x0038, 0x0039,
5953                 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046,
5954                 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C,
5955                 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052,
5956                 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
5957                 0x0059, 0x005A
5958         };
5959 #define XDIG_CNT        (sizeof(xdig)/sizeof(xdig[0]))
5960
5961         num %= XDIG_CNT * XDIG_CNT * XDIG_CNT;
5962         archive_be16enc(p, xdig[(num / (XDIG_CNT * XDIG_CNT))]);
5963         num %= XDIG_CNT * XDIG_CNT;
5964         archive_be16enc(p+2, xdig[ (num / XDIG_CNT)]);
5965         num %= XDIG_CNT;
5966         archive_be16enc(p+4, xdig[num]);
5967 }
5968
5969 /*
5970  * Generate ISO9660 Identifier.
5971  */
5972 static int
5973 isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent,
5974     struct idr *idr)
5975 {
5976         struct iso9660 *iso9660;
5977         struct isoent *np;
5978         char *p;
5979         int l, r;
5980         const char *char_map;
5981         char allow_ldots, allow_multidot, allow_period, allow_vernum;
5982         int fnmax, ffmax, dnmax;
5983         static const struct archive_rb_tree_ops rb_ops = {
5984                 isoent_cmp_node_iso9660, isoent_cmp_key_iso9660
5985         };
5986
5987         if (isoent->children.cnt == 0)
5988                 return (0);
5989
5990         iso9660 = a->format_data;
5991         char_map = idr->char_map;
5992         if (iso9660->opt.iso_level <= 3) {
5993                 allow_ldots = 0;
5994                 allow_multidot = 0;
5995                 allow_period = 1;
5996                 allow_vernum = iso9660->opt.allow_vernum;
5997                 if (iso9660->opt.iso_level == 1) {
5998                         fnmax = 8;
5999                         ffmax = 12;/* fnmax + '.' + 3 */
6000                         dnmax = 8;
6001                 } else {
6002                         fnmax = 30;
6003                         ffmax = 31;
6004                         dnmax = 31;
6005                 }
6006         } else {
6007                 allow_ldots = allow_multidot = 1;
6008                 allow_period = allow_vernum = 0;
6009                 if (iso9660->opt.rr)
6010                         /*
6011                          * MDR : The maximum size of Directory Record(254).
6012                          * DRL : A Directory Record Length(33).
6013                          * CE  : A size of SUSP CE System Use Entry(28).
6014                          * MDR - DRL - CE = 254 - 33 - 28 = 193.
6015                          */
6016                         fnmax = ffmax = dnmax = 193;
6017                 else
6018                         /*
6019                          * XA  : CD-ROM XA System Use Extension
6020                          *       Information(14).
6021                          * MDR - DRL - XA = 254 - 33 -14 = 207.
6022                          */
6023                         fnmax = ffmax = dnmax = 207;
6024         }
6025
6026         r = idr_start(a, idr, isoent->children.cnt, ffmax, 3, 1, &rb_ops);
6027         if (r < 0)
6028                 return (r);
6029
6030         for (np = isoent->children.first; np != NULL; np = np->chnext) {
6031                 char *dot, *xdot;
6032                 int ext_off, noff, weight;
6033
6034                 l = (int)np->file->basename.length;
6035                 p = malloc(l+31+2+1);
6036                 if (p == NULL) {
6037                         archive_set_error(&a->archive, ENOMEM,
6038                             "Can't allocate memory");
6039                         return (ARCHIVE_FATAL);
6040                 }
6041                 memcpy(p, np->file->basename.s, l);
6042                 p[l] = '\0';
6043                 np->identifier = p;
6044
6045                 dot = xdot = NULL;
6046                 if (!allow_ldots) {
6047                         /*
6048                          * If there is a '.' character at the first byte,
6049                          * it has to be replaced by '_' character.
6050                          */
6051                         if (*p == '.')
6052                                 *p++ = '_';
6053                 }
6054                 for (;*p; p++) {
6055                         if (*p & 0x80) {
6056                                 *p = '_';
6057                                 continue;
6058                         }
6059                         if (char_map[(unsigned char)*p]) {
6060                                 /* if iso-level is '4', a character '.' is
6061                                  * allowed by char_map. */
6062                                 if (*p == '.') {
6063                                         xdot = dot;
6064                                         dot = p;
6065                                 }
6066                                 continue;
6067                         }
6068                         if (*p >= 'a' && *p <= 'z') {
6069                                 *p -= 'a' - 'A';
6070                                 continue;
6071                         }
6072                         if (*p == '.') {
6073                                 xdot = dot;
6074                                 dot = p;
6075                                 if (allow_multidot)
6076                                         continue;
6077                         }
6078                         *p = '_';
6079                 }
6080                 p = np->identifier;
6081                 weight = -1;
6082                 if (dot == NULL) {
6083                         int nammax;
6084
6085                         if (np->dir)
6086                                 nammax = dnmax;
6087                         else
6088                                 nammax = fnmax;
6089
6090                         if (l > nammax) {
6091                                 p[nammax] = '\0';
6092                                 weight = nammax;
6093                                 ext_off = nammax;
6094                         } else
6095                                 ext_off = l;
6096                 } else {
6097                         *dot = '.';
6098                         ext_off = (int)(dot - p);
6099
6100                         if (iso9660->opt.iso_level == 1) {
6101                                 if (dot - p <= 8) {
6102                                         if (strlen(dot) > 4) {
6103                                                 /* A length of a file extension
6104                                                  * must be less than 4 */
6105                                                 dot[4] = '\0';
6106                                                 weight = 0;
6107                                         }
6108                                 } else {
6109                                         p[8] = dot[0];
6110                                         p[9] = dot[1];
6111                                         p[10] = dot[2];
6112                                         p[11] = dot[3];
6113                                         p[12] = '\0';
6114                                         weight = 8;
6115                                         ext_off = 8;
6116                                 }
6117                         } else if (np->dir) {
6118                                 if (l > dnmax) {
6119                                         p[dnmax] = '\0';
6120                                         weight = dnmax;
6121                                         if (ext_off > dnmax)
6122                                                 ext_off = dnmax;
6123                                 }
6124                         } else if (l > ffmax) {
6125                                 int extlen = (int)strlen(dot);
6126                                 int xdoff;
6127
6128                                 if (xdot != NULL)
6129                                         xdoff = (int)(xdot - p);
6130                                 else
6131                                         xdoff = 0;
6132
6133                                 if (extlen > 1 && xdoff < fnmax-1) {
6134                                         int off;
6135
6136                                         if (extlen > ffmax)
6137                                                 extlen = ffmax;
6138                                         off = ffmax - extlen;
6139                                         if (off == 0) {
6140                                                 /* A dot('.')  character
6141                                                  * doesn't place to the first
6142                                                  * byte of identifier. */
6143                                                 off ++;
6144                                                 extlen --;
6145                                         }
6146                                         memmove(p+off, dot, extlen);
6147                                         p[ffmax] = '\0';
6148                                         ext_off = off;
6149                                         weight = off;
6150 #ifdef COMPAT_MKISOFS
6151                                 } else if (xdoff >= fnmax-1) {
6152                                         /* Simulate a bug(?) of mkisofs. */
6153                                         p[fnmax-1] = '\0';
6154                                         ext_off = fnmax-1;
6155                                         weight = fnmax-1;
6156 #endif
6157                                 } else {
6158                                         p[fnmax] = '\0';
6159                                         ext_off = fnmax;
6160                                         weight = fnmax;
6161                                 }
6162                         }
6163                 }
6164                 /* Save an offset of a file name extension to sort files. */
6165                 np->ext_off = ext_off;
6166                 np->ext_len = (int)strlen(&p[ext_off]);
6167                 np->id_len = l = ext_off + np->ext_len;
6168
6169                 /* Make an offset of the number which is used to be set
6170                  * hexadecimal number to avoid duplicate identifier. */
6171                 if (iso9660->opt.iso_level == 1) {
6172                         if (ext_off >= 5)
6173                                 noff = 5;
6174                         else
6175                                 noff = ext_off;
6176                 } else {
6177                         if (l == ffmax)
6178                                 noff = ext_off - 3;
6179                         else if (l == ffmax-1)
6180                                 noff = ext_off - 2;
6181                         else if (l == ffmax-2)
6182                                 noff = ext_off - 1;
6183                         else
6184                                 noff = ext_off;
6185                 }
6186                 /* Register entry to the identifier resolver. */
6187                 idr_register(idr, np, weight, noff);
6188         }
6189
6190         /* Resolve duplicate identifier. */
6191         idr_resolve(idr, idr_set_num);
6192
6193         /* Add a period and a version number to identifiers. */
6194         for (np = isoent->children.first; np != NULL; np = np->chnext) {
6195                 if (!np->dir && np->rr_child == NULL) {
6196                         p = np->identifier + np->ext_off + np->ext_len;
6197                         if (np->ext_len == 0 && allow_period) {
6198                                 *p++ = '.';
6199                                 np->ext_len = 1;
6200                         }
6201                         if (np->ext_len == 1 && !allow_period) {
6202                                 *--p = '\0';
6203                                 np->ext_len = 0;
6204                         }
6205                         np->id_len = np->ext_off + np->ext_len;
6206                         if (allow_vernum) {
6207                                 *p++ = ';';
6208                                 *p++ = '1';
6209                                 np->id_len += 2;
6210                         }
6211                         *p = '\0';
6212                 } else
6213                         np->id_len = np->ext_off + np->ext_len;
6214                 np->mb_len = np->id_len;
6215         }
6216         return (ARCHIVE_OK);
6217 }
6218
6219 /*
6220  * Generate Joliet Identifier.
6221  */
6222 static int
6223 isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent,
6224     struct idr *idr)
6225 {
6226         struct iso9660 *iso9660;
6227         struct isoent *np;
6228         unsigned char *p;
6229         size_t l;
6230         int r;
6231         size_t ffmax, parent_len;
6232         static const struct archive_rb_tree_ops rb_ops = {
6233                 isoent_cmp_node_joliet, isoent_cmp_key_joliet
6234         };
6235
6236         if (isoent->children.cnt == 0)
6237                 return (0);
6238
6239         iso9660 = a->format_data;
6240         if (iso9660->opt.joliet == OPT_JOLIET_LONGNAME)
6241                 ffmax = 206;
6242         else
6243                 ffmax = 128;
6244
6245         r = idr_start(a, idr, isoent->children.cnt, (int)ffmax, 6, 2, &rb_ops);
6246         if (r < 0)
6247                 return (r);
6248
6249         parent_len = 1;
6250         for (np = isoent; np->parent != np; np = np->parent)
6251                 parent_len += np->mb_len + 1;
6252
6253         for (np = isoent->children.first; np != NULL; np = np->chnext) {
6254                 unsigned char *dot;
6255                 int ext_off, noff, weight;
6256                 size_t lt;
6257
6258                 if ((l = np->file->basename_utf16.length) > ffmax)
6259                         l = ffmax;
6260
6261                 p = malloc((l+1)*2);
6262                 if (p == NULL) {
6263                         archive_set_error(&a->archive, ENOMEM,
6264                             "Can't allocate memory");
6265                         return (ARCHIVE_FATAL);
6266                 }
6267                 memcpy(p, np->file->basename_utf16.s, l);
6268                 p[l] = 0;
6269                 p[l+1] = 0;
6270
6271                 np->identifier = (char *)p;
6272                 lt = l;
6273                 dot = p + l;
6274                 weight = 0;
6275                 while (lt > 0) {
6276                         if (!joliet_allowed_char(p[0], p[1]))
6277                                 archive_be16enc(p, 0x005F); /* '_' */
6278                         else if (p[0] == 0 && p[1] == 0x2E) /* '.' */
6279                                 dot = p;
6280                         p += 2;
6281                         lt -= 2;
6282                 }
6283                 ext_off = (int)(dot - (unsigned char *)np->identifier);
6284                 np->ext_off = ext_off;
6285                 np->ext_len = (int)l - ext_off;
6286                 np->id_len = (int)l;
6287
6288                 /*
6289                  * Get a length of MBS of a full-pathname.
6290                  */
6291                 if (np->file->basename_utf16.length > ffmax) {
6292                         if (archive_strncpy_l(&iso9660->mbs,
6293                             (const char *)np->identifier, l,
6294                                 iso9660->sconv_from_utf16be) != 0 &&
6295                             errno == ENOMEM) {
6296                                 archive_set_error(&a->archive, errno,
6297                                     "No memory");
6298                                 return (ARCHIVE_FATAL);
6299                         }
6300                         np->mb_len = (int)iso9660->mbs.length;
6301                         if (np->mb_len != (int)np->file->basename.length)
6302                                 weight = np->mb_len;
6303                 } else
6304                         np->mb_len = (int)np->file->basename.length;
6305
6306                 /* If a length of full-pathname is longer than 240 bytes,
6307                  * it violates Joliet extensions regulation. */
6308                 if (parent_len > 240
6309                     || np->mb_len > 240
6310                     || parent_len + np->mb_len > 240) {
6311                         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
6312                             "The regulation of Joliet extensions;"
6313                             " A length of a full-pathname of `%s' is "
6314                             "longer than 240 bytes, (p=%d, b=%d)",
6315                             archive_entry_pathname(np->file->entry),
6316                             (int)parent_len, (int)np->mb_len);
6317                         return (ARCHIVE_FATAL);
6318                 }
6319
6320                 /* Make an offset of the number which is used to be set
6321                  * hexadecimal number to avoid duplicate identifier. */
6322                 if (l == ffmax)
6323                         noff = ext_off - 6;
6324                 else if (l == ffmax-2)
6325                         noff = ext_off - 4;
6326                 else if (l == ffmax-4)
6327                         noff = ext_off - 2;
6328                 else
6329                         noff = ext_off;
6330                 /* Register entry to the identifier resolver. */
6331                 idr_register(idr, np, weight, noff);
6332         }
6333
6334         /* Resolve duplicate identifier with Joliet Volume. */
6335         idr_resolve(idr, idr_set_num_beutf16);
6336
6337         return (ARCHIVE_OK);
6338 }
6339
6340 /*
6341  * This comparing rule is according to ISO9660 Standard 9.3
6342  */
6343 static int
6344 isoent_cmp_iso9660_identifier(const struct isoent *p1, const struct isoent *p2)
6345 {
6346         const char *s1, *s2;
6347         int cmp;
6348         int l;
6349
6350         s1 = p1->identifier;
6351         s2 = p2->identifier;
6352
6353         /* Compare File Name */
6354         l = p1->ext_off;
6355         if (l > p2->ext_off)
6356                 l = p2->ext_off;
6357         cmp = memcmp(s1, s2, l);
6358         if (cmp != 0)
6359                 return (cmp);
6360         if (p1->ext_off < p2->ext_off) {
6361                 s2 += l;
6362                 l = p2->ext_off - p1->ext_off;
6363                 while (l--)
6364                         if (0x20 != *s2++)
6365                                 return (0x20
6366                                     - *(const unsigned char *)(s2 - 1));
6367         } else if (p1->ext_off > p2->ext_off) {
6368                 s1 += l;
6369                 l = p1->ext_off - p2->ext_off;
6370                 while (l--)
6371                         if (0x20 != *s1++)
6372                                 return (*(const unsigned char *)(s1 - 1)
6373                                     - 0x20);
6374         }
6375         /* Compare File Name Extension */
6376         if (p1->ext_len == 0 && p2->ext_len == 0)
6377                 return (0);
6378         if (p1->ext_len == 1 && p2->ext_len == 1)
6379                 return (0);
6380         if (p1->ext_len <= 1)
6381                 return (-1);
6382         if (p2->ext_len <= 1)
6383                 return (1);
6384         l = p1->ext_len;
6385         if (l > p2->ext_len)
6386                 l = p2->ext_len;
6387         s1 = p1->identifier + p1->ext_off;
6388         s2 = p2->identifier + p2->ext_off;
6389         if (l > 1) {
6390                 cmp = memcmp(s1, s2, l);
6391                 if (cmp != 0)
6392                         return (cmp);
6393         }
6394         if (p1->ext_len < p2->ext_len) {
6395                 s2 += l;
6396                 l = p2->ext_len - p1->ext_len;
6397                 while (l--)
6398                         if (0x20 != *s2++)
6399                                 return (0x20
6400                                     - *(const unsigned char *)(s2 - 1));
6401         } else if (p1->ext_len > p2->ext_len) {
6402                 s1 += l;
6403                 l = p1->ext_len - p2->ext_len;
6404                 while (l--)
6405                         if (0x20 != *s1++)
6406                                 return (*(const unsigned char *)(s1 - 1)
6407                                     - 0x20);
6408         }
6409         /* Compare File Version Number */
6410         /* No operation. The File Version Number is always one. */
6411
6412         return (cmp);
6413 }
6414
6415 static int
6416 isoent_cmp_node_iso9660(const struct archive_rb_node *n1,
6417     const struct archive_rb_node *n2)
6418 {
6419         const struct idrent *e1 = (const struct idrent *)n1;
6420         const struct idrent *e2 = (const struct idrent *)n2;
6421
6422         return (isoent_cmp_iso9660_identifier(e2->isoent, e1->isoent));
6423 }
6424
6425 static int
6426 isoent_cmp_key_iso9660(const struct archive_rb_node *node, const void *key)
6427 {
6428         const struct isoent *isoent = (const struct isoent *)key;
6429         const struct idrent *idrent = (const struct idrent *)node;
6430
6431         return (isoent_cmp_iso9660_identifier(isoent, idrent->isoent));
6432 }
6433
6434 static int
6435 isoent_cmp_joliet_identifier(const struct isoent *p1, const struct isoent *p2)
6436 {
6437         const unsigned char *s1, *s2;
6438         int cmp;
6439         int l;
6440
6441         s1 = (const unsigned char *)p1->identifier;
6442         s2 = (const unsigned char *)p2->identifier;
6443
6444         /* Compare File Name */
6445         l = p1->ext_off;
6446         if (l > p2->ext_off)
6447                 l = p2->ext_off;
6448         cmp = memcmp(s1, s2, l);
6449         if (cmp != 0)
6450                 return (cmp);
6451         if (p1->ext_off < p2->ext_off) {
6452                 s2 += l;
6453                 l = p2->ext_off - p1->ext_off;
6454                 while (l--)
6455                         if (0 != *s2++)
6456                                 return (- *(const unsigned char *)(s2 - 1));
6457         } else if (p1->ext_off > p2->ext_off) {
6458                 s1 += l;
6459                 l = p1->ext_off - p2->ext_off;
6460                 while (l--)
6461                         if (0 != *s1++)
6462                                 return (*(const unsigned char *)(s1 - 1));
6463         }
6464         /* Compare File Name Extension */
6465         if (p1->ext_len == 0 && p2->ext_len == 0)
6466                 return (0);
6467         if (p1->ext_len == 2 && p2->ext_len == 2)
6468                 return (0);
6469         if (p1->ext_len <= 2)
6470                 return (-1);
6471         if (p2->ext_len <= 2)
6472                 return (1);
6473         l = p1->ext_len;
6474         if (l > p2->ext_len)
6475                 l = p2->ext_len;
6476         s1 = (unsigned char *)(p1->identifier + p1->ext_off);
6477         s2 = (unsigned char *)(p2->identifier + p2->ext_off);
6478         if (l > 1) {
6479                 cmp = memcmp(s1, s2, l);
6480                 if (cmp != 0)
6481                         return (cmp);
6482         }
6483         if (p1->ext_len < p2->ext_len) {
6484                 s2 += l;
6485                 l = p2->ext_len - p1->ext_len;
6486                 while (l--)
6487                         if (0 != *s2++)
6488                                 return (- *(const unsigned char *)(s2 - 1));
6489         } else if (p1->ext_len > p2->ext_len) {
6490                 s1 += l;
6491                 l = p1->ext_len - p2->ext_len;
6492                 while (l--)
6493                         if (0 != *s1++)
6494                                 return (*(const unsigned char *)(s1 - 1));
6495         }
6496         /* Compare File Version Number */
6497         /* No operation. The File Version Number is always one. */
6498
6499         return (cmp);
6500 }
6501
6502 static int
6503 isoent_cmp_node_joliet(const struct archive_rb_node *n1,
6504     const struct archive_rb_node *n2)
6505 {
6506         const struct idrent *e1 = (const struct idrent *)n1;
6507         const struct idrent *e2 = (const struct idrent *)n2;
6508
6509         return (isoent_cmp_joliet_identifier(e2->isoent, e1->isoent));
6510 }
6511
6512 static int
6513 isoent_cmp_key_joliet(const struct archive_rb_node *node, const void *key)
6514 {
6515         const struct isoent *isoent = (const struct isoent *)key;
6516         const struct idrent *idrent = (const struct idrent *)node;
6517
6518         return (isoent_cmp_joliet_identifier(isoent, idrent->isoent));
6519 }
6520
6521 static int
6522 isoent_make_sorted_files(struct archive_write *a, struct isoent *isoent,
6523     struct idr *idr)
6524 {
6525         struct archive_rb_node *rn;
6526         struct isoent **children;
6527
6528         children = malloc(isoent->children.cnt * sizeof(struct isoent *));
6529         if (children == NULL) {
6530                 archive_set_error(&a->archive, ENOMEM,
6531                     "Can't allocate memory");
6532                 return (ARCHIVE_FATAL);
6533         }
6534         isoent->children_sorted = children;
6535
6536         ARCHIVE_RB_TREE_FOREACH(rn, &(idr->rbtree)) {
6537                 struct idrent *idrent = (struct idrent *)rn;
6538                 *children ++ = idrent->isoent;
6539         }
6540         return (ARCHIVE_OK);
6541 }
6542
6543 /*
6544  * - Generate ISO9660 and Joliet identifiers from basenames.
6545  * - Sort files by each directory.
6546  */
6547 static int
6548 isoent_traverse_tree(struct archive_write *a, struct vdd* vdd)
6549 {
6550         struct iso9660 *iso9660 = a->format_data;
6551         struct isoent *np;
6552         struct idr idr;
6553         int depth;
6554         int r;
6555         int (*genid)(struct archive_write *, struct isoent *, struct idr *);
6556
6557         idr_init(iso9660, vdd, &idr);
6558         np = vdd->rootent;
6559         depth = 0;
6560         if (vdd->vdd_type == VDD_JOLIET)
6561                 genid = isoent_gen_joliet_identifier;
6562         else
6563                 genid = isoent_gen_iso9660_identifier;
6564         do {
6565                 if (np->virtual &&
6566                     !archive_entry_mtime_is_set(np->file->entry)) {
6567                         /* Set properly times to virtual directory */
6568                         archive_entry_set_mtime(np->file->entry,
6569                             iso9660->birth_time, 0);
6570                         archive_entry_set_atime(np->file->entry,
6571                             iso9660->birth_time, 0);
6572                         archive_entry_set_ctime(np->file->entry,
6573                             iso9660->birth_time, 0);
6574                 }
6575                 if (np->children.first != NULL) {
6576                         if (vdd->vdd_type != VDD_JOLIET &&
6577                             !iso9660->opt.rr && depth + 1 >= vdd->max_depth) {
6578                                 if (np->children.cnt > 0)
6579                                         iso9660->directories_too_deep = np;
6580                         } else {
6581                                 /* Generate Identifier */
6582                                 r = genid(a, np, &idr);
6583                                 if (r < 0)
6584                                         goto exit_traverse_tree;
6585                                 r = isoent_make_sorted_files(a, np, &idr);
6586                                 if (r < 0)
6587                                         goto exit_traverse_tree;
6588
6589                                 if (np->subdirs.first != NULL &&
6590                                     depth + 1 < vdd->max_depth) {
6591                                         /* Enter to sub directories. */
6592                                         np = np->subdirs.first;
6593                                         depth++;
6594                                         continue;
6595                                 }
6596                         }
6597                 }
6598                 while (np != np->parent) {
6599                         if (np->drnext == NULL) {
6600                                 /* Return to the parent directory. */
6601                                 np = np->parent;
6602                                 depth--;
6603                         } else {
6604                                 np = np->drnext;
6605                                 break;
6606                         }
6607                 }
6608         } while (np != np->parent);
6609
6610         r = ARCHIVE_OK;
6611 exit_traverse_tree:
6612         idr_cleanup(&idr);
6613
6614         return (r);
6615 }
6616
6617 /*
6618  * Collect directory entries into path_table by a directory depth.
6619  */
6620 static int
6621 isoent_collect_dirs(struct vdd *vdd, struct isoent *rootent, int depth)
6622 {
6623         struct isoent *np;
6624
6625         if (rootent == NULL)
6626                 rootent = vdd->rootent;
6627         np = rootent;
6628         do {
6629                 /* Register current directory to pathtable. */
6630                 path_table_add_entry(&(vdd->pathtbl[depth]), np);
6631
6632                 if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) {
6633                         /* Enter to sub directories. */
6634                         np = np->subdirs.first;
6635                         depth++;
6636                         continue;
6637                 }
6638                 while (np != rootent) {
6639                         if (np->drnext == NULL) {
6640                                 /* Return to the parent directory. */
6641                                 np = np->parent;
6642                                 depth--;
6643                         } else {
6644                                 np = np->drnext;
6645                                 break;
6646                         }
6647                 }
6648         } while (np != rootent);
6649
6650         return (ARCHIVE_OK);
6651 }
6652
6653 /*
6654  * The entry whose number of levels in a directory hierarchy is
6655  * large than eight relocate to rr_move directory.
6656  */
6657 static int
6658 isoent_rr_move_dir(struct archive_write *a, struct isoent **rr_moved,
6659     struct isoent *curent, struct isoent **newent)
6660 {
6661         struct iso9660 *iso9660 = a->format_data;
6662         struct isoent *rrmoved, *mvent, *np;
6663
6664         if ((rrmoved = *rr_moved) == NULL) {
6665                 struct isoent *rootent = iso9660->primary.rootent;
6666                 /* There isn't rr_move entry.
6667                  * Create rr_move entry and insert it into the root entry.
6668                  */
6669                 rrmoved = isoent_create_virtual_dir(a, iso9660, "rr_moved");
6670                 if (rrmoved == NULL) {
6671                         archive_set_error(&a->archive, ENOMEM,
6672                             "Can't allocate memory");
6673                         return (ARCHIVE_FATAL);
6674                 }
6675                 /* Add "rr_moved" entry to the root entry. */
6676                 isoent_add_child_head(rootent, rrmoved);
6677                 archive_entry_set_nlink(rootent->file->entry,
6678                     archive_entry_nlink(rootent->file->entry) + 1);
6679                 /* Register "rr_moved" entry to second level pathtable. */
6680                 path_table_add_entry(&(iso9660->primary.pathtbl[1]), rrmoved);
6681                 /* Save rr_moved. */
6682                 *rr_moved = rrmoved;
6683         }
6684         /*
6685          * Make a clone of curent which is going to be relocated
6686          * to rr_moved.
6687          */
6688         mvent = isoent_clone(curent);
6689         if (mvent == NULL) {
6690                 archive_set_error(&a->archive, ENOMEM,
6691                     "Can't allocate memory");
6692                 return (ARCHIVE_FATAL);
6693         }
6694         /* linking..  and use for creating "CL", "PL" and "RE" */
6695         mvent->rr_parent = curent->parent;
6696         curent->rr_child = mvent;
6697         /*
6698          * Move subdirectories from the curent to mvent
6699          */
6700         if (curent->children.first != NULL) {
6701                 *mvent->children.last = curent->children.first;
6702                 mvent->children.last = curent->children.last;
6703         }
6704         for (np = mvent->children.first; np != NULL; np = np->chnext)
6705                 np->parent = mvent;
6706         mvent->children.cnt = curent->children.cnt;
6707         curent->children.cnt = 0;
6708         curent->children.first = NULL;
6709         curent->children.last = &curent->children.first;
6710
6711         if (curent->subdirs.first != NULL) {
6712                 *mvent->subdirs.last = curent->subdirs.first;
6713                 mvent->subdirs.last = curent->subdirs.last;
6714         }
6715         mvent->subdirs.cnt = curent->subdirs.cnt;
6716         curent->subdirs.cnt = 0;
6717         curent->subdirs.first = NULL;
6718         curent->subdirs.last = &curent->subdirs.first;
6719
6720         /*
6721          * The mvent becomes a child of the rr_moved entry.
6722          */
6723         isoent_add_child_tail(rrmoved, mvent);
6724         archive_entry_set_nlink(rrmoved->file->entry,
6725             archive_entry_nlink(rrmoved->file->entry) + 1);
6726         /*
6727          * This entry which relocated to the rr_moved directory
6728          * has to set the flag as a file.
6729          * See also RRIP 4.1.5.1 Description of the "CL" System Use Entry.
6730          */
6731         curent->dir = 0;
6732
6733         *newent = mvent;
6734
6735         return (ARCHIVE_OK);
6736 }
6737
6738 static int
6739 isoent_rr_move(struct archive_write *a)
6740 {
6741         struct iso9660 *iso9660 = a->format_data;
6742         struct path_table *pt;
6743         struct isoent *rootent, *rr_moved;
6744         struct isoent *np, *last;
6745         int r;
6746
6747         pt = &(iso9660->primary.pathtbl[MAX_DEPTH-1]);
6748         /* There aren't level 8 directories reaching a deeper level. */
6749         if (pt->cnt == 0)
6750                 return (ARCHIVE_OK);
6751
6752         rootent = iso9660->primary.rootent;
6753         /* If "rr_moved" directory is already existing,
6754          * we have to use it. */
6755         rr_moved = isoent_find_child(rootent, "rr_moved");
6756         if (rr_moved != NULL &&
6757             rr_moved != rootent->children.first) {
6758                 /*
6759                  * It's necessary that rr_move is the first entry
6760                  * of the root.
6761                  */
6762                 /* Remove "rr_moved" entry from children chain. */
6763                 isoent_remove_child(rootent, rr_moved);
6764
6765                 /* Add "rr_moved" entry into the head of children chain. */
6766                 isoent_add_child_head(rootent, rr_moved);
6767         }
6768
6769         /*
6770          * Check level 8 path_table.
6771          * If find out sub directory entries, that entries move to rr_move.
6772          */
6773         np = pt->first;
6774         while (np != NULL) {
6775                 last = path_table_last_entry(pt);
6776                 for (; np != NULL; np = np->ptnext) {
6777                         struct isoent *mvent;
6778                         struct isoent *newent;
6779
6780                         if (!np->dir)
6781                                 continue;
6782                         for (mvent = np->subdirs.first;
6783                             mvent != NULL; mvent = mvent->drnext) {
6784                                 r = isoent_rr_move_dir(a, &rr_moved,
6785                                     mvent, &newent);
6786                                 if (r < 0)
6787                                         return (r);
6788                                 isoent_collect_dirs(&(iso9660->primary),
6789                                     newent, 2);
6790                         }
6791                 }
6792                 /* If new entries are added to level 8 path_talbe,
6793                  * its sub directory entries move to rr_move too.
6794                  */
6795                 np = last->ptnext;
6796         }
6797
6798         return (ARCHIVE_OK);
6799 }
6800
6801 /*
6802  * This comparing rule is according to ISO9660 Standard 6.9.1
6803  */
6804 static int
6805 _compare_path_table(const void *v1, const void *v2)
6806 {
6807         const struct isoent *p1, *p2;
6808         const char *s1, *s2;
6809         int cmp, l;
6810
6811         p1 = *((const struct isoent **)(uintptr_t)v1);
6812         p2 = *((const struct isoent **)(uintptr_t)v2);
6813
6814         /* Compare parent directory number */
6815         cmp = p1->parent->dir_number - p2->parent->dir_number;
6816         if (cmp != 0)
6817                 return (cmp);
6818
6819         /* Compare identifier */
6820         s1 = p1->identifier;
6821         s2 = p2->identifier;
6822         l = p1->ext_off;
6823         if (l > p2->ext_off)
6824                 l = p2->ext_off;
6825         cmp = strncmp(s1, s2, l);
6826         if (cmp != 0)
6827                 return (cmp);
6828         if (p1->ext_off < p2->ext_off) {
6829                 s2 += l;
6830                 l = p2->ext_off - p1->ext_off;
6831                 while (l--)
6832                         if (0x20 != *s2++)
6833                                 return (0x20
6834                                     - *(const unsigned char *)(s2 - 1));
6835         } else if (p1->ext_off > p2->ext_off) {
6836                 s1 += l;
6837                 l = p1->ext_off - p2->ext_off;
6838                 while (l--)
6839                         if (0x20 != *s1++)
6840                                 return (*(const unsigned char *)(s1 - 1)
6841                                     - 0x20);
6842         }
6843         return (0);
6844 }
6845
6846 static int
6847 _compare_path_table_joliet(const void *v1, const void *v2)
6848 {
6849         const struct isoent *p1, *p2;
6850         const unsigned char *s1, *s2;
6851         int cmp, l;
6852
6853         p1 = *((const struct isoent **)(uintptr_t)v1);
6854         p2 = *((const struct isoent **)(uintptr_t)v2);
6855
6856         /* Compare parent directory number */
6857         cmp = p1->parent->dir_number - p2->parent->dir_number;
6858         if (cmp != 0)
6859                 return (cmp);
6860
6861         /* Compare identifier */
6862         s1 = (const unsigned char *)p1->identifier;
6863         s2 = (const unsigned char *)p2->identifier;
6864         l = p1->ext_off;
6865         if (l > p2->ext_off)
6866                 l = p2->ext_off;
6867         cmp = memcmp(s1, s2, l);
6868         if (cmp != 0)
6869                 return (cmp);
6870         if (p1->ext_off < p2->ext_off) {
6871                 s2 += l;
6872                 l = p2->ext_off - p1->ext_off;
6873                 while (l--)
6874                         if (0 != *s2++)
6875                                 return (- *(const unsigned char *)(s2 - 1));
6876         } else if (p1->ext_off > p2->ext_off) {
6877                 s1 += l;
6878                 l = p1->ext_off - p2->ext_off;
6879                 while (l--)
6880                         if (0 != *s1++)
6881                                 return (*(const unsigned char *)(s1 - 1));
6882         }
6883         return (0);
6884 }
6885
6886 static inline void
6887 path_table_add_entry(struct path_table *pathtbl, struct isoent *ent)
6888 {
6889         ent->ptnext = NULL;
6890         *pathtbl->last = ent;
6891         pathtbl->last = &(ent->ptnext);
6892         pathtbl->cnt ++;
6893 }
6894
6895 static inline struct isoent *
6896 path_table_last_entry(struct path_table *pathtbl)
6897 {
6898         if (pathtbl->first == NULL)
6899                 return (NULL);
6900         return (((struct isoent *)(void *)
6901                 ((char *)(pathtbl->last) - offsetof(struct isoent, ptnext))));
6902 }
6903
6904 /*
6905  * Sort directory entries in path_table
6906  * and assign directory number to each entries.
6907  */
6908 static int
6909 isoent_make_path_table_2(struct archive_write *a, struct vdd *vdd,
6910     int depth, int *dir_number)
6911 {
6912         struct isoent *np;
6913         struct isoent **enttbl;
6914         struct path_table *pt;
6915         int i;
6916
6917         pt = &vdd->pathtbl[depth];
6918         if (pt->cnt == 0) {
6919                 pt->sorted = NULL;
6920                 return (ARCHIVE_OK);
6921         }
6922         enttbl = malloc(pt->cnt * sizeof(struct isoent *));
6923         if (enttbl == NULL) {
6924                 archive_set_error(&a->archive, ENOMEM,
6925                     "Can't allocate memory");
6926                 return (ARCHIVE_FATAL);
6927         }
6928         pt->sorted = enttbl;
6929         for (np = pt->first; np != NULL; np = np->ptnext)
6930                 *enttbl ++ = np;
6931         enttbl = pt->sorted;
6932
6933         switch (vdd->vdd_type) {
6934         case VDD_PRIMARY:
6935         case VDD_ENHANCED:
6936 #ifdef __COMPAR_FN_T
6937                 qsort(enttbl, pt->cnt, sizeof(struct isoent *),
6938                     (__compar_fn_t)_compare_path_table);
6939 #else
6940                 qsort(enttbl, pt->cnt, sizeof(struct isoent *),
6941                     _compare_path_table);
6942 #endif
6943                 break;
6944         case VDD_JOLIET:
6945 #ifdef __COMPAR_FN_T
6946                 qsort(enttbl, pt->cnt, sizeof(struct isoent *),
6947                     (__compar_fn_t)_compare_path_table_joliet);
6948 #else
6949                 qsort(enttbl, pt->cnt, sizeof(struct isoent *),
6950                     _compare_path_table_joliet);
6951 #endif
6952                 break;
6953         }
6954         for (i = 0; i < pt->cnt; i++)
6955                 enttbl[i]->dir_number = (*dir_number)++;
6956
6957         return (ARCHIVE_OK);
6958 }
6959
6960 static int
6961 isoent_alloc_path_table(struct archive_write *a, struct vdd *vdd,
6962     int max_depth)
6963 {
6964         int i;
6965
6966         vdd->max_depth = max_depth;
6967         vdd->pathtbl = malloc(sizeof(*vdd->pathtbl) * vdd->max_depth);
6968         if (vdd->pathtbl == NULL) {
6969                 archive_set_error(&a->archive, ENOMEM,
6970                     "Can't allocate memory");
6971                 return (ARCHIVE_FATAL);
6972         }
6973         for (i = 0; i < vdd->max_depth; i++) {
6974                 vdd->pathtbl[i].first = NULL;
6975                 vdd->pathtbl[i].last = &(vdd->pathtbl[i].first);
6976                 vdd->pathtbl[i].sorted = NULL;
6977                 vdd->pathtbl[i].cnt = 0;
6978         }
6979         return (ARCHIVE_OK);
6980 }
6981
6982 /*
6983  * Make Path Tables
6984  */
6985 static int
6986 isoent_make_path_table(struct archive_write *a)
6987 {
6988         struct iso9660 *iso9660 = a->format_data;
6989         int depth, r;
6990         int dir_number;
6991
6992         /*
6993          * Init Path Table.
6994          */
6995         if (iso9660->dircnt_max >= MAX_DEPTH &&
6996             (!iso9660->opt.limit_depth || iso9660->opt.iso_level == 4))
6997                 r = isoent_alloc_path_table(a, &(iso9660->primary),
6998                     iso9660->dircnt_max + 1);
6999         else
7000                 /* The number of levels in the hierarchy cannot exceed
7001                  * eight. */
7002                 r = isoent_alloc_path_table(a, &(iso9660->primary),
7003                     MAX_DEPTH);
7004         if (r < 0)
7005                 return (r);
7006         if (iso9660->opt.joliet) {
7007                 r = isoent_alloc_path_table(a, &(iso9660->joliet),
7008                     iso9660->dircnt_max + 1);
7009                 if (r < 0)
7010                         return (r);
7011         }
7012
7013         /* Step 0.
7014          * - Collect directories for primary and joliet.
7015          */
7016         isoent_collect_dirs(&(iso9660->primary), NULL, 0);
7017         if (iso9660->opt.joliet)
7018                 isoent_collect_dirs(&(iso9660->joliet), NULL, 0);
7019         /*
7020          * Rockridge; move deeper depth directories to rr_moved.
7021          */
7022         if (iso9660->opt.rr) {
7023                 r = isoent_rr_move(a);
7024                 if (r < 0)
7025                         return (r);
7026         }
7027
7028         /* Update nlink. */
7029         isofile_connect_hardlink_files(iso9660);
7030
7031         /* Step 1.
7032          * - Renew a value of the depth of that directories.
7033          * - Resolve hardlinks.
7034          * - Convert pathnames to ISO9660 name or UCS2(joliet).
7035          * - Sort files by each directory.
7036          */
7037         r = isoent_traverse_tree(a, &(iso9660->primary));
7038         if (r < 0)
7039                 return (r);
7040         if (iso9660->opt.joliet) {
7041                 r = isoent_traverse_tree(a, &(iso9660->joliet));
7042                 if (r < 0)
7043                         return (r);
7044         }
7045
7046         /* Step 2.
7047          * - Sort directories.
7048          * - Assign all directory number.
7049          */
7050         dir_number = 1;
7051         for (depth = 0; depth < iso9660->primary.max_depth; depth++) {
7052                 r = isoent_make_path_table_2(a, &(iso9660->primary),
7053                     depth, &dir_number);
7054                 if (r < 0)
7055                         return (r);
7056         }
7057         if (iso9660->opt.joliet) {
7058                 dir_number = 1;
7059                 for (depth = 0; depth < iso9660->joliet.max_depth; depth++) {
7060                         r = isoent_make_path_table_2(a, &(iso9660->joliet),
7061                             depth, &dir_number);
7062                         if (r < 0)
7063                                 return (r);
7064                 }
7065         }
7066         if (iso9660->opt.limit_dirs && dir_number > 0xffff) {
7067                 /*
7068                  * Maximum number of directories is 65535(0xffff)
7069                  * doe to size(16bit) of Parent Directory Number of
7070                  * the Path Table.
7071                  * See also ISO9660 Standard 9.4.
7072                  */
7073                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7074                     "Too many directories(%d) over 65535.", dir_number);
7075                 return (ARCHIVE_FATAL);
7076         }
7077
7078         /* Get the size of the Path Table. */
7079         calculate_path_table_size(&(iso9660->primary));
7080         if (iso9660->opt.joliet)
7081                 calculate_path_table_size(&(iso9660->joliet));
7082
7083         return (ARCHIVE_OK);
7084 }
7085
7086 static int
7087 isoent_find_out_boot_file(struct archive_write *a, struct isoent *rootent)
7088 {
7089         struct iso9660 *iso9660 = a->format_data;
7090
7091         /* Find a isoent of the boot file. */
7092         iso9660->el_torito.boot = isoent_find_entry(rootent,
7093             iso9660->el_torito.boot_filename.s);
7094         if (iso9660->el_torito.boot == NULL) {
7095                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7096                     "Can't find the boot image file ``%s''",
7097                     iso9660->el_torito.boot_filename.s);
7098                 return (ARCHIVE_FATAL);
7099         }
7100         iso9660->el_torito.boot->file->boot = BOOT_IMAGE;
7101         return (ARCHIVE_OK);
7102 }
7103
7104 static int
7105 isoent_create_boot_catalog(struct archive_write *a, struct isoent *rootent)
7106 {
7107         struct iso9660 *iso9660 = a->format_data;
7108         struct isofile *file;
7109         struct isoent *isoent;
7110         struct archive_entry *entry;
7111
7112         (void)rootent; /* UNUSED */
7113         /*
7114          * Create the entry which is the "boot.catalog" file.
7115          */
7116         file = isofile_new(a, NULL);
7117         if (file == NULL) {
7118                 archive_set_error(&a->archive, ENOMEM,
7119                     "Can't allocate memory");
7120                 return (ARCHIVE_FATAL);
7121         }
7122         archive_entry_set_pathname(file->entry,
7123             iso9660->el_torito.catalog_filename.s);
7124         archive_entry_set_size(file->entry, LOGICAL_BLOCK_SIZE);
7125         archive_entry_set_mtime(file->entry, iso9660->birth_time, 0);
7126         archive_entry_set_atime(file->entry, iso9660->birth_time, 0);
7127         archive_entry_set_ctime(file->entry, iso9660->birth_time, 0);
7128         archive_entry_set_uid(file->entry, getuid());
7129         archive_entry_set_gid(file->entry, getgid());
7130         archive_entry_set_mode(file->entry, AE_IFREG | 0444);
7131         archive_entry_set_nlink(file->entry, 1);
7132
7133         if (isofile_gen_utility_names(a, file) < ARCHIVE_WARN) {
7134                 isofile_free(file);
7135                 return (ARCHIVE_FATAL);
7136         }
7137         file->boot = BOOT_CATALOG;
7138         file->content.size = LOGICAL_BLOCK_SIZE;
7139         isofile_add_entry(iso9660, file);
7140
7141         isoent = isoent_new(file);
7142         if (isoent == NULL) {
7143                 archive_set_error(&a->archive, ENOMEM,
7144                     "Can't allocate memory");
7145                 return (ARCHIVE_FATAL);
7146         }
7147         isoent->virtual = 1;
7148
7149         /* Add the "boot.catalog" entry into tree */
7150         if (isoent_tree(a, &isoent) != ARCHIVE_OK)
7151                 return (ARCHIVE_FATAL);
7152
7153         iso9660->el_torito.catalog = isoent;
7154         /*
7155          * Get a boot media type.
7156          */
7157         switch (iso9660->opt.boot_type) {
7158         default:
7159         case OPT_BOOT_TYPE_AUTO:
7160                 /* Try detecting a media type of the boot image. */
7161                 entry = iso9660->el_torito.boot->file->entry;
7162                 if (archive_entry_size(entry) == FD_1_2M_SIZE)
7163                         iso9660->el_torito.media_type =
7164                             BOOT_MEDIA_1_2M_DISKETTE;
7165                 else if (archive_entry_size(entry) == FD_1_44M_SIZE)
7166                         iso9660->el_torito.media_type =
7167                             BOOT_MEDIA_1_44M_DISKETTE;
7168                 else if (archive_entry_size(entry) == FD_2_88M_SIZE)
7169                         iso9660->el_torito.media_type =
7170                             BOOT_MEDIA_2_88M_DISKETTE;
7171                 else
7172                         /* We cannot decide whether the boot image is
7173                          * hard-disk. */
7174                         iso9660->el_torito.media_type =
7175                             BOOT_MEDIA_NO_EMULATION;
7176                 break;
7177         case OPT_BOOT_TYPE_NO_EMU:
7178                 iso9660->el_torito.media_type = BOOT_MEDIA_NO_EMULATION;
7179                 break;
7180         case OPT_BOOT_TYPE_HARD_DISK:
7181                 iso9660->el_torito.media_type = BOOT_MEDIA_HARD_DISK;
7182                 break;
7183         case OPT_BOOT_TYPE_FD:
7184                 entry = iso9660->el_torito.boot->file->entry;
7185                 if (archive_entry_size(entry) <= FD_1_2M_SIZE)
7186                         iso9660->el_torito.media_type =
7187                             BOOT_MEDIA_1_2M_DISKETTE;
7188                 else if (archive_entry_size(entry) <= FD_1_44M_SIZE)
7189                         iso9660->el_torito.media_type =
7190                             BOOT_MEDIA_1_44M_DISKETTE;
7191                 else if (archive_entry_size(entry) <= FD_2_88M_SIZE)
7192                         iso9660->el_torito.media_type =
7193                             BOOT_MEDIA_2_88M_DISKETTE;
7194                 else {
7195                         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7196                             "Boot image file(``%s'') size is too big "
7197                             "for fd type.",
7198                             iso9660->el_torito.boot_filename.s);
7199                         return (ARCHIVE_FATAL);
7200                 }
7201                 break;
7202         }
7203
7204         /*
7205          * Get a system type.
7206          * TODO: `El Torito' specification says "A copy of byte 5 from the
7207          *       Partition Table found in the boot image".
7208          */
7209         iso9660->el_torito.system_type = 0;
7210
7211         /*
7212          * Get an ID.
7213          */
7214         if (iso9660->opt.publisher)
7215                 archive_string_copy(&(iso9660->el_torito.id),
7216                     &(iso9660->publisher_identifier));
7217
7218
7219         return (ARCHIVE_OK);
7220 }
7221
7222 /*
7223  * If a media type is floppy, return its image size.
7224  * otherwise return 0.
7225  */
7226 static size_t
7227 fd_boot_image_size(int media_type)
7228 {
7229         switch (media_type) {
7230         case BOOT_MEDIA_1_2M_DISKETTE:
7231                 return (FD_1_2M_SIZE);
7232         case BOOT_MEDIA_1_44M_DISKETTE:
7233                 return (FD_1_44M_SIZE);
7234         case BOOT_MEDIA_2_88M_DISKETTE:
7235                 return (FD_2_88M_SIZE);
7236         default:
7237                 return (0);
7238         }
7239 }
7240
7241 /*
7242  * Make a boot catalog image data.
7243  */
7244 static int
7245 make_boot_catalog(struct archive_write *a)
7246 {
7247         struct iso9660 *iso9660 = a->format_data;
7248         unsigned char *block;
7249         unsigned char *p;
7250         uint16_t sum, *wp;
7251
7252         block = wb_buffptr(a);
7253         memset(block, 0, LOGICAL_BLOCK_SIZE);
7254         p = block;
7255         /*
7256          * Validation Entry
7257          */
7258         /* Header ID */
7259         p[0] = 1;
7260         /* Platform ID */
7261         p[1] = iso9660->el_torito.platform_id;
7262         /* Reserved */
7263         p[2] = p[3] = 0;
7264         /* ID */
7265         if (archive_strlen(&(iso9660->el_torito.id)) > 0)
7266                 strncpy((char *)p+4, iso9660->el_torito.id.s, 23);
7267         p[27] = 0;
7268         /* Checksum */
7269         p[28] = p[29] = 0;
7270         /* Key */
7271         p[30] = 0x55;
7272         p[31] = 0xAA;
7273
7274         sum = 0;
7275         wp = (uint16_t *)block;
7276         while (wp < (uint16_t *)&block[32])
7277                 sum += archive_le16dec(wp++);
7278         set_num_721(&block[28], (~sum) + 1);
7279
7280         /*
7281          * Initial/Default Entry
7282          */
7283         p = &block[32];
7284         /* Boot Indicator */
7285         p[0] = 0x88;
7286         /* Boot media type */
7287         p[1] = iso9660->el_torito.media_type;
7288         /* Load Segment */
7289         if (iso9660->el_torito.media_type == BOOT_MEDIA_NO_EMULATION)
7290                 set_num_721(&p[2], iso9660->el_torito.boot_load_seg);
7291         else
7292                 set_num_721(&p[2], 0);
7293         /* System Type */
7294         p[4] = iso9660->el_torito.system_type;
7295         /* Unused */
7296         p[5] = 0;
7297         /* Sector Count */
7298         if (iso9660->el_torito.media_type == BOOT_MEDIA_NO_EMULATION)
7299                 set_num_721(&p[6], iso9660->el_torito.boot_load_size);
7300         else
7301                 set_num_721(&p[6], 1);
7302         /* Load RBA */
7303         set_num_731(&p[8],
7304             iso9660->el_torito.boot->file->content.location);
7305         /* Unused */
7306         memset(&p[12], 0, 20);
7307
7308         return (wb_consume(a, LOGICAL_BLOCK_SIZE));
7309 }
7310
7311 static int
7312 setup_boot_information(struct archive_write *a)
7313 {
7314         struct iso9660 *iso9660 = a->format_data;
7315         struct isoent *np;
7316         int64_t size;
7317         uint32_t sum;
7318         unsigned char buff[4096];
7319
7320         np = iso9660->el_torito.boot;
7321         lseek(iso9660->temp_fd,
7322             np->file->content.offset_of_temp + 64, SEEK_SET);
7323         size = archive_entry_size(np->file->entry) - 64;
7324         if (size <= 0) {
7325                 archive_set_error(&a->archive, errno,
7326                     "Boot file(%jd) is too small", (intmax_t)size + 64);
7327                 return (ARCHIVE_FATAL);
7328         }
7329         sum = 0;
7330         while (size > 0) {
7331                 size_t rsize;
7332                 ssize_t i, rs;
7333
7334                 if (size > (int64_t)sizeof(buff))
7335                         rsize = sizeof(buff);
7336                 else
7337                         rsize = (size_t)size;
7338
7339                 rs = read(iso9660->temp_fd, buff, rsize);
7340                 if (rs <= 0) {
7341                         archive_set_error(&a->archive, errno,
7342                             "Can't read temporary file(%jd)",
7343                             (intmax_t)rs);
7344                         return (ARCHIVE_FATAL);
7345                 }
7346                 for (i = 0; i < rs; i += 4)
7347                         sum += archive_le32dec(buff + i);
7348                 size -= rs;
7349         }
7350         /* Set the location of Primary Volume Descriptor. */
7351         set_num_731(buff, SYSTEM_AREA_BLOCK);
7352         /* Set the location of the boot file. */
7353         set_num_731(buff+4, np->file->content.location);
7354         /* Set the size of the boot file. */
7355         size = fd_boot_image_size(iso9660->el_torito.media_type);
7356         if (size == 0)
7357                 size = archive_entry_size(np->file->entry);
7358         set_num_731(buff+8, (uint32_t)size);
7359         /* Set the sum of the boot file. */
7360         set_num_731(buff+12, sum);
7361         /* Clear reserved bytes. */
7362         memset(buff+16, 0, 40);
7363
7364         /* Overwrite the boot file. */
7365         lseek(iso9660->temp_fd,
7366             np->file->content.offset_of_temp + 8, SEEK_SET);
7367         return (write_to_temp(a, buff, 56));
7368 }
7369
7370 #ifdef HAVE_ZLIB_H
7371
7372 static int
7373 zisofs_init_zstream(struct archive_write *a)
7374 {
7375         struct iso9660 *iso9660 = a->format_data;
7376         int r;
7377
7378         iso9660->zisofs.stream.next_in = NULL;
7379         iso9660->zisofs.stream.avail_in = 0;
7380         iso9660->zisofs.stream.total_in = 0;
7381         iso9660->zisofs.stream.total_out = 0;
7382         if (iso9660->zisofs.stream_valid)
7383                 r = deflateReset(&(iso9660->zisofs.stream));
7384         else {
7385                 r = deflateInit(&(iso9660->zisofs.stream),
7386                     iso9660->zisofs.compression_level);
7387                 iso9660->zisofs.stream_valid = 1;
7388         }
7389         switch (r) {
7390         case Z_OK:
7391                 break;
7392         default:
7393         case Z_STREAM_ERROR:
7394                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7395                     "Internal error initializing "
7396                     "compression library: invalid setup parameter");
7397                 return (ARCHIVE_FATAL);
7398         case Z_MEM_ERROR:
7399                 archive_set_error(&a->archive, ENOMEM,
7400                     "Internal error initializing "
7401                     "compression library");
7402                 return (ARCHIVE_FATAL);
7403         case Z_VERSION_ERROR:
7404                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7405                     "Internal error initializing "
7406                     "compression library: invalid library version");
7407                 return (ARCHIVE_FATAL);
7408         }
7409         return (ARCHIVE_OK);
7410 }
7411
7412 #endif /* HAVE_ZLIB_H */
7413
7414 static int
7415 zisofs_init(struct archive_write *a,  struct isofile *file)
7416 {
7417         struct iso9660 *iso9660 = a->format_data;
7418 #ifdef HAVE_ZLIB_H
7419         uint64_t tsize;
7420         size_t _ceil, bpsize;
7421         int r;
7422 #endif
7423
7424         iso9660->zisofs.detect_magic = 0;
7425         iso9660->zisofs.making = 0;
7426
7427         if (!iso9660->opt.rr || !iso9660->opt.zisofs)
7428                 return (ARCHIVE_OK);
7429
7430         if (archive_entry_size(file->entry) >= 24 &&
7431             archive_entry_size(file->entry) < MULTI_EXTENT_SIZE) {
7432                 /* Acceptable file size for zisofs. */
7433                 iso9660->zisofs.detect_magic = 1;
7434                 iso9660->zisofs.magic_cnt = 0;
7435         }
7436         if (!iso9660->zisofs.detect_magic)
7437                 return (ARCHIVE_OK);
7438
7439 #ifdef HAVE_ZLIB_H
7440         /* The number of Logical Blocks which uncompressed data
7441          * will use in iso-image file is the same as the number of
7442          * Logical Blocks which zisofs(compressed) data will use
7443          * in ISO-image file. It won't reduce iso-image file size. */
7444         if (archive_entry_size(file->entry) <= LOGICAL_BLOCK_SIZE)
7445                 return (ARCHIVE_OK);
7446
7447         /* Initialize compression library */
7448         r = zisofs_init_zstream(a);
7449         if (r != ARCHIVE_OK)
7450                 return (ARCHIVE_FATAL);
7451
7452         /* Mark file->zisofs to create RRIP 'ZF' Use Entry. */
7453         file->zisofs.header_size = ZF_HEADER_SIZE >> 2;
7454         file->zisofs.log2_bs = ZF_LOG2_BS;
7455         file->zisofs.uncompressed_size =
7456                 (uint32_t)archive_entry_size(file->entry);
7457
7458         /* Calculate a size of Block Pointers of zisofs. */
7459         _ceil = (file->zisofs.uncompressed_size + ZF_BLOCK_SIZE -1)
7460                 >> file->zisofs.log2_bs;
7461         iso9660->zisofs.block_pointers_cnt = (int)_ceil + 1;
7462         iso9660->zisofs.block_pointers_idx = 0;
7463
7464         /* Ensure a buffer size used for Block Pointers */
7465         bpsize = iso9660->zisofs.block_pointers_cnt *
7466             sizeof(iso9660->zisofs.block_pointers[0]);
7467         if (iso9660->zisofs.block_pointers_allocated < bpsize) {
7468                 free(iso9660->zisofs.block_pointers);
7469                 iso9660->zisofs.block_pointers = malloc(bpsize);
7470                 if (iso9660->zisofs.block_pointers == NULL) {
7471                         archive_set_error(&a->archive, ENOMEM,
7472                             "Can't allocate data");
7473                         return (ARCHIVE_FATAL);
7474                 }
7475                 iso9660->zisofs.block_pointers_allocated = bpsize;
7476         }
7477
7478         /*
7479          * Skip zisofs header and Block Pointers, which we will write
7480          * after all compressed data of a file written to the temporary
7481          * file.
7482          */
7483         tsize = ZF_HEADER_SIZE + bpsize;
7484         if (write_null(a, (size_t)tsize) != ARCHIVE_OK)
7485                 return (ARCHIVE_FATAL);
7486
7487         /*
7488          * Initialize some variables to make zisofs.
7489          */
7490         archive_le32enc(&(iso9660->zisofs.block_pointers[0]),
7491                 (uint32_t)tsize);
7492         iso9660->zisofs.remaining = file->zisofs.uncompressed_size;
7493         iso9660->zisofs.making = 1;
7494         iso9660->zisofs.allzero = 1;
7495         iso9660->zisofs.block_offset = tsize;
7496         iso9660->zisofs.total_size = tsize;
7497         iso9660->cur_file->cur_content->size = tsize;
7498 #endif
7499
7500         return (ARCHIVE_OK);
7501 }
7502
7503 static void
7504 zisofs_detect_magic(struct archive_write *a, const void *buff, size_t s)
7505 {
7506         struct iso9660 *iso9660 = a->format_data;
7507         struct isofile *file = iso9660->cur_file;
7508         const unsigned char *p, *endp;
7509         const unsigned char *magic_buff;
7510         uint32_t uncompressed_size;
7511         unsigned char header_size;
7512         unsigned char log2_bs;
7513         size_t _ceil, doff;
7514         uint32_t bst, bed;
7515         int magic_max;
7516         int64_t entry_size;
7517
7518         entry_size = archive_entry_size(file->entry);
7519         if ((int64_t)sizeof(iso9660->zisofs.magic_buffer) > entry_size)
7520                 magic_max = (int)entry_size;
7521         else
7522                 magic_max = sizeof(iso9660->zisofs.magic_buffer);
7523
7524         if (iso9660->zisofs.magic_cnt == 0 && s >= (size_t)magic_max)
7525                 /* It's unnecessary we copy buffer. */
7526                 magic_buff = buff;
7527         else {
7528                 if (iso9660->zisofs.magic_cnt < magic_max) {
7529                         size_t l;
7530
7531                         l = sizeof(iso9660->zisofs.magic_buffer)
7532                             - iso9660->zisofs.magic_cnt;
7533                         if (l > s)
7534                                 l = s;
7535                         memcpy(iso9660->zisofs.magic_buffer
7536                             + iso9660->zisofs.magic_cnt, buff, l);
7537                         iso9660->zisofs.magic_cnt += (int)l;
7538                         if (iso9660->zisofs.magic_cnt < magic_max)
7539                                 return;
7540                 }
7541                 magic_buff = iso9660->zisofs.magic_buffer;
7542         }
7543         iso9660->zisofs.detect_magic = 0;
7544         p = magic_buff;
7545
7546         /* Check the magic code of zisofs. */
7547         if (memcmp(p, zisofs_magic, sizeof(zisofs_magic)) != 0)
7548                 /* This is not zisofs file which made by mkzftree. */
7549                 return;
7550         p += sizeof(zisofs_magic);
7551
7552         /* Read a zisofs header. */
7553         uncompressed_size = archive_le32dec(p);
7554         header_size = p[4];
7555         log2_bs = p[5];
7556         if (uncompressed_size < 24 || header_size != 4 ||
7557             log2_bs > 30 || log2_bs < 7)
7558                 return;/* Invalid or not supported header. */
7559
7560         /* Calculate a size of Block Pointers of zisofs. */
7561         _ceil = (uncompressed_size +
7562                 (ARCHIVE_LITERAL_LL(1) << log2_bs) -1) >> log2_bs;
7563         doff = (_ceil + 1) * 4 + 16;
7564         if (entry_size < (int64_t)doff)
7565                 return;/* Invalid data. */
7566
7567         /* Check every Block Pointer has valid value. */
7568         p = magic_buff + 16;
7569         endp = magic_buff + magic_max;
7570         while (_ceil && p + 8 <= endp) {
7571                 bst = archive_le32dec(p);
7572                 if (bst != doff)
7573                         return;/* Invalid data. */
7574                 p += 4;
7575                 bed = archive_le32dec(p);
7576                 if (bed < bst || bed > entry_size)
7577                         return;/* Invalid data. */
7578                 doff += bed - bst;
7579                 _ceil--;
7580         }
7581
7582         file->zisofs.uncompressed_size = uncompressed_size;
7583         file->zisofs.header_size = header_size;
7584         file->zisofs.log2_bs = log2_bs;
7585
7586         /* Disable making a zisofs image. */
7587         iso9660->zisofs.making = 0;
7588 }
7589
7590 #ifdef HAVE_ZLIB_H
7591
7592 /*
7593  * Compress data and write it to a temporary file.
7594  */
7595 static int
7596 zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s)
7597 {
7598         struct iso9660 *iso9660 = a->format_data;
7599         struct isofile *file = iso9660->cur_file;
7600         const unsigned char *b;
7601         z_stream *zstrm;
7602         size_t avail, csize;
7603         int flush, r;
7604
7605         zstrm = &(iso9660->zisofs.stream);
7606         zstrm->next_out = wb_buffptr(a);
7607         zstrm->avail_out = (uInt)wb_remaining(a);
7608         b = (const unsigned char *)buff;
7609         do {
7610                 avail = ZF_BLOCK_SIZE - zstrm->total_in;
7611                 if (s < avail) {
7612                         avail = s;
7613                         flush = Z_NO_FLUSH;
7614                 } else
7615                         flush = Z_FINISH;
7616                 iso9660->zisofs.remaining -= avail;
7617                 if (iso9660->zisofs.remaining <= 0)
7618                         flush = Z_FINISH;
7619
7620                 zstrm->next_in = (Bytef *)(uintptr_t)(const void *)b;
7621                 zstrm->avail_in = (uInt)avail;
7622
7623                 /*
7624                  * Check if current data block are all zero.
7625                  */
7626                 if (iso9660->zisofs.allzero) {
7627                         const unsigned char *nonzero = b;
7628                         const unsigned char *nonzeroend = b + avail;
7629
7630                         while (nonzero < nonzeroend)
7631                                 if (*nonzero++) {
7632                                         iso9660->zisofs.allzero = 0;
7633                                         break;
7634                                 }
7635                 }
7636                 b += avail;
7637                 s -= avail;
7638
7639                 /*
7640                  * If current data block are all zero, we do not use
7641                  * compressed data.
7642                  */
7643                 if (flush == Z_FINISH && iso9660->zisofs.allzero &&
7644                     avail + zstrm->total_in == ZF_BLOCK_SIZE) {
7645                         if (iso9660->zisofs.block_offset !=
7646                             file->cur_content->size) {
7647                                 int64_t diff;
7648
7649                                 r = wb_set_offset(a,
7650                                     file->cur_content->offset_of_temp +
7651                                         iso9660->zisofs.block_offset);
7652                                 if (r != ARCHIVE_OK)
7653                                         return (r);
7654                                 diff = file->cur_content->size -
7655                                     iso9660->zisofs.block_offset;
7656                                 file->cur_content->size -= diff;
7657                                 iso9660->zisofs.total_size -= diff;
7658                         }
7659                         zstrm->avail_in = 0;
7660                 }
7661
7662                 /*
7663                  * Compress file data.
7664                  */
7665                 while (zstrm->avail_in > 0) {
7666                         csize = zstrm->total_out;
7667                         r = deflate(zstrm, flush);
7668                         switch (r) {
7669                         case Z_OK:
7670                         case Z_STREAM_END:
7671                                 csize = zstrm->total_out - csize;
7672                                 if (wb_consume(a, csize) != ARCHIVE_OK)
7673                                         return (ARCHIVE_FATAL);
7674                                 iso9660->zisofs.total_size += csize;
7675                                 iso9660->cur_file->cur_content->size += csize;
7676                                 zstrm->next_out = wb_buffptr(a);
7677                                 zstrm->avail_out = (uInt)wb_remaining(a);
7678                                 break;
7679                         default:
7680                                 archive_set_error(&a->archive,
7681                                     ARCHIVE_ERRNO_MISC,
7682                                     "Compression failed:"
7683                                     " deflate() call returned status %d",
7684                                     r);
7685                                 return (ARCHIVE_FATAL);
7686                         }
7687                 }
7688
7689                 if (flush == Z_FINISH) {
7690                         /*
7691                          * Save the information of one zisofs block.
7692                          */
7693                         iso9660->zisofs.block_pointers_idx ++;
7694                         archive_le32enc(&(iso9660->zisofs.block_pointers[
7695                             iso9660->zisofs.block_pointers_idx]),
7696                                 (uint32_t)iso9660->zisofs.total_size);
7697                         r = zisofs_init_zstream(a);
7698                         if (r != ARCHIVE_OK)
7699                                 return (ARCHIVE_FATAL);
7700                         iso9660->zisofs.allzero = 1;
7701                         iso9660->zisofs.block_offset = file->cur_content->size;
7702                 }
7703         } while (s);
7704
7705         return (ARCHIVE_OK);
7706 }
7707
7708 static int
7709 zisofs_finish_entry(struct archive_write *a)
7710 {
7711         struct iso9660 *iso9660 = a->format_data;
7712         struct isofile *file = iso9660->cur_file;
7713         unsigned char buff[16];
7714         size_t s;
7715         int64_t tail;
7716
7717         /* Direct temp file stream to zisofs temp file stream. */
7718         archive_entry_set_size(file->entry, iso9660->zisofs.total_size);
7719
7720         /*
7721          * Save a file pointer which points the end of current zisofs data.
7722          */
7723         tail = wb_offset(a);
7724
7725         /*
7726          * Make a header.
7727          *
7728          * +-----------------+----------------+-----------------+
7729          * | Header 16 bytes | Block Pointers | Compressed data |
7730          * +-----------------+----------------+-----------------+
7731          * 0                16               +X
7732          * Block Pointers :
7733          *   4 * (((Uncompressed file size + block_size -1) / block_size) + 1)
7734          *
7735          * Write zisofs header.
7736          *    Magic number
7737          * +----+----+----+----+----+----+----+----+
7738          * | 37 | E4 | 53 | 96 | C9 | DB | D6 | 07 |
7739          * +----+----+----+----+----+----+----+----+
7740          * 0    1    2    3    4    5    6    7    8
7741          *
7742          * +------------------------+------------------+
7743          * | Uncompressed file size | header_size >> 2 |
7744          * +------------------------+------------------+
7745          * 8                       12                 13
7746          *
7747          * +-----------------+----------------+
7748          * | log2 block_size | Reserved(0000) |
7749          * +-----------------+----------------+
7750          * 13               14               16
7751          */
7752         memcpy(buff, zisofs_magic, 8);
7753         set_num_731(buff+8, file->zisofs.uncompressed_size);
7754         buff[12] = file->zisofs.header_size;
7755         buff[13] = file->zisofs.log2_bs;
7756         buff[14] = buff[15] = 0;/* Reserved */
7757
7758         /* Move to the right position to write the header. */
7759         wb_set_offset(a, file->content.offset_of_temp);
7760
7761         /* Write the header. */
7762         if (wb_write_to_temp(a, buff, 16) != ARCHIVE_OK)
7763                 return (ARCHIVE_FATAL);
7764
7765         /*
7766          * Write zisofs Block Pointers.
7767          */
7768         s = iso9660->zisofs.block_pointers_cnt *
7769             sizeof(iso9660->zisofs.block_pointers[0]);
7770         if (wb_write_to_temp(a, iso9660->zisofs.block_pointers, s)
7771             != ARCHIVE_OK)
7772                 return (ARCHIVE_FATAL);
7773
7774         /* Set a file pointer back to the end of the temporary file. */
7775         wb_set_offset(a, tail);
7776
7777         return (ARCHIVE_OK);
7778 }
7779
7780 static int
7781 zisofs_free(struct archive_write *a)
7782 {
7783         struct iso9660 *iso9660 = a->format_data;
7784         int ret = ARCHIVE_OK;
7785
7786         free(iso9660->zisofs.block_pointers);
7787         if (iso9660->zisofs.stream_valid &&
7788             deflateEnd(&(iso9660->zisofs.stream)) != Z_OK) {
7789                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7790                     "Failed to clean up compressor");
7791                 ret = ARCHIVE_FATAL;
7792         }
7793         iso9660->zisofs.block_pointers = NULL;
7794         iso9660->zisofs.stream_valid = 0;
7795         return (ret);
7796 }
7797
7798 struct zisofs_extract {
7799         int              pz_log2_bs; /* Log2 of block size */
7800         uint64_t         pz_uncompressed_size;
7801         size_t           uncompressed_buffer_size;
7802
7803         signed int       initialized:1;
7804         signed int       header_passed:1;
7805
7806         uint32_t         pz_offset;
7807         unsigned char   *block_pointers;
7808         size_t           block_pointers_size;
7809         size_t           block_pointers_avail;
7810         size_t           block_off;
7811         uint32_t         block_avail;
7812
7813         z_stream         stream;
7814         int              stream_valid;
7815 };
7816
7817 static ssize_t
7818 zisofs_extract_init(struct archive_write *a, struct zisofs_extract *zisofs,
7819     const unsigned char *p, size_t bytes)
7820 {
7821         size_t avail = bytes;
7822         size_t _ceil, xsize;
7823
7824         /* Allocate block pointers buffer. */
7825         _ceil = (size_t)((zisofs->pz_uncompressed_size +
7826                 (((int64_t)1) << zisofs->pz_log2_bs) - 1)
7827                 >> zisofs->pz_log2_bs);
7828         xsize = (_ceil + 1) * 4;
7829         if (zisofs->block_pointers == NULL) {
7830                 size_t alloc = ((xsize >> 10) + 1) << 10;
7831                 zisofs->block_pointers = malloc(alloc);
7832                 if (zisofs->block_pointers == NULL) {
7833                         archive_set_error(&a->archive, ENOMEM,
7834                             "No memory for zisofs decompression");
7835                         return (ARCHIVE_FATAL);
7836                 }
7837         }
7838         zisofs->block_pointers_size = xsize;
7839
7840         /* Allocate uncompressed data buffer. */
7841         zisofs->uncompressed_buffer_size = (size_t)1UL << zisofs->pz_log2_bs;
7842
7843         /*
7844          * Read the file header, and check the magic code of zisofs.
7845          */
7846         if (!zisofs->header_passed) {
7847                 int err = 0;
7848                 if (avail < 16) {
7849                         archive_set_error(&a->archive,
7850                             ARCHIVE_ERRNO_FILE_FORMAT,
7851                             "Illegal zisofs file body");
7852                         return (ARCHIVE_FATAL);
7853                 }
7854
7855                 if (memcmp(p, zisofs_magic, sizeof(zisofs_magic)) != 0)
7856                         err = 1;
7857                 else if (archive_le32dec(p + 8) != zisofs->pz_uncompressed_size)
7858                         err = 1;
7859                 else if (p[12] != 4 || p[13] != zisofs->pz_log2_bs)
7860                         err = 1;
7861                 if (err) {
7862                         archive_set_error(&a->archive,
7863                             ARCHIVE_ERRNO_FILE_FORMAT,
7864                             "Illegal zisofs file body");
7865                         return (ARCHIVE_FATAL);
7866                 }
7867                 avail -= 16;
7868                 p += 16;
7869                 zisofs->header_passed = 1;
7870         }
7871
7872         /*
7873          * Read block pointers.
7874          */
7875         if (zisofs->header_passed &&
7876             zisofs->block_pointers_avail < zisofs->block_pointers_size) {
7877                 xsize = zisofs->block_pointers_size
7878                     - zisofs->block_pointers_avail;
7879                 if (avail < xsize)
7880                         xsize = avail;
7881                 memcpy(zisofs->block_pointers
7882                     + zisofs->block_pointers_avail, p, xsize);
7883                 zisofs->block_pointers_avail += xsize;
7884                 avail -= xsize;
7885                 if (zisofs->block_pointers_avail
7886                     == zisofs->block_pointers_size) {
7887                         /* We've got all block pointers and initialize
7888                          * related variables.   */
7889                         zisofs->block_off = 0;
7890                         zisofs->block_avail = 0;
7891                         /* Complete a initialization */
7892                         zisofs->initialized = 1;
7893                 }
7894         }
7895         return ((ssize_t)avail);
7896 }
7897
7898 static ssize_t
7899 zisofs_extract(struct archive_write *a, struct zisofs_extract *zisofs,
7900     const unsigned char *p, size_t bytes)
7901 {
7902         size_t avail;
7903         int r;
7904
7905         if (!zisofs->initialized) {
7906                 ssize_t rs = zisofs_extract_init(a, zisofs, p, bytes);
7907                 if (rs < 0)
7908                         return (rs);
7909                 if (!zisofs->initialized) {
7910                         /* We need more data. */
7911                         zisofs->pz_offset += (uint32_t)bytes;
7912                         return (bytes);
7913                 }
7914                 avail = rs;
7915                 p += bytes - avail;
7916         } else
7917                 avail = bytes;
7918
7919         /*
7920          * Get block offsets from block pointers.
7921          */
7922         if (zisofs->block_avail == 0) {
7923                 uint32_t bst, bed;
7924
7925                 if (zisofs->block_off + 4 >= zisofs->block_pointers_size) {
7926                         /* There isn't a pair of offsets. */
7927                         archive_set_error(&a->archive,
7928                             ARCHIVE_ERRNO_FILE_FORMAT,
7929                             "Illegal zisofs block pointers");
7930                         return (ARCHIVE_FATAL);
7931                 }
7932                 bst = archive_le32dec(
7933                     zisofs->block_pointers + zisofs->block_off);
7934                 if (bst != zisofs->pz_offset + (bytes - avail)) {
7935                         archive_set_error(&a->archive,
7936                             ARCHIVE_ERRNO_FILE_FORMAT,
7937                             "Illegal zisofs block pointers(cannot seek)");
7938                         return (ARCHIVE_FATAL);
7939                 }
7940                 bed = archive_le32dec(
7941                     zisofs->block_pointers + zisofs->block_off + 4);
7942                 if (bed < bst) {
7943                         archive_set_error(&a->archive,
7944                             ARCHIVE_ERRNO_FILE_FORMAT,
7945                             "Illegal zisofs block pointers");
7946                         return (ARCHIVE_FATAL);
7947                 }
7948                 zisofs->block_avail = bed - bst;
7949                 zisofs->block_off += 4;
7950
7951                 /* Initialize compression library for new block. */
7952                 if (zisofs->stream_valid)
7953                         r = inflateReset(&zisofs->stream);
7954                 else
7955                         r = inflateInit(&zisofs->stream);
7956                 if (r != Z_OK) {
7957                         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
7958                             "Can't initialize zisofs decompression.");
7959                         return (ARCHIVE_FATAL);
7960                 }
7961                 zisofs->stream_valid = 1;
7962                 zisofs->stream.total_in = 0;
7963                 zisofs->stream.total_out = 0;
7964         }
7965
7966         /*
7967          * Make uncompressed data.
7968          */
7969         if (zisofs->block_avail == 0) {
7970                 /*
7971                  * It's basically 32K bytes NUL data.
7972                  */
7973                 unsigned char *wb;
7974                 size_t size, wsize;
7975
7976                 size = zisofs->uncompressed_buffer_size;
7977                 while (size) {
7978                         wb = wb_buffptr(a);
7979                         if (size > wb_remaining(a))
7980                                 wsize = wb_remaining(a);
7981                         else
7982                                 wsize = size;
7983                         memset(wb, 0, wsize);
7984                         r = wb_consume(a, wsize);
7985                         if (r < 0)
7986                                 return (r);
7987                         size -= wsize;
7988                 }
7989         } else {
7990                 zisofs->stream.next_in = (Bytef *)(uintptr_t)(const void *)p;
7991                 if (avail > zisofs->block_avail)
7992                         zisofs->stream.avail_in = zisofs->block_avail;
7993                 else
7994                         zisofs->stream.avail_in = (uInt)avail;
7995                 zisofs->stream.next_out = wb_buffptr(a);
7996                 zisofs->stream.avail_out = (uInt)wb_remaining(a);
7997
7998                 r = inflate(&zisofs->stream, 0);
7999                 switch (r) {
8000                 case Z_OK: /* Decompressor made some progress.*/
8001                 case Z_STREAM_END: /* Found end of stream. */
8002                         break;
8003                 default:
8004                         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
8005                             "zisofs decompression failed (%d)", r);
8006                         return (ARCHIVE_FATAL);
8007                 }
8008                 avail -= zisofs->stream.next_in - p;
8009                 zisofs->block_avail -= (uint32_t)(zisofs->stream.next_in - p);
8010                 r = wb_consume(a, wb_remaining(a) - zisofs->stream.avail_out);
8011                 if (r < 0)
8012                         return (r);
8013         }
8014         zisofs->pz_offset += (uint32_t)bytes;
8015         return (bytes - avail);
8016 }
8017
8018 static int
8019 zisofs_rewind_boot_file(struct archive_write *a)
8020 {
8021         struct iso9660 *iso9660 = a->format_data;
8022         struct isofile *file;
8023         unsigned char *rbuff;
8024         ssize_t r;
8025         size_t remaining, rbuff_size;
8026         struct zisofs_extract zext;
8027         int64_t read_offset, write_offset, new_offset;
8028         int fd, ret = ARCHIVE_OK;
8029
8030         file = iso9660->el_torito.boot->file;
8031         /*
8032          * There is nothing to do if this boot file does not have
8033          * zisofs header.
8034          */
8035         if (file->zisofs.header_size == 0)
8036                 return (ARCHIVE_OK);
8037
8038         /*
8039          * Uncompress the zisofs'ed file contents.
8040          */
8041         memset(&zext, 0, sizeof(zext));
8042         zext.pz_uncompressed_size = file->zisofs.uncompressed_size;
8043         zext.pz_log2_bs = file->zisofs.log2_bs;
8044
8045         fd = iso9660->temp_fd;
8046         new_offset = wb_offset(a);
8047         read_offset = file->content.offset_of_temp;
8048         remaining = (size_t)file->content.size;
8049         if (remaining > 1024 * 32)
8050                 rbuff_size = 1024 * 32;
8051         else
8052                 rbuff_size = remaining;
8053
8054         rbuff = malloc(rbuff_size);
8055         if (rbuff == NULL) {
8056                 archive_set_error(&a->archive, ENOMEM, "Can't allocate memory");
8057                 return (ARCHIVE_FATAL);
8058         }
8059         while (remaining) {
8060                 size_t rsize;
8061                 ssize_t rs;
8062
8063                 /* Get the current file pointer. */
8064                 write_offset = lseek(fd, 0, SEEK_CUR);
8065
8066                 /* Change the file pointer to read. */
8067                 lseek(fd, read_offset, SEEK_SET);
8068
8069                 rsize = rbuff_size;
8070                 if (rsize > remaining)
8071                         rsize = remaining;
8072                 rs = read(iso9660->temp_fd, rbuff, rsize);
8073                 if (rs <= 0) {
8074                         archive_set_error(&a->archive, errno,
8075                             "Can't read temporary file(%jd)", (intmax_t)rs);
8076                         ret = ARCHIVE_FATAL;
8077                         break;
8078                 }
8079                 remaining -= rs;
8080                 read_offset += rs;
8081
8082                 /* Put the file pointer back to write. */
8083                 lseek(fd, write_offset, SEEK_SET);
8084
8085                 r = zisofs_extract(a, &zext, rbuff, rs);
8086                 if (r < 0) {
8087                         ret = (int)r;
8088                         break;
8089                 }
8090         }
8091
8092         if (ret == ARCHIVE_OK) {
8093                 /*
8094                  * Change the boot file content from zisofs'ed data
8095                  * to plain data.
8096                  */
8097                 file->content.offset_of_temp = new_offset;
8098                 file->content.size = file->zisofs.uncompressed_size;
8099                 archive_entry_set_size(file->entry, file->content.size);
8100                 /* Set to be no zisofs. */
8101                 file->zisofs.header_size = 0;
8102                 file->zisofs.log2_bs = 0;
8103                 file->zisofs.uncompressed_size = 0;
8104                 r = wb_write_padding_to_temp(a, file->content.size);
8105                 if (r < 0)
8106                         ret = ARCHIVE_FATAL;
8107         }
8108
8109         /*
8110          * Free the resource we used in this function only.
8111          */
8112         free(rbuff);
8113         free(zext.block_pointers);
8114         if (zext.stream_valid && inflateEnd(&(zext.stream)) != Z_OK) {
8115                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
8116                     "Failed to clean up compressor");
8117                 ret = ARCHIVE_FATAL;
8118         }
8119
8120         return (ret);
8121 }
8122
8123 #else
8124
8125 static int
8126 zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s)
8127 {
8128         (void)buff; /* UNUSED */
8129         (void)s; /* UNUSED */
8130         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Programming error");
8131         return (ARCHIVE_FATAL);
8132 }
8133
8134 static int
8135 zisofs_rewind_boot_file(struct archive_write *a)
8136 {
8137         struct iso9660 *iso9660 = a->format_data;
8138
8139         if (iso9660->el_torito.boot->file->zisofs.header_size != 0) {
8140                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
8141                     "We cannot extract the zisofs imaged boot file;"
8142                     " this may not boot in being zisofs imaged");
8143                 return (ARCHIVE_FAILED);
8144         }
8145         return (ARCHIVE_OK);
8146 }
8147
8148 static int
8149 zisofs_finish_entry(struct archive_write *a)
8150 {
8151         (void)a; /* UNUSED */
8152         return (ARCHIVE_OK);
8153 }
8154
8155 static int
8156 zisofs_free(struct archive_write *a)
8157 {
8158         (void)a; /* UNUSED */
8159         return (ARCHIVE_OK);
8160 }
8161
8162 #endif /* HAVE_ZLIB_H */
8163