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