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