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