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