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