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