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