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