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