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