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