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