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