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