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