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 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 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 int detect_magic:1; 759 int making:1; 760 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 #error no way to get the system identifier on your platform. 2182 #endif 2183 } 2184 2185 static void 2186 set_str(unsigned char *p, const char *s, size_t l, char f, const char *map) 2187 { 2188 unsigned char c; 2189 2190 if (s == NULL) 2191 s = ""; 2192 while ((c = *s++) != 0 && l > 0) { 2193 if (c >= 0x80 || map[c] == 0) 2194 { 2195 /* illegal character */ 2196 if (c >= 'a' && c <= 'z') { 2197 /* convert c from a-z to A-Z */ 2198 c -= 0x20; 2199 } else 2200 c = 0x5f; 2201 } 2202 *p++ = c; 2203 l--; 2204 } 2205 /* If l isn't zero, fill p buffer by the character 2206 * which indicated by f. */ 2207 if (l > 0) 2208 memset(p , f, l); 2209 } 2210 2211 static inline int 2212 joliet_allowed_char(unsigned char high, unsigned char low) 2213 { 2214 int utf16 = (high << 8) | low; 2215 2216 if (utf16 <= 0x001F) 2217 return (0); 2218 2219 switch (utf16) { 2220 case 0x002A: /* '*' */ 2221 case 0x002F: /* '/' */ 2222 case 0x003A: /* ':' */ 2223 case 0x003B: /* ';' */ 2224 case 0x003F: /* '?' */ 2225 case 0x005C: /* '\' */ 2226 return (0);/* Not allowed. */ 2227 } 2228 return (1); 2229 } 2230 2231 static int 2232 set_str_utf16be(struct archive_write *a, unsigned char *p, const char *s, 2233 size_t l, uint16_t uf, enum vdc vdc) 2234 { 2235 size_t size, i; 2236 int onepad; 2237 2238 if (s == NULL) 2239 s = ""; 2240 if (l & 0x01) { 2241 onepad = 1; 2242 l &= ~1; 2243 } else 2244 onepad = 0; 2245 if (vdc == VDC_UCS2) { 2246 struct iso9660 *iso9660 = a->format_data; 2247 if (archive_strncpy_l(&iso9660->utf16be, s, strlen(s), 2248 iso9660->sconv_to_utf16be) != 0 && errno == ENOMEM) { 2249 archive_set_error(&a->archive, ENOMEM, 2250 "Can't allocate memory for UTF-16BE"); 2251 return (ARCHIVE_FATAL); 2252 } 2253 size = iso9660->utf16be.length; 2254 if (size > l) 2255 size = l; 2256 memcpy(p, iso9660->utf16be.s, size); 2257 } else { 2258 const uint16_t *u16 = (const uint16_t *)s; 2259 2260 size = 0; 2261 while (*u16++) 2262 size += 2; 2263 if (size > l) 2264 size = l; 2265 memcpy(p, s, size); 2266 } 2267 for (i = 0; i < size; i += 2, p += 2) { 2268 if (!joliet_allowed_char(p[0], p[1])) 2269 archive_be16enc(p, 0x005F);/* '_' */ 2270 } 2271 l -= size; 2272 while (l > 0) { 2273 archive_be16enc(p, uf); 2274 p += 2; 2275 l -= 2; 2276 } 2277 if (onepad) 2278 *p = 0; 2279 return (ARCHIVE_OK); 2280 } 2281 2282 static const char a_characters_map[0x80] = { 2283 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 2284 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */ 2285 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */ 2286 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20-2F */ 2287 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30-3F */ 2288 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */ 2289 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */ 2290 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 60-6F */ 2291 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 70-7F */ 2292 }; 2293 2294 static const char a1_characters_map[0x80] = { 2295 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 2296 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */ 2297 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */ 2298 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20-2F */ 2299 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30-3F */ 2300 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */ 2301 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */ 2302 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60-6F */ 2303 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,/* 70-7F */ 2304 }; 2305 2306 static const char d_characters_map[0x80] = { 2307 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 2308 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */ 2309 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */ 2310 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 20-2F */ 2311 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,/* 30-3F */ 2312 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */ 2313 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */ 2314 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 60-6F */ 2315 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 70-7F */ 2316 }; 2317 2318 static const char d1_characters_map[0x80] = { 2319 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 2320 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */ 2321 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */ 2322 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 20-2F */ 2323 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,/* 30-3F */ 2324 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */ 2325 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */ 2326 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60-6F */ 2327 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,/* 70-7F */ 2328 }; 2329 2330 static int 2331 set_str_a_characters_bp(struct archive_write *a, unsigned char *bp, 2332 int from, int to, const char *s, enum vdc vdc) 2333 { 2334 int r; 2335 2336 switch (vdc) { 2337 case VDC_STD: 2338 set_str(bp+from, s, to - from + 1, 0x20, 2339 a_characters_map); 2340 r = ARCHIVE_OK; 2341 break; 2342 case VDC_LOWERCASE: 2343 set_str(bp+from, s, to - from + 1, 0x20, 2344 a1_characters_map); 2345 r = ARCHIVE_OK; 2346 break; 2347 case VDC_UCS2: 2348 case VDC_UCS2_DIRECT: 2349 r = set_str_utf16be(a, bp+from, s, to - from + 1, 2350 0x0020, vdc); 2351 break; 2352 default: 2353 r = ARCHIVE_FATAL; 2354 } 2355 return (r); 2356 } 2357 2358 static int 2359 set_str_d_characters_bp(struct archive_write *a, unsigned char *bp, 2360 int from, int to, const char *s, enum vdc vdc) 2361 { 2362 int r; 2363 2364 switch (vdc) { 2365 case VDC_STD: 2366 set_str(bp+from, s, to - from + 1, 0x20, 2367 d_characters_map); 2368 r = ARCHIVE_OK; 2369 break; 2370 case VDC_LOWERCASE: 2371 set_str(bp+from, s, to - from + 1, 0x20, 2372 d1_characters_map); 2373 r = ARCHIVE_OK; 2374 break; 2375 case VDC_UCS2: 2376 case VDC_UCS2_DIRECT: 2377 r = set_str_utf16be(a, bp+from, s, to - from + 1, 2378 0x0020, vdc); 2379 break; 2380 default: 2381 r = ARCHIVE_FATAL; 2382 } 2383 return (r); 2384 } 2385 2386 static void 2387 set_VD_bp(unsigned char *bp, enum VD_type type, unsigned char ver) 2388 { 2389 2390 /* Volume Descriptor Type */ 2391 bp[1] = (unsigned char)type; 2392 /* Standard Identifier */ 2393 memcpy(bp + 2, "CD001", 5); 2394 /* Volume Descriptor Version */ 2395 bp[7] = ver; 2396 } 2397 2398 static inline void 2399 set_unused_field_bp(unsigned char *bp, int from, int to) 2400 { 2401 memset(bp + from, 0, to - from + 1); 2402 } 2403 2404 /* 2405 * 8-bit unsigned numerical values. 2406 * ISO9660 Standard 7.1.1 2407 */ 2408 static inline void 2409 set_num_711(unsigned char *p, unsigned char value) 2410 { 2411 *p = value; 2412 } 2413 2414 /* 2415 * 8-bit signed numerical values. 2416 * ISO9660 Standard 7.1.2 2417 */ 2418 static inline void 2419 set_num_712(unsigned char *p, char value) 2420 { 2421 *((char *)p) = value; 2422 } 2423 2424 /* 2425 * Least significant byte first. 2426 * ISO9660 Standard 7.2.1 2427 */ 2428 static inline void 2429 set_num_721(unsigned char *p, uint16_t value) 2430 { 2431 archive_le16enc(p, value); 2432 } 2433 2434 /* 2435 * Most significant byte first. 2436 * ISO9660 Standard 7.2.2 2437 */ 2438 static inline void 2439 set_num_722(unsigned char *p, uint16_t value) 2440 { 2441 archive_be16enc(p, value); 2442 } 2443 2444 /* 2445 * Both-byte orders. 2446 * ISO9660 Standard 7.2.3 2447 */ 2448 static void 2449 set_num_723(unsigned char *p, uint16_t value) 2450 { 2451 archive_le16enc(p, value); 2452 archive_be16enc(p+2, value); 2453 } 2454 2455 /* 2456 * Least significant byte first. 2457 * ISO9660 Standard 7.3.1 2458 */ 2459 static inline void 2460 set_num_731(unsigned char *p, uint32_t value) 2461 { 2462 archive_le32enc(p, value); 2463 } 2464 2465 /* 2466 * Most significant byte first. 2467 * ISO9660 Standard 7.3.2 2468 */ 2469 static inline void 2470 set_num_732(unsigned char *p, uint32_t value) 2471 { 2472 archive_be32enc(p, value); 2473 } 2474 2475 /* 2476 * Both-byte orders. 2477 * ISO9660 Standard 7.3.3 2478 */ 2479 static inline void 2480 set_num_733(unsigned char *p, uint32_t value) 2481 { 2482 archive_le32enc(p, value); 2483 archive_be32enc(p+4, value); 2484 } 2485 2486 static void 2487 set_digit(unsigned char *p, size_t s, int value) 2488 { 2489 2490 while (s--) { 2491 p[s] = '0' + (value % 10); 2492 value /= 10; 2493 } 2494 } 2495 2496 #if defined(HAVE_STRUCT_TM_TM_GMTOFF) 2497 #define get_gmoffset(tm) ((tm)->tm_gmtoff) 2498 #elif defined(HAVE_STRUCT_TM___TM_GMTOFF) 2499 #define get_gmoffset(tm) ((tm)->__tm_gmtoff) 2500 #else 2501 static long 2502 get_gmoffset(struct tm *tm) 2503 { 2504 long offset; 2505 2506 #if defined(HAVE__GET_TIMEZONE) 2507 _get_timezone(&offset); 2508 #elif defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__) 2509 offset = _timezone; 2510 #else 2511 offset = timezone; 2512 #endif 2513 offset *= -1; 2514 if (tm->tm_isdst) 2515 offset += 3600; 2516 return (offset); 2517 } 2518 #endif 2519 2520 static void 2521 get_tmfromtime(struct tm *tm, time_t *t) 2522 { 2523 #if HAVE_LOCALTIME_R 2524 tzset(); 2525 localtime_r(t, tm); 2526 #elif HAVE__LOCALTIME64_S 2527 __time64_t tmp_t = (__time64_t) *t; //time_t may be shorter than 64 bits 2528 _localtime64_s(tm, &tmp_t); 2529 #else 2530 memcpy(tm, localtime(t), sizeof(*tm)); 2531 #endif 2532 } 2533 2534 /* 2535 * Date and Time Format. 2536 * ISO9660 Standard 8.4.26.1 2537 */ 2538 static void 2539 set_date_time(unsigned char *p, time_t t) 2540 { 2541 struct tm tm; 2542 2543 get_tmfromtime(&tm, &t); 2544 set_digit(p, 4, tm.tm_year + 1900); 2545 set_digit(p+4, 2, tm.tm_mon + 1); 2546 set_digit(p+6, 2, tm.tm_mday); 2547 set_digit(p+8, 2, tm.tm_hour); 2548 set_digit(p+10, 2, tm.tm_min); 2549 set_digit(p+12, 2, tm.tm_sec); 2550 set_digit(p+14, 2, 0); 2551 set_num_712(p+16, (char)(get_gmoffset(&tm)/(60*15))); 2552 } 2553 2554 static void 2555 set_date_time_null(unsigned char *p) 2556 { 2557 memset(p, (int)'0', 16); 2558 p[16] = 0; 2559 } 2560 2561 static void 2562 set_time_915(unsigned char *p, time_t t) 2563 { 2564 struct tm tm; 2565 2566 get_tmfromtime(&tm, &t); 2567 set_num_711(p+0, tm.tm_year); 2568 set_num_711(p+1, tm.tm_mon+1); 2569 set_num_711(p+2, tm.tm_mday); 2570 set_num_711(p+3, tm.tm_hour); 2571 set_num_711(p+4, tm.tm_min); 2572 set_num_711(p+5, tm.tm_sec); 2573 set_num_712(p+6, (char)(get_gmoffset(&tm)/(60*15))); 2574 } 2575 2576 2577 /* 2578 * Write SUSP "CE" System Use Entry. 2579 */ 2580 static int 2581 set_SUSP_CE(unsigned char *p, int location, int offset, int size) 2582 { 2583 unsigned char *bp = p -1; 2584 /* Extend the System Use Area 2585 * "CE" Format: 2586 * len ver 2587 * +----+----+----+----+-----------+-----------+ 2588 * | 'C'| 'E'| 1C | 01 | LOCATION1 | LOCATION2 | 2589 * +----+----+----+----+-----------+-----------+ 2590 * 0 1 2 3 4 12 20 2591 * +-----------+ 2592 * | LOCATION3 | 2593 * +-----------+ 2594 * 20 28 2595 * LOCATION1 : Location of Continuation of System Use Area. 2596 * LOCATION2 : Offset to Start of Continuation. 2597 * LOCATION3 : Length of the Continuation. 2598 */ 2599 2600 bp[1] = 'C'; 2601 bp[2] = 'E'; 2602 bp[3] = RR_CE_SIZE; /* length */ 2603 bp[4] = 1; /* version */ 2604 set_num_733(bp+5, location); 2605 set_num_733(bp+13, offset); 2606 set_num_733(bp+21, size); 2607 return (RR_CE_SIZE); 2608 } 2609 2610 /* 2611 * The functions, which names are beginning with extra_, are used to 2612 * control extra records. 2613 * The maximum size of a Directory Record is 254. When a filename is 2614 * very long, all of RRIP data of a file won't stored to the Directory 2615 * Record and so remaining RRIP data store to an extra record instead. 2616 */ 2617 static unsigned char * 2618 extra_open_record(unsigned char *bp, int dr_len, struct isoent *isoent, 2619 struct ctl_extr_rec *ctl) 2620 { 2621 ctl->bp = bp; 2622 if (bp != NULL) 2623 bp += dr_len; 2624 ctl->use_extr = 0; 2625 ctl->isoent = isoent; 2626 ctl->ce_ptr = NULL; 2627 ctl->cur_len = ctl->dr_len = dr_len; 2628 ctl->limit = DR_LIMIT; 2629 2630 return (bp); 2631 } 2632 2633 static void 2634 extra_close_record(struct ctl_extr_rec *ctl, int ce_size) 2635 { 2636 int padding = 0; 2637 2638 if (ce_size > 0) 2639 extra_tell_used_size(ctl, ce_size); 2640 /* Padding. */ 2641 if (ctl->cur_len & 0x01) { 2642 ctl->cur_len++; 2643 if (ctl->bp != NULL) 2644 ctl->bp[ctl->cur_len] = 0; 2645 padding = 1; 2646 } 2647 if (ctl->use_extr) { 2648 if (ctl->ce_ptr != NULL) 2649 set_SUSP_CE(ctl->ce_ptr, ctl->extr_loc, 2650 ctl->extr_off, ctl->cur_len - padding); 2651 } else 2652 ctl->dr_len = ctl->cur_len; 2653 } 2654 2655 #define extra_space(ctl) ((ctl)->limit - (ctl)->cur_len) 2656 2657 static unsigned char * 2658 extra_next_record(struct ctl_extr_rec *ctl, int length) 2659 { 2660 int cur_len = ctl->cur_len;/* save cur_len */ 2661 2662 /* Close the current extra record or Directory Record. */ 2663 extra_close_record(ctl, RR_CE_SIZE); 2664 2665 /* Get a next extra record. */ 2666 ctl->use_extr = 1; 2667 if (ctl->bp != NULL) { 2668 /* Storing data into an extra record. */ 2669 unsigned char *p; 2670 2671 /* Save the pointer where a CE extension will be 2672 * stored to. */ 2673 ctl->ce_ptr = &ctl->bp[cur_len+1]; 2674 p = extra_get_record(ctl->isoent, 2675 &ctl->limit, &ctl->extr_off, &ctl->extr_loc); 2676 ctl->bp = p - 1;/* the base of bp offset is 1. */ 2677 } else 2678 /* Calculating the size of an extra record. */ 2679 (void)extra_get_record(ctl->isoent, 2680 &ctl->limit, NULL, NULL); 2681 ctl->cur_len = 0; 2682 /* Check if an extra record is almost full. 2683 * If so, get a next one. */ 2684 if (extra_space(ctl) < length) 2685 (void)extra_next_record(ctl, length); 2686 2687 return (ctl->bp); 2688 } 2689 2690 static inline struct extr_rec * 2691 extra_last_record(struct isoent *isoent) 2692 { 2693 if (isoent->extr_rec_list.first == NULL) 2694 return (NULL); 2695 return ((struct extr_rec *)(void *) 2696 ((char *)(isoent->extr_rec_list.last) 2697 - offsetof(struct extr_rec, next))); 2698 } 2699 2700 static unsigned char * 2701 extra_get_record(struct isoent *isoent, int *space, int *off, int *loc) 2702 { 2703 struct extr_rec *rec; 2704 2705 isoent = isoent->parent; 2706 if (off != NULL) { 2707 /* Storing data into an extra record. */ 2708 rec = isoent->extr_rec_list.current; 2709 if (DR_SAFETY > LOGICAL_BLOCK_SIZE - rec->offset) 2710 rec = rec->next; 2711 } else { 2712 /* Calculating the size of an extra record. */ 2713 rec = extra_last_record(isoent); 2714 if (rec == NULL || 2715 DR_SAFETY > LOGICAL_BLOCK_SIZE - rec->offset) { 2716 rec = malloc(sizeof(*rec)); 2717 if (rec == NULL) 2718 return (NULL); 2719 rec->location = 0; 2720 rec->offset = 0; 2721 /* Insert `rec` into the tail of isoent->extr_rec_list */ 2722 rec->next = NULL; 2723 /* 2724 * Note: testing isoent->extr_rec_list.last == NULL 2725 * here is really unneeded since it has been already 2726 * initialized at isoent_new function but Clang Static 2727 * Analyzer claims that it is dereference of null 2728 * pointer. 2729 */ 2730 if (isoent->extr_rec_list.last == NULL) 2731 isoent->extr_rec_list.last = 2732 &(isoent->extr_rec_list.first); 2733 *isoent->extr_rec_list.last = rec; 2734 isoent->extr_rec_list.last = &(rec->next); 2735 } 2736 } 2737 *space = LOGICAL_BLOCK_SIZE - rec->offset - DR_SAFETY; 2738 if (*space & 0x01) 2739 *space -= 1;/* Keep padding space. */ 2740 if (off != NULL) 2741 *off = rec->offset; 2742 if (loc != NULL) 2743 *loc = rec->location; 2744 isoent->extr_rec_list.current = rec; 2745 2746 return (&rec->buf[rec->offset]); 2747 } 2748 2749 static void 2750 extra_tell_used_size(struct ctl_extr_rec *ctl, int size) 2751 { 2752 struct isoent *isoent; 2753 struct extr_rec *rec; 2754 2755 if (ctl->use_extr) { 2756 isoent = ctl->isoent->parent; 2757 rec = isoent->extr_rec_list.current; 2758 if (rec != NULL) 2759 rec->offset += size; 2760 } 2761 ctl->cur_len += size; 2762 } 2763 2764 static int 2765 extra_setup_location(struct isoent *isoent, int location) 2766 { 2767 struct extr_rec *rec; 2768 int cnt; 2769 2770 cnt = 0; 2771 rec = isoent->extr_rec_list.first; 2772 isoent->extr_rec_list.current = rec; 2773 while (rec) { 2774 cnt++; 2775 rec->location = location++; 2776 rec->offset = 0; 2777 rec = rec->next; 2778 } 2779 return (cnt); 2780 } 2781 2782 /* 2783 * Create the RRIP entries. 2784 */ 2785 static int 2786 set_directory_record_rr(unsigned char *bp, int dr_len, 2787 struct isoent *isoent, struct iso9660 *iso9660, enum dir_rec_type t) 2788 { 2789 /* Flags(BP 5) of the Rockridge "RR" System Use Field */ 2790 unsigned char rr_flag; 2791 #define RR_USE_PX 0x01 2792 #define RR_USE_PN 0x02 2793 #define RR_USE_SL 0x04 2794 #define RR_USE_NM 0x08 2795 #define RR_USE_CL 0x10 2796 #define RR_USE_PL 0x20 2797 #define RR_USE_RE 0x40 2798 #define RR_USE_TF 0x80 2799 int length; 2800 struct ctl_extr_rec ctl; 2801 struct isoent *rr_parent, *pxent; 2802 struct isofile *file; 2803 2804 bp = extra_open_record(bp, dr_len, isoent, &ctl); 2805 2806 if (t == DIR_REC_PARENT) { 2807 rr_parent = isoent->rr_parent; 2808 pxent = isoent->parent; 2809 if (rr_parent != NULL) 2810 isoent = rr_parent; 2811 else 2812 isoent = isoent->parent; 2813 } else { 2814 rr_parent = NULL; 2815 pxent = isoent; 2816 } 2817 file = isoent->file; 2818 2819 if (t != DIR_REC_NORMAL) { 2820 rr_flag = RR_USE_PX | RR_USE_TF; 2821 if (rr_parent != NULL) 2822 rr_flag |= RR_USE_PL; 2823 } else { 2824 rr_flag = RR_USE_PX | RR_USE_NM | RR_USE_TF; 2825 if (archive_entry_filetype(file->entry) == AE_IFLNK) 2826 rr_flag |= RR_USE_SL; 2827 if (isoent->rr_parent != NULL) 2828 rr_flag |= RR_USE_RE; 2829 if (isoent->rr_child != NULL) 2830 rr_flag |= RR_USE_CL; 2831 if (archive_entry_filetype(file->entry) == AE_IFCHR || 2832 archive_entry_filetype(file->entry) == AE_IFBLK) 2833 rr_flag |= RR_USE_PN; 2834 #ifdef COMPAT_MKISOFS 2835 /* 2836 * mkisofs 2.01.01a63 records "RE" extension to 2837 * the entry of "rr_moved" directory. 2838 * I don't understand this behavior. 2839 */ 2840 if (isoent->virtual && 2841 isoent->parent == iso9660->primary.rootent && 2842 strcmp(isoent->file->basename.s, "rr_moved") == 0) 2843 rr_flag |= RR_USE_RE; 2844 #endif 2845 } 2846 2847 /* Write "SP" System Use Entry. */ 2848 if (t == DIR_REC_SELF && isoent == isoent->parent) { 2849 length = 7; 2850 if (bp != NULL) { 2851 bp[1] = 'S'; 2852 bp[2] = 'P'; 2853 bp[3] = length; 2854 bp[4] = 1; /* version */ 2855 bp[5] = 0xBE; /* Check Byte */ 2856 bp[6] = 0xEF; /* Check Byte */ 2857 bp[7] = 0; 2858 bp += length; 2859 } 2860 extra_tell_used_size(&ctl, length); 2861 } 2862 2863 /* Write "RR" System Use Entry. */ 2864 length = 5; 2865 if (extra_space(&ctl) < length) 2866 bp = extra_next_record(&ctl, length); 2867 if (bp != NULL) { 2868 bp[1] = 'R'; 2869 bp[2] = 'R'; 2870 bp[3] = length; 2871 bp[4] = 1; /* version */ 2872 bp[5] = rr_flag; 2873 bp += length; 2874 } 2875 extra_tell_used_size(&ctl, length); 2876 2877 /* Write "NM" System Use Entry. */ 2878 if (rr_flag & RR_USE_NM) { 2879 /* 2880 * "NM" Format: 2881 * e.g. a basename is 'foo' 2882 * len ver flg 2883 * +----+----+----+----+----+----+----+----+ 2884 * | 'N'| 'M'| 08 | 01 | 00 | 'f'| 'o'| 'o'| 2885 * +----+----+----+----+----+----+----+----+ 2886 * <----------------- len -----------------> 2887 */ 2888 size_t nmlen = file->basename.length; 2889 const char *nm = file->basename.s; 2890 size_t nmmax; 2891 2892 if (extra_space(&ctl) < 6) 2893 bp = extra_next_record(&ctl, 6); 2894 if (bp != NULL) { 2895 bp[1] = 'N'; 2896 bp[2] = 'M'; 2897 bp[4] = 1; /* version */ 2898 } 2899 nmmax = extra_space(&ctl); 2900 if (nmmax > 0xff) 2901 nmmax = 0xff; 2902 while (nmlen + 5 > nmmax) { 2903 length = (int)nmmax; 2904 if (bp != NULL) { 2905 bp[3] = length; 2906 bp[5] = 0x01;/* Alternate Name continues 2907 * in next "NM" field */ 2908 memcpy(bp+6, nm, length - 5); 2909 bp += length; 2910 } 2911 nmlen -= length - 5; 2912 nm += length - 5; 2913 extra_tell_used_size(&ctl, length); 2914 if (extra_space(&ctl) < 6) { 2915 bp = extra_next_record(&ctl, 6); 2916 nmmax = extra_space(&ctl); 2917 if (nmmax > 0xff) 2918 nmmax = 0xff; 2919 } 2920 if (bp != NULL) { 2921 bp[1] = 'N'; 2922 bp[2] = 'M'; 2923 bp[4] = 1; /* version */ 2924 } 2925 } 2926 length = 5 + (int)nmlen; 2927 if (bp != NULL) { 2928 bp[3] = length; 2929 bp[5] = 0; 2930 memcpy(bp+6, nm, nmlen); 2931 bp += length; 2932 } 2933 extra_tell_used_size(&ctl, length); 2934 } 2935 2936 /* Write "PX" System Use Entry. */ 2937 if (rr_flag & RR_USE_PX) { 2938 /* 2939 * "PX" Format: 2940 * len ver 2941 * +----+----+----+----+-----------+-----------+ 2942 * | 'P'| 'X'| 2C | 01 | FILE MODE | LINKS | 2943 * +----+----+----+----+-----------+-----------+ 2944 * 0 1 2 3 4 12 20 2945 * +-----------+-----------+------------------+ 2946 * | USER ID | GROUP ID |FILE SERIAL NUMBER| 2947 * +-----------+-----------+------------------+ 2948 * 20 28 36 44 2949 */ 2950 length = 44; 2951 if (extra_space(&ctl) < length) 2952 bp = extra_next_record(&ctl, length); 2953 if (bp != NULL) { 2954 mode_t mode; 2955 int64_t uid; 2956 int64_t gid; 2957 2958 mode = archive_entry_mode(file->entry); 2959 uid = archive_entry_uid(file->entry); 2960 gid = archive_entry_gid(file->entry); 2961 if (iso9660->opt.rr == OPT_RR_USEFUL) { 2962 /* 2963 * This action is similar to mkisofs -r option 2964 * but our rockridge=useful option does not 2965 * set a zero to uid and gid. 2966 */ 2967 /* set all read bit ON */ 2968 mode |= 0444; 2969 #if !defined(_WIN32) && !defined(__CYGWIN__) 2970 if (mode & 0111) 2971 #endif 2972 /* set all exec bit ON */ 2973 mode |= 0111; 2974 /* clear all write bits. */ 2975 mode &= ~0222; 2976 /* clear setuid,setgid,sticky bits. */ 2977 mode &= ~07000; 2978 } 2979 2980 bp[1] = 'P'; 2981 bp[2] = 'X'; 2982 bp[3] = length; 2983 bp[4] = 1; /* version */ 2984 /* file mode */ 2985 set_num_733(bp+5, mode); 2986 /* file links (stat.st_nlink) */ 2987 set_num_733(bp+13, 2988 archive_entry_nlink(file->entry)); 2989 set_num_733(bp+21, (uint32_t)uid); 2990 set_num_733(bp+29, (uint32_t)gid); 2991 /* File Serial Number */ 2992 if (pxent->dir) 2993 set_num_733(bp+37, pxent->dir_location); 2994 else if (file->hardlink_target != NULL) 2995 set_num_733(bp+37, 2996 file->hardlink_target->cur_content->location); 2997 else 2998 set_num_733(bp+37, 2999 file->cur_content->location); 3000 bp += length; 3001 } 3002 extra_tell_used_size(&ctl, length); 3003 } 3004 3005 /* Write "SL" System Use Entry. */ 3006 if (rr_flag & RR_USE_SL) { 3007 /* 3008 * "SL" Format: 3009 * e.g. a symbolic name is 'foo/bar' 3010 * len ver flg 3011 * +----+----+----+----+----+------------+ 3012 * | 'S'| 'L'| 0F | 01 | 00 | components | 3013 * +----+----+----+----+----+-----+------+ 3014 * 0 1 2 3 4 5 ...|... 15 3015 * <----------------- len --------+------> 3016 * components : | 3017 * cflg clen | 3018 * +----+----+----+----+----+ | 3019 * | 00 | 03 | 'f'| 'o'| 'o'| <---+ 3020 * +----+----+----+----+----+ | 3021 * 5 6 7 8 9 10 | 3022 * cflg clen | 3023 * +----+----+----+----+----+ | 3024 * | 00 | 03 | 'b'| 'a'| 'r'| <---+ 3025 * +----+----+----+----+----+ 3026 * 10 11 12 13 14 15 3027 * 3028 * - cflg : flag of component 3029 * - clen : length of component 3030 */ 3031 const char *sl; 3032 char sl_last; 3033 3034 if (extra_space(&ctl) < 7) 3035 bp = extra_next_record(&ctl, 7); 3036 sl = file->symlink.s; 3037 sl_last = '\0'; 3038 if (bp != NULL) { 3039 bp[1] = 'S'; 3040 bp[2] = 'L'; 3041 bp[4] = 1; /* version */ 3042 } 3043 for (;;) { 3044 unsigned char *nc, *cf, *cl, cldmy = 0; 3045 int sllen, slmax; 3046 3047 slmax = extra_space(&ctl); 3048 if (slmax > 0xff) 3049 slmax = 0xff; 3050 if (bp != NULL) 3051 nc = &bp[6]; 3052 else 3053 nc = NULL; 3054 cf = cl = NULL; 3055 sllen = 0; 3056 while (*sl && sllen + 11 < slmax) { 3057 if (sl_last == '\0' && sl[0] == '/') { 3058 /* 3059 * flg len 3060 * +----+----+ 3061 * | 08 | 00 | ROOT component. 3062 * +----+----+ ("/") 3063 * 3064 * Root component has to appear 3065 * at the first component only. 3066 */ 3067 if (nc != NULL) { 3068 cf = nc++; 3069 *cf = 0x08; /* ROOT */ 3070 *nc++ = 0; 3071 } 3072 sllen += 2; 3073 sl++; 3074 sl_last = '/'; 3075 cl = NULL; 3076 continue; 3077 } 3078 if (((sl_last == '\0' || sl_last == '/') && 3079 sl[0] == '.' && sl[1] == '.' && 3080 (sl[2] == '/' || sl[2] == '\0')) || 3081 (sl[0] == '/' && 3082 sl[1] == '.' && sl[2] == '.' && 3083 (sl[3] == '/' || sl[3] == '\0'))) { 3084 /* 3085 * flg len 3086 * +----+----+ 3087 * | 04 | 00 | PARENT component. 3088 * +----+----+ ("..") 3089 */ 3090 if (nc != NULL) { 3091 cf = nc++; 3092 *cf = 0x04; /* PARENT */ 3093 *nc++ = 0; 3094 } 3095 sllen += 2; 3096 if (sl[0] == '/') 3097 sl += 3;/* skip "/.." */ 3098 else 3099 sl += 2;/* skip ".." */ 3100 sl_last = '.'; 3101 cl = NULL; 3102 continue; 3103 } 3104 if (((sl_last == '\0' || sl_last == '/') && 3105 sl[0] == '.' && 3106 (sl[1] == '/' || sl[1] == '\0')) || 3107 (sl[0] == '/' && sl[1] == '.' && 3108 (sl[2] == '/' || sl[2] == '\0'))) { 3109 /* 3110 * flg len 3111 * +----+----+ 3112 * | 02 | 00 | CURRENT component. 3113 * +----+----+ (".") 3114 */ 3115 if (nc != NULL) { 3116 cf = nc++; 3117 *cf = 0x02; /* CURRENT */ 3118 *nc++ = 0; 3119 } 3120 sllen += 2; 3121 if (sl[0] == '/') 3122 sl += 2;/* skip "/." */ 3123 else 3124 sl ++; /* skip "." */ 3125 sl_last = '.'; 3126 cl = NULL; 3127 continue; 3128 } 3129 if (sl[0] == '/' || cl == NULL) { 3130 if (nc != NULL) { 3131 cf = nc++; 3132 *cf = 0; 3133 cl = nc++; 3134 *cl = 0; 3135 } else 3136 cl = &cldmy; 3137 sllen += 2; 3138 if (sl[0] == '/') { 3139 sl_last = *sl++; 3140 continue; 3141 } 3142 } 3143 sl_last = *sl++; 3144 if (nc != NULL) { 3145 *nc++ = sl_last; 3146 (*cl) ++; 3147 } 3148 sllen++; 3149 } 3150 if (*sl) { 3151 length = 5 + sllen; 3152 if (bp != NULL) { 3153 /* 3154 * Mark flg as CONTINUE component. 3155 */ 3156 *cf |= 0x01; 3157 /* 3158 * len ver flg 3159 * +----+----+----+----+----+- 3160 * | 'S'| 'L'| XX | 01 | 01 | 3161 * +----+----+----+----+----+- 3162 * ^ 3163 * continues in next "SL" 3164 */ 3165 bp[3] = length; 3166 bp[5] = 0x01;/* This Symbolic Link 3167 * continues in next 3168 * "SL" field */ 3169 bp += length; 3170 } 3171 extra_tell_used_size(&ctl, length); 3172 if (extra_space(&ctl) < 11) 3173 bp = extra_next_record(&ctl, 11); 3174 if (bp != NULL) { 3175 /* Next 'SL' */ 3176 bp[1] = 'S'; 3177 bp[2] = 'L'; 3178 bp[4] = 1; /* version */ 3179 } 3180 } else { 3181 length = 5 + sllen; 3182 if (bp != NULL) { 3183 bp[3] = length; 3184 bp[5] = 0; 3185 bp += length; 3186 } 3187 extra_tell_used_size(&ctl, length); 3188 break; 3189 } 3190 } 3191 } 3192 3193 /* Write "TF" System Use Entry. */ 3194 if (rr_flag & RR_USE_TF) { 3195 /* 3196 * "TF" Format: 3197 * len ver 3198 * +----+----+----+----+-----+-------------+ 3199 * | 'T'| 'F'| XX | 01 |FLAGS| TIME STAMPS | 3200 * +----+----+----+----+-----+-------------+ 3201 * 0 1 2 3 4 5 XX 3202 * TIME STAMPS : ISO 9660 Standard 9.1.5. 3203 * If TF_LONG_FORM FLAGS is set, 3204 * use ISO9660 Standard 8.4.26.1. 3205 */ 3206 #define TF_CREATION 0x01 /* Creation time recorded */ 3207 #define TF_MODIFY 0x02 /* Modification time recorded */ 3208 #define TF_ACCESS 0x04 /* Last Access time recorded */ 3209 #define TF_ATTRIBUTES 0x08 /* Last Attribute Change time recorded */ 3210 #define TF_BACKUP 0x10 /* Last Backup time recorded */ 3211 #define TF_EXPIRATION 0x20 /* Expiration time recorded */ 3212 #define TF_EFFECTIVE 0x40 /* Effective time recorded */ 3213 #define TF_LONG_FORM 0x80 /* ISO 9660 17-byte time format used */ 3214 unsigned char tf_flags; 3215 3216 length = 5; 3217 tf_flags = 0; 3218 #ifndef COMPAT_MKISOFS 3219 if (archive_entry_birthtime_is_set(file->entry) && 3220 archive_entry_birthtime(file->entry) <= 3221 archive_entry_mtime(file->entry)) { 3222 length += 7; 3223 tf_flags |= TF_CREATION; 3224 } 3225 #endif 3226 if (archive_entry_mtime_is_set(file->entry)) { 3227 length += 7; 3228 tf_flags |= TF_MODIFY; 3229 } 3230 if (archive_entry_atime_is_set(file->entry)) { 3231 length += 7; 3232 tf_flags |= TF_ACCESS; 3233 } 3234 if (archive_entry_ctime_is_set(file->entry)) { 3235 length += 7; 3236 tf_flags |= TF_ATTRIBUTES; 3237 } 3238 if (extra_space(&ctl) < length) 3239 bp = extra_next_record(&ctl, length); 3240 if (bp != NULL) { 3241 bp[1] = 'T'; 3242 bp[2] = 'F'; 3243 bp[3] = length; 3244 bp[4] = 1; /* version */ 3245 bp[5] = tf_flags; 3246 bp += 5; 3247 /* Creation time */ 3248 if (tf_flags & TF_CREATION) { 3249 set_time_915(bp+1, 3250 archive_entry_birthtime(file->entry)); 3251 bp += 7; 3252 } 3253 /* Modification time */ 3254 if (tf_flags & TF_MODIFY) { 3255 set_time_915(bp+1, 3256 archive_entry_mtime(file->entry)); 3257 bp += 7; 3258 } 3259 /* Last Access time */ 3260 if (tf_flags & TF_ACCESS) { 3261 set_time_915(bp+1, 3262 archive_entry_atime(file->entry)); 3263 bp += 7; 3264 } 3265 /* Last Attribute Change time */ 3266 if (tf_flags & TF_ATTRIBUTES) { 3267 set_time_915(bp+1, 3268 archive_entry_ctime(file->entry)); 3269 bp += 7; 3270 } 3271 } 3272 extra_tell_used_size(&ctl, length); 3273 } 3274 3275 /* Write "RE" System Use Entry. */ 3276 if (rr_flag & RR_USE_RE) { 3277 /* 3278 * "RE" Format: 3279 * len ver 3280 * +----+----+----+----+ 3281 * | 'R'| 'E'| 04 | 01 | 3282 * +----+----+----+----+ 3283 * 0 1 2 3 4 3284 */ 3285 length = 4; 3286 if (extra_space(&ctl) < length) 3287 bp = extra_next_record(&ctl, length); 3288 if (bp != NULL) { 3289 bp[1] = 'R'; 3290 bp[2] = 'E'; 3291 bp[3] = length; 3292 bp[4] = 1; /* version */ 3293 bp += length; 3294 } 3295 extra_tell_used_size(&ctl, length); 3296 } 3297 3298 /* Write "PL" System Use Entry. */ 3299 if (rr_flag & RR_USE_PL) { 3300 /* 3301 * "PL" Format: 3302 * len ver 3303 * +----+----+----+----+------------+ 3304 * | 'P'| 'L'| 0C | 01 | *LOCATION | 3305 * +----+----+----+----+------------+ 3306 * 0 1 2 3 4 12 3307 * *LOCATION: location of parent directory 3308 */ 3309 length = 12; 3310 if (extra_space(&ctl) < length) 3311 bp = extra_next_record(&ctl, length); 3312 if (bp != NULL) { 3313 bp[1] = 'P'; 3314 bp[2] = 'L'; 3315 bp[3] = length; 3316 bp[4] = 1; /* version */ 3317 set_num_733(bp + 5, 3318 rr_parent->dir_location); 3319 bp += length; 3320 } 3321 extra_tell_used_size(&ctl, length); 3322 } 3323 3324 /* Write "CL" System Use Entry. */ 3325 if (rr_flag & RR_USE_CL) { 3326 /* 3327 * "CL" Format: 3328 * len ver 3329 * +----+----+----+----+------------+ 3330 * | 'C'| 'L'| 0C | 01 | *LOCATION | 3331 * +----+----+----+----+------------+ 3332 * 0 1 2 3 4 12 3333 * *LOCATION: location of child directory 3334 */ 3335 length = 12; 3336 if (extra_space(&ctl) < length) 3337 bp = extra_next_record(&ctl, length); 3338 if (bp != NULL) { 3339 bp[1] = 'C'; 3340 bp[2] = 'L'; 3341 bp[3] = length; 3342 bp[4] = 1; /* version */ 3343 set_num_733(bp + 5, 3344 isoent->rr_child->dir_location); 3345 bp += length; 3346 } 3347 extra_tell_used_size(&ctl, length); 3348 } 3349 3350 /* Write "PN" System Use Entry. */ 3351 if (rr_flag & RR_USE_PN) { 3352 /* 3353 * "PN" Format: 3354 * len ver 3355 * +----+----+----+----+------------+------------+ 3356 * | 'P'| 'N'| 14 | 01 | dev_t high | dev_t low | 3357 * +----+----+----+----+------------+------------+ 3358 * 0 1 2 3 4 12 20 3359 */ 3360 length = 20; 3361 if (extra_space(&ctl) < length) 3362 bp = extra_next_record(&ctl, length); 3363 if (bp != NULL) { 3364 uint64_t dev; 3365 3366 bp[1] = 'P'; 3367 bp[2] = 'N'; 3368 bp[3] = length; 3369 bp[4] = 1; /* version */ 3370 dev = (uint64_t)archive_entry_rdev(file->entry); 3371 set_num_733(bp + 5, (uint32_t)(dev >> 32)); 3372 set_num_733(bp + 13, (uint32_t)(dev & 0xFFFFFFFF)); 3373 bp += length; 3374 } 3375 extra_tell_used_size(&ctl, length); 3376 } 3377 3378 /* Write "ZF" System Use Entry. */ 3379 if (file->zisofs.header_size) { 3380 /* 3381 * "ZF" Format: 3382 * len ver 3383 * +----+----+----+----+----+----+-------------+ 3384 * | 'Z'| 'F'| 10 | 01 | 'p'| 'z'| Header Size | 3385 * +----+----+----+----+----+----+-------------+ 3386 * 0 1 2 3 4 5 6 7 3387 * +--------------------+-------------------+ 3388 * | Log2 of block Size | Uncompressed Size | 3389 * +--------------------+-------------------+ 3390 * 7 8 16 3391 */ 3392 length = 16; 3393 if (extra_space(&ctl) < length) 3394 bp = extra_next_record(&ctl, length); 3395 if (bp != NULL) { 3396 bp[1] = 'Z'; 3397 bp[2] = 'F'; 3398 bp[3] = length; 3399 bp[4] = 1; /* version */ 3400 bp[5] = 'p'; 3401 bp[6] = 'z'; 3402 bp[7] = file->zisofs.header_size; 3403 bp[8] = file->zisofs.log2_bs; 3404 set_num_733(bp + 9, file->zisofs.uncompressed_size); 3405 bp += length; 3406 } 3407 extra_tell_used_size(&ctl, length); 3408 } 3409 3410 /* Write "CE" System Use Entry. */ 3411 if (t == DIR_REC_SELF && isoent == isoent->parent) { 3412 length = RR_CE_SIZE; 3413 if (bp != NULL) 3414 set_SUSP_CE(bp+1, iso9660->location_rrip_er, 3415 0, RRIP_ER_SIZE); 3416 extra_tell_used_size(&ctl, length); 3417 } 3418 3419 extra_close_record(&ctl, 0); 3420 3421 return (ctl.dr_len); 3422 } 3423 3424 /* 3425 * Write data of a Directory Record or calculate writing bytes itself. 3426 * If parameter `p' is NULL, calculates the size of writing data, which 3427 * a Directory Record needs to write, then it saved and return 3428 * the calculated size. 3429 * Parameter `n' is a remaining size of buffer. when parameter `p' is 3430 * not NULL, check whether that `n' is not less than the saved size. 3431 * if that `n' is small, return zero. 3432 * 3433 * This format of the Directory Record is according to 3434 * ISO9660 Standard 9.1 3435 */ 3436 static int 3437 set_directory_record(unsigned char *p, size_t n, struct isoent *isoent, 3438 struct iso9660 *iso9660, enum dir_rec_type t, 3439 enum vdd_type vdd_type) 3440 { 3441 unsigned char *bp; 3442 size_t dr_len; 3443 size_t fi_len; 3444 3445 if (p != NULL) { 3446 /* 3447 * Check whether a write buffer size is less than the 3448 * saved size which is needed to write this Directory 3449 * Record. 3450 */ 3451 switch (t) { 3452 case DIR_REC_VD: 3453 dr_len = isoent->dr_len.vd; break; 3454 case DIR_REC_SELF: 3455 dr_len = isoent->dr_len.self; break; 3456 case DIR_REC_PARENT: 3457 dr_len = isoent->dr_len.parent; break; 3458 case DIR_REC_NORMAL: 3459 default: 3460 dr_len = isoent->dr_len.normal; break; 3461 } 3462 if (dr_len > n) 3463 return (0);/* Needs more buffer size. */ 3464 } 3465 3466 if (t == DIR_REC_NORMAL && isoent->identifier != NULL) 3467 fi_len = isoent->id_len; 3468 else 3469 fi_len = 1; 3470 3471 if (p != NULL) { 3472 struct isoent *xisoent; 3473 struct isofile *file; 3474 unsigned char flag; 3475 3476 if (t == DIR_REC_PARENT) 3477 xisoent = isoent->parent; 3478 else 3479 xisoent = isoent; 3480 file = isoent->file; 3481 if (file->hardlink_target != NULL) 3482 file = file->hardlink_target; 3483 /* Make a file flag. */ 3484 if (xisoent->dir) 3485 flag = FILE_FLAG_DIRECTORY; 3486 else { 3487 if (file->cur_content->next != NULL) 3488 flag = FILE_FLAG_MULTI_EXTENT; 3489 else 3490 flag = 0; 3491 } 3492 3493 bp = p -1; 3494 /* Extended Attribute Record Length */ 3495 set_num_711(bp+2, 0); 3496 /* Location of Extent */ 3497 if (xisoent->dir) 3498 set_num_733(bp+3, xisoent->dir_location); 3499 else 3500 set_num_733(bp+3, file->cur_content->location); 3501 /* Data Length */ 3502 if (xisoent->dir) 3503 set_num_733(bp+11, 3504 xisoent->dir_block * LOGICAL_BLOCK_SIZE); 3505 else 3506 set_num_733(bp+11, (uint32_t)file->cur_content->size); 3507 /* Recording Date and Time */ 3508 /* NOTE: 3509 * If a file type is symbolic link, you are seeing this 3510 * field value is different from a value mkisofs makes. 3511 * libarchive uses lstat to get this one, but it 3512 * seems mkisofs uses stat to get. 3513 */ 3514 set_time_915(bp+19, 3515 archive_entry_mtime(xisoent->file->entry)); 3516 /* File Flags */ 3517 bp[26] = flag; 3518 /* File Unit Size */ 3519 set_num_711(bp+27, 0); 3520 /* Interleave Gap Size */ 3521 set_num_711(bp+28, 0); 3522 /* Volume Sequence Number */ 3523 set_num_723(bp+29, iso9660->volume_sequence_number); 3524 /* Length of File Identifier */ 3525 set_num_711(bp+33, (unsigned char)fi_len); 3526 /* File Identifier */ 3527 switch (t) { 3528 case DIR_REC_VD: 3529 case DIR_REC_SELF: 3530 set_num_711(bp+34, 0); 3531 break; 3532 case DIR_REC_PARENT: 3533 set_num_711(bp+34, 1); 3534 break; 3535 case DIR_REC_NORMAL: 3536 if (isoent->identifier != NULL) 3537 memcpy(bp+34, isoent->identifier, fi_len); 3538 else 3539 set_num_711(bp+34, 0); 3540 break; 3541 } 3542 } else 3543 bp = NULL; 3544 dr_len = 33 + fi_len; 3545 /* Padding Field */ 3546 if (dr_len & 0x01) { 3547 dr_len ++; 3548 if (p != NULL) 3549 bp[dr_len] = 0; 3550 } 3551 3552 /* Volume Descriptor does not record extension. */ 3553 if (t == DIR_REC_VD) { 3554 if (p != NULL) 3555 /* Length of Directory Record */ 3556 set_num_711(p, (unsigned char)dr_len); 3557 else 3558 isoent->dr_len.vd = (int)dr_len; 3559 return ((int)dr_len); 3560 } 3561 3562 /* Rockridge */ 3563 if (iso9660->opt.rr && vdd_type != VDD_JOLIET) 3564 dr_len = set_directory_record_rr(bp, (int)dr_len, 3565 isoent, iso9660, t); 3566 3567 if (p != NULL) 3568 /* Length of Directory Record */ 3569 set_num_711(p, (unsigned char)dr_len); 3570 else { 3571 /* 3572 * Save the size which is needed to write this 3573 * Directory Record. 3574 */ 3575 switch (t) { 3576 case DIR_REC_VD: 3577 /* This case does not come, but compiler 3578 * complains that DIR_REC_VD not handled 3579 * in switch .... */ 3580 break; 3581 case DIR_REC_SELF: 3582 isoent->dr_len.self = (int)dr_len; break; 3583 case DIR_REC_PARENT: 3584 isoent->dr_len.parent = (int)dr_len; break; 3585 case DIR_REC_NORMAL: 3586 isoent->dr_len.normal = (int)dr_len; break; 3587 } 3588 } 3589 3590 return ((int)dr_len); 3591 } 3592 3593 /* 3594 * Calculate the size of a directory record. 3595 */ 3596 static inline int 3597 get_dir_rec_size(struct iso9660 *iso9660, struct isoent *isoent, 3598 enum dir_rec_type t, enum vdd_type vdd_type) 3599 { 3600 3601 return (set_directory_record(NULL, SIZE_MAX, 3602 isoent, iso9660, t, vdd_type)); 3603 } 3604 3605 /* 3606 * Manage to write ISO-image data with wbuff to reduce calling 3607 * __archive_write_output() for performance. 3608 */ 3609 3610 3611 static inline unsigned char * 3612 wb_buffptr(struct archive_write *a) 3613 { 3614 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data; 3615 3616 return (&(iso9660->wbuff[sizeof(iso9660->wbuff) 3617 - iso9660->wbuff_remaining])); 3618 } 3619 3620 static int 3621 wb_write_out(struct archive_write *a) 3622 { 3623 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data; 3624 size_t wsize, nw; 3625 int r; 3626 3627 wsize = sizeof(iso9660->wbuff) - iso9660->wbuff_remaining; 3628 nw = wsize % LOGICAL_BLOCK_SIZE; 3629 if (iso9660->wbuff_type == WB_TO_STREAM) 3630 r = __archive_write_output(a, iso9660->wbuff, wsize - nw); 3631 else 3632 r = write_to_temp(a, iso9660->wbuff, wsize - nw); 3633 /* Increase the offset. */ 3634 iso9660->wbuff_offset += wsize - nw; 3635 if (iso9660->wbuff_offset > iso9660->wbuff_written) 3636 iso9660->wbuff_written = iso9660->wbuff_offset; 3637 iso9660->wbuff_remaining = sizeof(iso9660->wbuff); 3638 if (nw) { 3639 iso9660->wbuff_remaining -= nw; 3640 memmove(iso9660->wbuff, iso9660->wbuff + wsize - nw, nw); 3641 } 3642 return (r); 3643 } 3644 3645 static int 3646 wb_consume(struct archive_write *a, size_t size) 3647 { 3648 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data; 3649 3650 if (size > iso9660->wbuff_remaining || 3651 iso9660->wbuff_remaining == 0) { 3652 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 3653 "Internal Programing error: iso9660:wb_consume()" 3654 " size=%jd, wbuff_remaining=%jd", 3655 (intmax_t)size, (intmax_t)iso9660->wbuff_remaining); 3656 return (ARCHIVE_FATAL); 3657 } 3658 iso9660->wbuff_remaining -= size; 3659 if (iso9660->wbuff_remaining < LOGICAL_BLOCK_SIZE) 3660 return (wb_write_out(a)); 3661 return (ARCHIVE_OK); 3662 } 3663 3664 #ifdef HAVE_ZLIB_H 3665 3666 static int 3667 wb_set_offset(struct archive_write *a, int64_t off) 3668 { 3669 struct iso9660 *iso9660 = (struct iso9660 *)a->format_data; 3670 int64_t used, ext_bytes; 3671 3672 if (iso9660->wbuff_type != WB_TO_TEMP) { 3673 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 3674 "Internal Programing error: iso9660:wb_set_offset()"); 3675 return (ARCHIVE_FATAL); 3676 } 3677 3678 used = sizeof(iso9660->wbuff) - iso9660->wbuff_remaining; 3679 if (iso9660->wbuff_offset + used > iso9660->wbuff_tail) 3680 iso9660->wbuff_tail = iso9660->wbuff_offset + used; 3681 if (iso9660->wbuff_offset < iso9660->wbuff_written) { 3682 if (used > 0 && 3683 write_to_temp(a, iso9660->wbuff, (size_t)used) != ARCHIVE_OK) 3684 return (ARCHIVE_FATAL); 3685 iso9660->wbuff_offset = iso9660->wbuff_written; 3686 lseek(iso9660->temp_fd, iso9660->wbuff_offset, SEEK_SET); 3687 iso9660->wbuff_remaining = sizeof(iso9660->wbuff); 3688 used = 0; 3689 } 3690 if (off < iso9660->wbuff_offset) { 3691 /* 3692 * Write out waiting data. 3693 */ 3694 if (used > 0) { 3695 if (wb_write_out(a) != ARCHIVE_OK) 3696 return (ARCHIVE_FATAL); 3697 } 3698 lseek(iso9660->temp_fd, off, SEEK_SET); 3699 iso9660->wbuff_offset = off; 3700 iso9660->wbuff_remaining = sizeof(iso9660->wbuff); 3701 } else if (off <= iso9660->wbuff_tail) { 3702 iso9660->wbuff_remaining = (size_t) 3703 (sizeof(iso9660->wbuff) - (off - iso9660->wbuff_offset)); 3704 } else { 3705 ext_bytes = off - iso9660->wbuff_tail; 3706 iso9660->wbuff_remaining = (size_t)(sizeof(iso9660->wbuff) 3707 - (iso9660->wbuff_tail - iso9660->wbuff_offset)); 3708 while (ext_bytes >= (int64_t)iso9660->wbuff_remaining) { 3709 if (write_null(a, (size_t)iso9660->wbuff_remaining) 3710 != ARCHIVE_OK) 3711 return (ARCHIVE_FATAL); 3712 ext_bytes -= iso9660->wbuff_remaining; 3713 } 3714 if (ext_bytes > 0) { 3715 if (write_null(a, (size_t)ext_bytes) != ARCHIVE_OK) 3716 return (ARCHIVE_FATAL); 3717 } 3718 } 3719 return (ARCHIVE_OK); 3720 } 3721 3722 #endif /* HAVE_ZLIB_H */ 3723 3724 static int 3725 write_null(struct archive_write *a, size_t size) 3726 { 3727 size_t remaining; 3728 unsigned char *p, *old; 3729 int r; 3730 3731 remaining = wb_remaining(a); 3732 p = wb_buffptr(a); 3733 if (size <= remaining) { 3734 memset(p, 0, size); 3735 return (wb_consume(a, size)); 3736 } 3737 memset(p, 0, remaining); 3738 r = wb_consume(a, remaining); 3739 if (r != ARCHIVE_OK) 3740 return (r); 3741 size -= remaining; 3742 old = p; 3743 p = wb_buffptr(a); 3744 memset(p, 0, old - p); 3745 remaining = wb_remaining(a); 3746 while (size) { 3747 size_t wsize = size; 3748 3749 if (wsize > remaining) 3750 wsize = remaining; 3751 r = wb_consume(a, wsize); 3752 if (r != ARCHIVE_OK) 3753 return (r); 3754 size -= wsize; 3755 } 3756 return (ARCHIVE_OK); 3757 } 3758 3759 /* 3760 * Write Volume Descriptor Set Terminator 3761 */ 3762 static int 3763 write_VD_terminator(struct archive_write *a) 3764 { 3765 unsigned char *bp; 3766 3767 bp = wb_buffptr(a) -1; 3768 set_VD_bp(bp, VDT_TERMINATOR, 1); 3769 set_unused_field_bp(bp, 8, LOGICAL_BLOCK_SIZE); 3770 3771 return (wb_consume(a, LOGICAL_BLOCK_SIZE)); 3772 } 3773 3774 static int 3775 set_file_identifier(unsigned char *bp, int from, int to, enum vdc vdc, 3776 struct archive_write *a, struct vdd *vdd, struct archive_string *id, 3777 const char *label, int leading_under, enum char_type char_type) 3778 { 3779 char identifier[256]; 3780 struct isoent *isoent; 3781 const char *ids; 3782 size_t len; 3783 int r; 3784 3785 if (id->length > 0 && leading_under && id->s[0] != '_') { 3786 if (char_type == A_CHAR) 3787 r = set_str_a_characters_bp(a, bp, from, to, id->s, vdc); 3788 else 3789 r = set_str_d_characters_bp(a, bp, from, to, id->s, vdc); 3790 } else if (id->length > 0) { 3791 ids = id->s; 3792 if (leading_under) 3793 ids++; 3794 isoent = isoent_find_entry(vdd->rootent, ids); 3795 if (isoent == NULL) { 3796 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 3797 "Not Found %s `%s'.", 3798 label, ids); 3799 return (ARCHIVE_FATAL); 3800 } 3801 len = isoent->ext_off + isoent->ext_len; 3802 if (vdd->vdd_type == VDD_JOLIET) { 3803 if (len > sizeof(identifier)-2) 3804 len = sizeof(identifier)-2; 3805 } else { 3806 if (len > sizeof(identifier)-1) 3807 len = sizeof(identifier)-1; 3808 } 3809 memcpy(identifier, isoent->identifier, len); 3810 identifier[len] = '\0'; 3811 if (vdd->vdd_type == VDD_JOLIET) { 3812 identifier[len+1] = 0; 3813 vdc = VDC_UCS2_DIRECT; 3814 } 3815 if (char_type == A_CHAR) 3816 r = set_str_a_characters_bp(a, bp, from, to, 3817 identifier, vdc); 3818 else 3819 r = set_str_d_characters_bp(a, bp, from, to, 3820 identifier, vdc); 3821 } else { 3822 if (char_type == A_CHAR) 3823 r = set_str_a_characters_bp(a, bp, from, to, NULL, vdc); 3824 else 3825 r = set_str_d_characters_bp(a, bp, from, to, NULL, vdc); 3826 } 3827 return (r); 3828 } 3829 3830 /* 3831 * Write Primary/Supplementary Volume Descriptor 3832 */ 3833 static int 3834 write_VD(struct archive_write *a, struct vdd *vdd) 3835 { 3836 struct iso9660 *iso9660; 3837 unsigned char *bp; 3838 uint16_t volume_set_size = 1; 3839 char identifier[256]; 3840 enum VD_type vdt; 3841 enum vdc vdc; 3842 unsigned char vd_ver, fst_ver; 3843 int r; 3844 3845 iso9660 = a->format_data; 3846 switch (vdd->vdd_type) { 3847 case VDD_JOLIET: 3848 vdt = VDT_SUPPLEMENTARY; 3849 vd_ver = fst_ver = 1; 3850 vdc = VDC_UCS2; 3851 break; 3852 case VDD_ENHANCED: 3853 vdt = VDT_SUPPLEMENTARY; 3854 vd_ver = fst_ver = 2; 3855 vdc = VDC_LOWERCASE; 3856 break; 3857 case VDD_PRIMARY: 3858 default: 3859 vdt = VDT_PRIMARY; 3860 vd_ver = fst_ver = 1; 3861 #ifdef COMPAT_MKISOFS 3862 vdc = VDC_LOWERCASE; 3863 #else 3864 vdc = VDC_STD; 3865 #endif 3866 break; 3867 } 3868 3869 bp = wb_buffptr(a) -1; 3870 /* Volume Descriptor Type */ 3871 set_VD_bp(bp, vdt, vd_ver); 3872 /* Unused Field */ 3873 set_unused_field_bp(bp, 8, 8); 3874 /* System Identifier */ 3875 get_system_identitier(identifier, sizeof(identifier)); 3876 r = set_str_a_characters_bp(a, bp, 9, 40, identifier, vdc); 3877 if (r != ARCHIVE_OK) 3878 return (r); 3879 /* Volume Identifier */ 3880 r = set_str_d_characters_bp(a, bp, 41, 72, 3881 iso9660->volume_identifier.s, vdc); 3882 if (r != ARCHIVE_OK) 3883 return (r); 3884 /* Unused Field */ 3885 set_unused_field_bp(bp, 73, 80); 3886 /* Volume Space Size */ 3887 set_num_733(bp+81, iso9660->volume_space_size); 3888 if (vdd->vdd_type == VDD_JOLIET) { 3889 /* Escape Sequences */ 3890 bp[89] = 0x25;/* UCS-2 Level 3 */ 3891 bp[90] = 0x2F; 3892 bp[91] = 0x45; 3893 memset(bp + 92, 0, 120 - 92 + 1); 3894 } else { 3895 /* Unused Field */ 3896 set_unused_field_bp(bp, 89, 120); 3897 } 3898 /* Volume Set Size */ 3899 set_num_723(bp+121, volume_set_size); 3900 /* Volume Sequence Number */ 3901 set_num_723(bp+125, iso9660->volume_sequence_number); 3902 /* Logical Block Size */ 3903 set_num_723(bp+129, LOGICAL_BLOCK_SIZE); 3904 /* Path Table Size */ 3905 set_num_733(bp+133, vdd->path_table_size); 3906 /* Location of Occurrence of Type L Path Table */ 3907 set_num_731(bp+141, vdd->location_type_L_path_table); 3908 /* Location of Optional Occurrence of Type L Path Table */ 3909 set_num_731(bp+145, 0); 3910 /* Location of Occurrence of Type M Path Table */ 3911 set_num_732(bp+149, vdd->location_type_M_path_table); 3912 /* Location of Optional Occurrence of Type M Path Table */ 3913 set_num_732(bp+153, 0); 3914 /* Directory Record for Root Directory(BP 157 to 190) */ 3915 set_directory_record(bp+157, 190-157+1, vdd->rootent, 3916 iso9660, DIR_REC_VD, vdd->vdd_type); 3917 /* Volume Set Identifier */ 3918 r = set_str_d_characters_bp(a, bp, 191, 318, "", vdc); 3919 if (r != ARCHIVE_OK) 3920 return (r); 3921 /* Publisher Identifier */ 3922 r = set_file_identifier(bp, 319, 446, vdc, a, vdd, 3923 &(iso9660->publisher_identifier), 3924 "Publisher File", 1, A_CHAR); 3925 if (r != ARCHIVE_OK) 3926 return (r); 3927 /* Data Preparer Identifier */ 3928 r = set_file_identifier(bp, 447, 574, vdc, a, vdd, 3929 &(iso9660->data_preparer_identifier), 3930 "Data Preparer File", 1, A_CHAR); 3931 if (r != ARCHIVE_OK) 3932 return (r); 3933 /* Application Identifier */ 3934 r = set_file_identifier(bp, 575, 702, vdc, a, vdd, 3935 &(iso9660->application_identifier), 3936 "Application File", 1, A_CHAR); 3937 if (r != ARCHIVE_OK) 3938 return (r); 3939 /* Copyright File Identifier */ 3940 r = set_file_identifier(bp, 703, 739, vdc, a, vdd, 3941 &(iso9660->copyright_file_identifier), 3942 "Copyright File", 0, D_CHAR); 3943 if (r != ARCHIVE_OK) 3944 return (r); 3945 /* Abstract File Identifier */ 3946 r = set_file_identifier(bp, 740, 776, vdc, a, vdd, 3947 &(iso9660->abstract_file_identifier), 3948 "Abstract File", 0, D_CHAR); 3949 if (r != ARCHIVE_OK) 3950 return (r); 3951 /* Bibliographic File Identifier */ 3952 r = set_file_identifier(bp, 777, 813, vdc, a, vdd, 3953 &(iso9660->bibliographic_file_identifier), 3954 "Bibliongraphic File", 0, D_CHAR); 3955 if (r != ARCHIVE_OK) 3956 return (r); 3957 /* Volume Creation Date and Time */ 3958 set_date_time(bp+814, iso9660->birth_time); 3959 /* Volume Modification Date and Time */ 3960 set_date_time(bp+831, iso9660->birth_time); 3961 /* Volume Expiration Date and Time(obsolete) */ 3962 set_date_time_null(bp+848); 3963 /* Volume Effective Date and Time */ 3964 set_date_time(bp+865, iso9660->birth_time); 3965 /* File Structure Version */ 3966 bp[882] = fst_ver; 3967 /* Reserved */ 3968 bp[883] = 0; 3969 /* Application Use */ 3970 memset(bp + 884, 0x20, 1395 - 884 + 1); 3971 /* Reserved */ 3972 set_unused_field_bp(bp, 1396, LOGICAL_BLOCK_SIZE); 3973 3974 return (wb_consume(a, LOGICAL_BLOCK_SIZE)); 3975 } 3976 3977 /* 3978 * Write Boot Record Volume Descriptor 3979 */ 3980 static int 3981 write_VD_boot_record(struct archive_write *a) 3982 { 3983 struct iso9660 *iso9660; 3984 unsigned char *bp; 3985 3986 iso9660 = a->format_data; 3987 bp = wb_buffptr(a) -1; 3988 /* Volume Descriptor Type */ 3989 set_VD_bp(bp, VDT_BOOT_RECORD, 1); 3990 /* Boot System Identifier */ 3991 memcpy(bp+8, "EL TORITO SPECIFICATION", 23); 3992 set_unused_field_bp(bp, 8+23, 39); 3993 /* Unused */ 3994 set_unused_field_bp(bp, 40, 71); 3995 /* Absolute pointer to first sector of Boot Catalog */ 3996 set_num_731(bp+72, 3997 iso9660->el_torito.catalog->file->content.location); 3998 /* Unused */ 3999 set_unused_field_bp(bp, 76, LOGICAL_BLOCK_SIZE); 4000 4001 return (wb_consume(a, LOGICAL_BLOCK_SIZE)); 4002 } 4003 4004 enum keytype { 4005 KEY_FLG, 4006 KEY_STR, 4007 KEY_INT, 4008 KEY_HEX 4009 }; 4010 static void 4011 set_option_info(struct archive_string *info, int *opt, const char *key, 4012 enum keytype type, ...) 4013 { 4014 va_list ap; 4015 char prefix; 4016 const char *s; 4017 int d; 4018 4019 prefix = (*opt==0)? ' ':','; 4020 va_start(ap, type); 4021 switch (type) { 4022 case KEY_FLG: 4023 d = va_arg(ap, int); 4024 archive_string_sprintf(info, "%c%s%s", 4025 prefix, (d == 0)?"!":"", key); 4026 break; 4027 case KEY_STR: 4028 s = va_arg(ap, const char *); 4029 archive_string_sprintf(info, "%c%s=%s", 4030 prefix, key, s); 4031 break; 4032 case KEY_INT: 4033 d = va_arg(ap, int); 4034 archive_string_sprintf(info, "%c%s=%d", 4035 prefix, key, d); 4036 break; 4037 case KEY_HEX: 4038 d = va_arg(ap, int); 4039 archive_string_sprintf(info, "%c%s=%x", 4040 prefix, key, d); 4041 break; 4042 } 4043 va_end(ap); 4044 4045 *opt = 1; 4046 } 4047 4048 /* 4049 * Make Non-ISO File System Information 4050 */ 4051 static int 4052 write_information_block(struct archive_write *a) 4053 { 4054 struct iso9660 *iso9660; 4055 char buf[128]; 4056 const char *v; 4057 int opt, r; 4058 struct archive_string info; 4059 size_t info_size = LOGICAL_BLOCK_SIZE * 4060 NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK; 4061 4062 iso9660 = (struct iso9660 *)a->format_data; 4063 if (info_size > wb_remaining(a)) { 4064 r = wb_write_out(a); 4065 if (r != ARCHIVE_OK) 4066 return (r); 4067 } 4068 archive_string_init(&info); 4069 if (archive_string_ensure(&info, info_size) == NULL) { 4070 archive_set_error(&a->archive, ENOMEM, 4071 "Can't allocate memory"); 4072 return (ARCHIVE_FATAL); 4073 } 4074 memset(info.s, 0, info_size); 4075 opt = 0; 4076 #if defined(HAVE__CTIME64_S) 4077 { 4078 __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits 4079 _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp)); 4080 } 4081 #elif defined(HAVE_CTIME_R) 4082 ctime_r(&(iso9660->birth_time), buf); 4083 #else 4084 strncpy(buf, ctime(&(iso9660->birth_time)), sizeof(buf)-1); 4085 buf[sizeof(buf)-1] = '\0'; 4086 #endif 4087 archive_string_sprintf(&info, 4088 "INFO %s%s", buf, archive_version_string()); 4089 if (iso9660->opt.abstract_file != OPT_ABSTRACT_FILE_DEFAULT) 4090 set_option_info(&info, &opt, "abstract-file", 4091 KEY_STR, iso9660->abstract_file_identifier.s); 4092 if (iso9660->opt.application_id != OPT_APPLICATION_ID_DEFAULT) 4093 set_option_info(&info, &opt, "application-id", 4094 KEY_STR, iso9660->application_identifier.s); 4095 if (iso9660->opt.allow_vernum != OPT_ALLOW_VERNUM_DEFAULT) 4096 set_option_info(&info, &opt, "allow-vernum", 4097 KEY_FLG, iso9660->opt.allow_vernum); 4098 if (iso9660->opt.biblio_file != OPT_BIBLIO_FILE_DEFAULT) 4099 set_option_info(&info, &opt, "biblio-file", 4100 KEY_STR, iso9660->bibliographic_file_identifier.s); 4101 if (iso9660->opt.boot != OPT_BOOT_DEFAULT) 4102 set_option_info(&info, &opt, "boot", 4103 KEY_STR, iso9660->el_torito.boot_filename.s); 4104 if (iso9660->opt.boot_catalog != OPT_BOOT_CATALOG_DEFAULT) 4105 set_option_info(&info, &opt, "boot-catalog", 4106 KEY_STR, iso9660->el_torito.catalog_filename.s); 4107 if (iso9660->opt.boot_info_table != OPT_BOOT_INFO_TABLE_DEFAULT) 4108 set_option_info(&info, &opt, "boot-info-table", 4109 KEY_FLG, iso9660->opt.boot_info_table); 4110 if (iso9660->opt.boot_load_seg != OPT_BOOT_LOAD_SEG_DEFAULT) 4111 set_option_info(&info, &opt, "boot-load-seg", 4112 KEY_HEX, iso9660->el_torito.boot_load_seg); 4113 if (iso9660->opt.boot_load_size != OPT_BOOT_LOAD_SIZE_DEFAULT) 4114 set_option_info(&info, &opt, "boot-load-size", 4115 KEY_INT, iso9660->el_torito.boot_load_size); 4116 if (iso9660->opt.boot_type != OPT_BOOT_TYPE_DEFAULT) { 4117 v = "no-emulation"; 4118 if (iso9660->opt.boot_type == OPT_BOOT_TYPE_FD) 4119 v = "fd"; 4120 if (iso9660->opt.boot_type == OPT_BOOT_TYPE_HARD_DISK) 4121 v = "hard-disk"; 4122 set_option_info(&info, &opt, "boot-type", 4123 KEY_STR, v); 4124 } 4125 #ifdef HAVE_ZLIB_H 4126 if (iso9660->opt.compression_level != OPT_COMPRESSION_LEVEL_DEFAULT) 4127 set_option_info(&info, &opt, "compression-level", 4128 KEY_INT, iso9660->zisofs.compression_level); 4129 #endif 4130 if (iso9660->opt.copyright_file != OPT_COPYRIGHT_FILE_DEFAULT) 4131 set_option_info(&info, &opt, "copyright-file", 4132 KEY_STR, iso9660->copyright_file_identifier.s); 4133 if (iso9660->opt.iso_level != OPT_ISO_LEVEL_DEFAULT) 4134 set_option_info(&info, &opt, "iso-level", 4135 KEY_INT, iso9660->opt.iso_level); 4136 if (iso9660->opt.joliet != OPT_JOLIET_DEFAULT) { 4137 if (iso9660->opt.joliet == OPT_JOLIET_LONGNAME) 4138 set_option_info(&info, &opt, "joliet", 4139 KEY_STR, "long"); 4140 else 4141 set_option_info(&info, &opt, "joliet", 4142 KEY_FLG, iso9660->opt.joliet); 4143 } 4144 if (iso9660->opt.limit_depth != OPT_LIMIT_DEPTH_DEFAULT) 4145 set_option_info(&info, &opt, "limit-depth", 4146 KEY_FLG, iso9660->opt.limit_depth); 4147 if (iso9660->opt.limit_dirs != OPT_LIMIT_DIRS_DEFAULT) 4148 set_option_info(&info, &opt, "limit-dirs", 4149 KEY_FLG, iso9660->opt.limit_dirs); 4150 if (iso9660->opt.pad != OPT_PAD_DEFAULT) 4151 set_option_info(&info, &opt, "pad", 4152 KEY_FLG, iso9660->opt.pad); 4153 if (iso9660->opt.publisher != OPT_PUBLISHER_DEFAULT) 4154 set_option_info(&info, &opt, "publisher", 4155 KEY_STR, iso9660->publisher_identifier.s); 4156 if (iso9660->opt.rr != OPT_RR_DEFAULT) { 4157 if (iso9660->opt.rr == OPT_RR_DISABLED) 4158 set_option_info(&info, &opt, "rockridge", 4159 KEY_FLG, iso9660->opt.rr); 4160 else if (iso9660->opt.rr == OPT_RR_STRICT) 4161 set_option_info(&info, &opt, "rockridge", 4162 KEY_STR, "strict"); 4163 else if (iso9660->opt.rr == OPT_RR_USEFUL) 4164 set_option_info(&info, &opt, "rockridge", 4165 KEY_STR, "useful"); 4166 } 4167 if (iso9660->opt.volume_id != OPT_VOLUME_ID_DEFAULT) 4168 set_option_info(&info, &opt, "volume-id", 4169 KEY_STR, iso9660->volume_identifier.s); 4170 if (iso9660->opt.zisofs != OPT_ZISOFS_DEFAULT) 4171 set_option_info(&info, &opt, "zisofs", 4172 KEY_FLG, iso9660->opt.zisofs); 4173 4174 memcpy(wb_buffptr(a), info.s, info_size); 4175 archive_string_free(&info); 4176 return (wb_consume(a, info_size)); 4177 } 4178 4179 static int 4180 write_rr_ER(struct archive_write *a) 4181 { 4182 unsigned char *p; 4183 4184 p = wb_buffptr(a); 4185 4186 memset(p, 0, LOGICAL_BLOCK_SIZE); 4187 p[0] = 'E'; 4188 p[1] = 'R'; 4189 p[3] = 0x01; 4190 p[2] = RRIP_ER_SIZE; 4191 p[4] = RRIP_ER_ID_SIZE; 4192 p[5] = RRIP_ER_DSC_SIZE; 4193 p[6] = RRIP_ER_SRC_SIZE; 4194 p[7] = 0x01; 4195 memcpy(&p[8], rrip_identifier, p[4]); 4196 memcpy(&p[8+p[4]], rrip_descriptor, p[5]); 4197 memcpy(&p[8+p[4]+p[5]], rrip_source, p[6]); 4198 4199 return (wb_consume(a, LOGICAL_BLOCK_SIZE)); 4200 } 4201 4202 static void 4203 calculate_path_table_size(struct vdd *vdd) 4204 { 4205 int depth, size; 4206 struct path_table *pt; 4207 4208 pt = vdd->pathtbl; 4209 size = 0; 4210 for (depth = 0; depth < vdd->max_depth; depth++) { 4211 struct isoent **ptbl; 4212 int i, cnt; 4213 4214 if ((cnt = pt[depth].cnt) == 0) 4215 break; 4216 4217 ptbl = pt[depth].sorted; 4218 for (i = 0; i < cnt; i++) { 4219 int len; 4220 4221 if (ptbl[i]->identifier == NULL) 4222 len = 1; /* root directory */ 4223 else 4224 len = ptbl[i]->id_len; 4225 if (len & 0x01) 4226 len++; /* Padding Field */ 4227 size += 8 + len; 4228 } 4229 } 4230 vdd->path_table_size = size; 4231 vdd->path_table_block = 4232 ((size + PATH_TABLE_BLOCK_SIZE -1) / 4233 PATH_TABLE_BLOCK_SIZE) * 4234 (PATH_TABLE_BLOCK_SIZE / LOGICAL_BLOCK_SIZE); 4235 } 4236 4237 static int 4238 _write_path_table(struct archive_write *a, int type_m, int depth, 4239 struct vdd *vdd) 4240 { 4241 unsigned char *bp, *wb; 4242 struct isoent **ptbl; 4243 size_t wbremaining; 4244 int i, r, wsize; 4245 4246 if (vdd->pathtbl[depth].cnt == 0) 4247 return (0); 4248 4249 wsize = 0; 4250 wb = wb_buffptr(a); 4251 wbremaining = wb_remaining(a); 4252 bp = wb - 1; 4253 ptbl = vdd->pathtbl[depth].sorted; 4254 for (i = 0; i < vdd->pathtbl[depth].cnt; i++) { 4255 struct isoent *np; 4256 size_t len; 4257 4258 np = ptbl[i]; 4259 if (np->identifier == NULL) 4260 len = 1; /* root directory */ 4261 else 4262 len = np->id_len; 4263 if (wbremaining - ((bp+1) - wb) < (len + 1 + 8)) { 4264 r = wb_consume(a, (bp+1) - wb); 4265 if (r < 0) 4266 return (r); 4267 wb = wb_buffptr(a); 4268 wbremaining = wb_remaining(a); 4269 bp = wb -1; 4270 } 4271 /* Length of Directory Identifier */ 4272 set_num_711(bp+1, (unsigned char)len); 4273 /* Extended Attribute Record Length */ 4274 set_num_711(bp+2, 0); 4275 /* Location of Extent */ 4276 if (type_m) 4277 set_num_732(bp+3, np->dir_location); 4278 else 4279 set_num_731(bp+3, np->dir_location); 4280 /* Parent Directory Number */ 4281 if (type_m) 4282 set_num_722(bp+7, np->parent->dir_number); 4283 else 4284 set_num_721(bp+7, np->parent->dir_number); 4285 /* Directory Identifier */ 4286 if (np->identifier == NULL) 4287 bp[9] = 0; 4288 else 4289 memcpy(&bp[9], np->identifier, len); 4290 if (len & 0x01) { 4291 /* Padding Field */ 4292 bp[9+len] = 0; 4293 len++; 4294 } 4295 wsize += 8 + (int)len; 4296 bp += 8 + len; 4297 } 4298 if ((bp + 1) > wb) { 4299 r = wb_consume(a, (bp+1)-wb); 4300 if (r < 0) 4301 return (r); 4302 } 4303 return (wsize); 4304 } 4305 4306 static int 4307 write_path_table(struct archive_write *a, int type_m, struct vdd *vdd) 4308 { 4309 int depth, r; 4310 size_t path_table_size; 4311 4312 r = ARCHIVE_OK; 4313 path_table_size = 0; 4314 for (depth = 0; depth < vdd->max_depth; depth++) { 4315 r = _write_path_table(a, type_m, depth, vdd); 4316 if (r < 0) 4317 return (r); 4318 path_table_size += r; 4319 } 4320 4321 /* Write padding data. */ 4322 path_table_size = path_table_size % PATH_TABLE_BLOCK_SIZE; 4323 if (path_table_size > 0) 4324 r = write_null(a, PATH_TABLE_BLOCK_SIZE - path_table_size); 4325 return (r); 4326 } 4327 4328 static int 4329 calculate_directory_descriptors(struct iso9660 *iso9660, struct vdd *vdd, 4330 struct isoent *isoent, int depth) 4331 { 4332 struct isoent **enttbl; 4333 int bs, block, i; 4334 4335 block = 1; 4336 bs = get_dir_rec_size(iso9660, isoent, DIR_REC_SELF, vdd->vdd_type); 4337 bs += get_dir_rec_size(iso9660, isoent, DIR_REC_PARENT, vdd->vdd_type); 4338 4339 if (isoent->children.cnt <= 0 || (vdd->vdd_type != VDD_JOLIET && 4340 !iso9660->opt.rr && depth + 1 >= vdd->max_depth)) 4341 return (block); 4342 4343 enttbl = isoent->children_sorted; 4344 for (i = 0; i < isoent->children.cnt; i++) { 4345 struct isoent *np = enttbl[i]; 4346 struct isofile *file; 4347 4348 file = np->file; 4349 if (file->hardlink_target != NULL) 4350 file = file->hardlink_target; 4351 file->cur_content = &(file->content); 4352 do { 4353 int dr_l; 4354 4355 dr_l = get_dir_rec_size(iso9660, np, DIR_REC_NORMAL, 4356 vdd->vdd_type); 4357 if ((bs + dr_l) > LOGICAL_BLOCK_SIZE) { 4358 block ++; 4359 bs = dr_l; 4360 } else 4361 bs += dr_l; 4362 file->cur_content = file->cur_content->next; 4363 } while (file->cur_content != NULL); 4364 } 4365 return (block); 4366 } 4367 4368 static int 4369 _write_directory_descriptors(struct archive_write *a, struct vdd *vdd, 4370 struct isoent *isoent, int depth) 4371 { 4372 struct iso9660 *iso9660 = a->format_data; 4373 struct isoent **enttbl; 4374 unsigned char *p, *wb; 4375 int i, r; 4376 int dr_l; 4377 4378 p = wb = wb_buffptr(a); 4379 #define WD_REMAINING (LOGICAL_BLOCK_SIZE - (p - wb)) 4380 p += set_directory_record(p, WD_REMAINING, isoent, 4381 iso9660, DIR_REC_SELF, vdd->vdd_type); 4382 p += set_directory_record(p, WD_REMAINING, isoent, 4383 iso9660, DIR_REC_PARENT, vdd->vdd_type); 4384 4385 if (isoent->children.cnt <= 0 || (vdd->vdd_type != VDD_JOLIET && 4386 !iso9660->opt.rr && depth + 1 >= vdd->max_depth)) { 4387 memset(p, 0, WD_REMAINING); 4388 return (wb_consume(a, LOGICAL_BLOCK_SIZE)); 4389 } 4390 4391 enttbl = isoent->children_sorted; 4392 for (i = 0; i < isoent->children.cnt; i++) { 4393 struct isoent *np = enttbl[i]; 4394 struct isofile *file = np->file; 4395 4396 if (file->hardlink_target != NULL) 4397 file = file->hardlink_target; 4398 file->cur_content = &(file->content); 4399 do { 4400 dr_l = set_directory_record(p, WD_REMAINING, 4401 np, iso9660, DIR_REC_NORMAL, 4402 vdd->vdd_type); 4403 if (dr_l == 0) { 4404 memset(p, 0, WD_REMAINING); 4405 r = wb_consume(a, LOGICAL_BLOCK_SIZE); 4406 if (r < 0) 4407 return (r); 4408 p = wb = wb_buffptr(a); 4409 dr_l = set_directory_record(p, 4410 WD_REMAINING, np, iso9660, 4411 DIR_REC_NORMAL, vdd->vdd_type); 4412 } 4413 p += dr_l; 4414 file->cur_content = file->cur_content->next; 4415 } while (file->cur_content != NULL); 4416 } 4417 memset(p, 0, WD_REMAINING); 4418 return (wb_consume(a, LOGICAL_BLOCK_SIZE)); 4419 } 4420 4421 static int 4422 write_directory_descriptors(struct archive_write *a, struct vdd *vdd) 4423 { 4424 struct isoent *np; 4425 int depth, r; 4426 4427 depth = 0; 4428 np = vdd->rootent; 4429 do { 4430 struct extr_rec *extr; 4431 4432 r = _write_directory_descriptors(a, vdd, np, depth); 4433 if (r < 0) 4434 return (r); 4435 if (vdd->vdd_type != VDD_JOLIET) { 4436 /* 4437 * This extract record is used by SUSP,RRIP. 4438 * Not for joliet. 4439 */ 4440 for (extr = np->extr_rec_list.first; 4441 extr != NULL; 4442 extr = extr->next) { 4443 unsigned char *wb; 4444 4445 wb = wb_buffptr(a); 4446 memcpy(wb, extr->buf, extr->offset); 4447 memset(wb + extr->offset, 0, 4448 LOGICAL_BLOCK_SIZE - extr->offset); 4449 r = wb_consume(a, LOGICAL_BLOCK_SIZE); 4450 if (r < 0) 4451 return (r); 4452 } 4453 } 4454 4455 if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) { 4456 /* Enter to sub directories. */ 4457 np = np->subdirs.first; 4458 depth++; 4459 continue; 4460 } 4461 while (np != np->parent) { 4462 if (np->drnext == NULL) { 4463 /* Return to the parent directory. */ 4464 np = np->parent; 4465 depth--; 4466 } else { 4467 np = np->drnext; 4468 break; 4469 } 4470 } 4471 } while (np != np->parent); 4472 4473 return (ARCHIVE_OK); 4474 } 4475 4476 /* 4477 * Read file contents from the temporary file, and write it. 4478 */ 4479 static int 4480 write_file_contents(struct archive_write *a, int64_t offset, int64_t size) 4481 { 4482 struct iso9660 *iso9660 = a->format_data; 4483 int r; 4484 4485 lseek(iso9660->temp_fd, offset, SEEK_SET); 4486 4487 while (size) { 4488 size_t rsize; 4489 ssize_t rs; 4490 unsigned char *wb; 4491 4492 wb = wb_buffptr(a); 4493 rsize = wb_remaining(a); 4494 if (rsize > (size_t)size) 4495 rsize = (size_t)size; 4496 rs = read(iso9660->temp_fd, wb, rsize); 4497 if (rs <= 0) { 4498 archive_set_error(&a->archive, errno, 4499 "Can't read temporary file(%jd)", (intmax_t)rs); 4500 return (ARCHIVE_FATAL); 4501 } 4502 size -= rs; 4503 r = wb_consume(a, rs); 4504 if (r < 0) 4505 return (r); 4506 } 4507 return (ARCHIVE_OK); 4508 } 4509 4510 static int 4511 write_file_descriptors(struct archive_write *a) 4512 { 4513 struct iso9660 *iso9660 = a->format_data; 4514 struct isofile *file; 4515 int64_t blocks, offset; 4516 int r; 4517 4518 blocks = 0; 4519 offset = 0; 4520 4521 /* Make the boot catalog contents, and write it. */ 4522 if (iso9660->el_torito.catalog != NULL) { 4523 r = make_boot_catalog(a); 4524 if (r < 0) 4525 return (r); 4526 } 4527 4528 /* Write the boot file contents. */ 4529 if (iso9660->el_torito.boot != NULL) { 4530 file = iso9660->el_torito.boot->file; 4531 blocks = file->content.blocks; 4532 offset = file->content.offset_of_temp; 4533 if (offset != 0) { 4534 r = write_file_contents(a, offset, 4535 blocks << LOGICAL_BLOCK_BITS); 4536 if (r < 0) 4537 return (r); 4538 blocks = 0; 4539 offset = 0; 4540 } 4541 } 4542 4543 /* Write out all file contents. */ 4544 for (file = iso9660->data_file_list.first; 4545 file != NULL; file = file->datanext) { 4546 4547 if (!file->write_content) 4548 continue; 4549 4550 if ((offset + (blocks << LOGICAL_BLOCK_BITS)) < 4551 file->content.offset_of_temp) { 4552 if (blocks > 0) { 4553 r = write_file_contents(a, offset, 4554 blocks << LOGICAL_BLOCK_BITS); 4555 if (r < 0) 4556 return (r); 4557 } 4558 blocks = 0; 4559 offset = file->content.offset_of_temp; 4560 } 4561 4562 file->cur_content = &(file->content); 4563 do { 4564 blocks += file->cur_content->blocks; 4565 /* Next fragment */ 4566 file->cur_content = file->cur_content->next; 4567 } while (file->cur_content != NULL); 4568 } 4569 4570 /* Flush out remaining blocks. */ 4571 if (blocks > 0) { 4572 r = write_file_contents(a, offset, 4573 blocks << LOGICAL_BLOCK_BITS); 4574 if (r < 0) 4575 return (r); 4576 } 4577 4578 return (ARCHIVE_OK); 4579 } 4580 4581 static void 4582 isofile_init_entry_list(struct iso9660 *iso9660) 4583 { 4584 iso9660->all_file_list.first = NULL; 4585 iso9660->all_file_list.last = &(iso9660->all_file_list.first); 4586 } 4587 4588 static void 4589 isofile_add_entry(struct iso9660 *iso9660, struct isofile *file) 4590 { 4591 file->allnext = NULL; 4592 *iso9660->all_file_list.last = file; 4593 iso9660->all_file_list.last = &(file->allnext); 4594 } 4595 4596 static void 4597 isofile_free_all_entries(struct iso9660 *iso9660) 4598 { 4599 struct isofile *file, *file_next; 4600 4601 file = iso9660->all_file_list.first; 4602 while (file != NULL) { 4603 file_next = file->allnext; 4604 isofile_free(file); 4605 file = file_next; 4606 } 4607 } 4608 4609 static void 4610 isofile_init_entry_data_file_list(struct iso9660 *iso9660) 4611 { 4612 iso9660->data_file_list.first = NULL; 4613 iso9660->data_file_list.last = &(iso9660->data_file_list.first); 4614 } 4615 4616 static void 4617 isofile_add_data_file(struct iso9660 *iso9660, struct isofile *file) 4618 { 4619 file->datanext = NULL; 4620 *iso9660->data_file_list.last = file; 4621 iso9660->data_file_list.last = &(file->datanext); 4622 } 4623 4624 4625 static struct isofile * 4626 isofile_new(struct archive_write *a, struct archive_entry *entry) 4627 { 4628 struct isofile *file; 4629 4630 file = calloc(1, sizeof(*file)); 4631 if (file == NULL) 4632 return (NULL); 4633 4634 if (entry != NULL) 4635 file->entry = archive_entry_clone(entry); 4636 else 4637 file->entry = archive_entry_new2(&a->archive); 4638 if (file->entry == NULL) { 4639 free(file); 4640 return (NULL); 4641 } 4642 archive_string_init(&(file->parentdir)); 4643 archive_string_init(&(file->basename)); 4644 archive_string_init(&(file->basename_utf16)); 4645 archive_string_init(&(file->symlink)); 4646 file->cur_content = &(file->content); 4647 4648 return (file); 4649 } 4650 4651 static void 4652 isofile_free(struct isofile *file) 4653 { 4654 struct content *con, *tmp; 4655 4656 con = file->content.next; 4657 while (con != NULL) { 4658 tmp = con; 4659 con = con->next; 4660 free(tmp); 4661 } 4662 archive_entry_free(file->entry); 4663 archive_string_free(&(file->parentdir)); 4664 archive_string_free(&(file->basename)); 4665 archive_string_free(&(file->basename_utf16)); 4666 archive_string_free(&(file->symlink)); 4667 free(file); 4668 } 4669 4670 #if defined(_WIN32) || defined(__CYGWIN__) 4671 static int 4672 cleanup_backslash_1(char *p) 4673 { 4674 int mb, dos; 4675 4676 mb = dos = 0; 4677 while (*p) { 4678 if (*(unsigned char *)p > 127) 4679 mb = 1; 4680 if (*p == '\\') { 4681 /* If we have not met any multi-byte characters, 4682 * we can replace '\' with '/'. */ 4683 if (!mb) 4684 *p = '/'; 4685 dos = 1; 4686 } 4687 p++; 4688 } 4689 if (!mb || !dos) 4690 return (0); 4691 return (-1); 4692 } 4693 4694 static void 4695 cleanup_backslash_2(wchar_t *p) 4696 { 4697 4698 /* Convert a path-separator from '\' to '/' */ 4699 while (*p != L'\0') { 4700 if (*p == L'\\') 4701 *p = L'/'; 4702 p++; 4703 } 4704 } 4705 #endif 4706 4707 /* 4708 * Generate a parent directory name and a base name from a pathname. 4709 */ 4710 static int 4711 isofile_gen_utility_names(struct archive_write *a, struct isofile *file) 4712 { 4713 struct iso9660 *iso9660; 4714 const char *pathname; 4715 char *p, *dirname, *slash; 4716 size_t len; 4717 int ret = ARCHIVE_OK; 4718 4719 iso9660 = a->format_data; 4720 4721 archive_string_empty(&(file->parentdir)); 4722 archive_string_empty(&(file->basename)); 4723 archive_string_empty(&(file->basename_utf16)); 4724 archive_string_empty(&(file->symlink)); 4725 4726 pathname = archive_entry_pathname(file->entry); 4727 if (pathname == NULL || pathname[0] == '\0') {/* virtual root */ 4728 file->dircnt = 0; 4729 return (ret); 4730 } 4731 4732 /* 4733 * Make a UTF-16BE basename if Joliet extension enabled. 4734 */ 4735 if (iso9660->opt.joliet) { 4736 const char *u16, *ulast; 4737 size_t u16len, ulen_last; 4738 4739 if (iso9660->sconv_to_utf16be == NULL) { 4740 iso9660->sconv_to_utf16be = 4741 archive_string_conversion_to_charset( 4742 &(a->archive), "UTF-16BE", 1); 4743 if (iso9660->sconv_to_utf16be == NULL) 4744 /* Couldn't allocate memory */ 4745 return (ARCHIVE_FATAL); 4746 iso9660->sconv_from_utf16be = 4747 archive_string_conversion_from_charset( 4748 &(a->archive), "UTF-16BE", 1); 4749 if (iso9660->sconv_from_utf16be == NULL) 4750 /* Couldn't allocate memory */ 4751 return (ARCHIVE_FATAL); 4752 } 4753 4754 /* 4755 * Convert a filename to UTF-16BE. 4756 */ 4757 if (0 > archive_entry_pathname_l(file->entry, &u16, &u16len, 4758 iso9660->sconv_to_utf16be)) { 4759 if (errno == ENOMEM) { 4760 archive_set_error(&a->archive, ENOMEM, 4761 "Can't allocate memory for UTF-16BE"); 4762 return (ARCHIVE_FATAL); 4763 } 4764 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 4765 "A filename cannot be converted to UTF-16BE;" 4766 "You should disable making Joliet extension"); 4767 ret = ARCHIVE_WARN; 4768 } 4769 4770 /* 4771 * Make sure a path separator is not in the last; 4772 * Remove trailing '/'. 4773 */ 4774 while (u16len >= 2) { 4775 #if defined(_WIN32) || defined(__CYGWIN__) 4776 if (u16[u16len-2] == 0 && 4777 (u16[u16len-1] == '/' || u16[u16len-1] == '\\')) 4778 #else 4779 if (u16[u16len-2] == 0 && u16[u16len-1] == '/') 4780 #endif 4781 { 4782 u16len -= 2; 4783 } else 4784 break; 4785 } 4786 4787 /* 4788 * Find a basename in UTF-16BE. 4789 */ 4790 ulast = u16; 4791 u16len >>= 1; 4792 ulen_last = u16len; 4793 while (u16len > 0) { 4794 #if defined(_WIN32) || defined(__CYGWIN__) 4795 if (u16[0] == 0 && (u16[1] == '/' || u16[1] == '\\')) 4796 #else 4797 if (u16[0] == 0 && u16[1] == '/') 4798 #endif 4799 { 4800 ulast = u16 + 2; 4801 ulen_last = u16len -1; 4802 } 4803 u16 += 2; 4804 u16len --; 4805 } 4806 ulen_last <<= 1; 4807 if (archive_string_ensure(&(file->basename_utf16), 4808 ulen_last) == NULL) { 4809 archive_set_error(&a->archive, ENOMEM, 4810 "Can't allocate memory for UTF-16BE"); 4811 return (ARCHIVE_FATAL); 4812 } 4813 4814 /* 4815 * Set UTF-16BE basename. 4816 */ 4817 memcpy(file->basename_utf16.s, ulast, ulen_last); 4818 file->basename_utf16.length = ulen_last; 4819 } 4820 4821 archive_strcpy(&(file->parentdir), pathname); 4822 #if defined(_WIN32) || defined(__CYGWIN__) 4823 /* 4824 * Convert a path-separator from '\' to '/' 4825 */ 4826 if (cleanup_backslash_1(file->parentdir.s) != 0) { 4827 const wchar_t *wp = archive_entry_pathname_w(file->entry); 4828 struct archive_wstring ws; 4829 4830 if (wp != NULL) { 4831 int r; 4832 archive_string_init(&ws); 4833 archive_wstrcpy(&ws, wp); 4834 cleanup_backslash_2(ws.s); 4835 archive_string_empty(&(file->parentdir)); 4836 r = archive_string_append_from_wcs(&(file->parentdir), 4837 ws.s, ws.length); 4838 archive_wstring_free(&ws); 4839 if (r < 0 && errno == ENOMEM) { 4840 archive_set_error(&a->archive, ENOMEM, 4841 "Can't allocate memory"); 4842 return (ARCHIVE_FATAL); 4843 } 4844 } 4845 } 4846 #endif 4847 4848 len = file->parentdir.length; 4849 p = dirname = file->parentdir.s; 4850 4851 /* 4852 * Remove leading '/', '../' and './' elements 4853 */ 4854 while (*p) { 4855 if (p[0] == '/') { 4856 p++; 4857 len--; 4858 } else if (p[0] != '.') 4859 break; 4860 else if (p[1] == '.' && p[2] == '/') { 4861 p += 3; 4862 len -= 3; 4863 } else if (p[1] == '/' || (p[1] == '.' && p[2] == '\0')) { 4864 p += 2; 4865 len -= 2; 4866 } else if (p[1] == '\0') { 4867 p++; 4868 len--; 4869 } else 4870 break; 4871 } 4872 if (p != dirname) { 4873 memmove(dirname, p, len+1); 4874 p = dirname; 4875 } 4876 /* 4877 * Remove "/","/." and "/.." elements from tail. 4878 */ 4879 while (len > 0) { 4880 size_t ll = len; 4881 4882 if (len > 0 && p[len-1] == '/') { 4883 p[len-1] = '\0'; 4884 len--; 4885 } 4886 if (len > 1 && p[len-2] == '/' && p[len-1] == '.') { 4887 p[len-2] = '\0'; 4888 len -= 2; 4889 } 4890 if (len > 2 && p[len-3] == '/' && p[len-2] == '.' && 4891 p[len-1] == '.') { 4892 p[len-3] = '\0'; 4893 len -= 3; 4894 } 4895 if (ll == len) 4896 break; 4897 } 4898 while (*p) { 4899 if (p[0] == '/') { 4900 if (p[1] == '/') 4901 /* Convert '//' --> '/' */ 4902 strcpy(p, p+1); 4903 else if (p[1] == '.' && p[2] == '/') 4904 /* Convert '/./' --> '/' */ 4905 strcpy(p, p+2); 4906 else if (p[1] == '.' && p[2] == '.' && p[3] == '/') { 4907 /* Convert 'dir/dir1/../dir2/' 4908 * --> 'dir/dir2/' 4909 */ 4910 char *rp = p -1; 4911 while (rp >= dirname) { 4912 if (*rp == '/') 4913 break; 4914 --rp; 4915 } 4916 if (rp > dirname) { 4917 strcpy(rp, p+3); 4918 p = rp; 4919 } else { 4920 strcpy(dirname, p+4); 4921 p = dirname; 4922 } 4923 } else 4924 p++; 4925 } else 4926 p++; 4927 } 4928 p = dirname; 4929 len = strlen(p); 4930 4931 if (archive_entry_filetype(file->entry) == AE_IFLNK) { 4932 /* Convert symlink name too. */ 4933 pathname = archive_entry_symlink(file->entry); 4934 archive_strcpy(&(file->symlink), pathname); 4935 #if defined(_WIN32) || defined(__CYGWIN__) 4936 /* 4937 * Convert a path-separator from '\' to '/' 4938 */ 4939 if (archive_strlen(&(file->symlink)) > 0 && 4940 cleanup_backslash_1(file->symlink.s) != 0) { 4941 const wchar_t *wp = 4942 archive_entry_symlink_w(file->entry); 4943 struct archive_wstring ws; 4944 4945 if (wp != NULL) { 4946 int r; 4947 archive_string_init(&ws); 4948 archive_wstrcpy(&ws, wp); 4949 cleanup_backslash_2(ws.s); 4950 archive_string_empty(&(file->symlink)); 4951 r = archive_string_append_from_wcs( 4952 &(file->symlink), 4953 ws.s, ws.length); 4954 archive_wstring_free(&ws); 4955 if (r < 0 && errno == ENOMEM) { 4956 archive_set_error(&a->archive, ENOMEM, 4957 "Can't allocate memory"); 4958 return (ARCHIVE_FATAL); 4959 } 4960 } 4961 } 4962 #endif 4963 } 4964 /* 4965 * - Count up directory elements. 4966 * - Find out the position which points the last position of 4967 * path separator('/'). 4968 */ 4969 slash = NULL; 4970 file->dircnt = 0; 4971 for (; *p != '\0'; p++) 4972 if (*p == '/') { 4973 slash = p; 4974 file->dircnt++; 4975 } 4976 if (slash == NULL) { 4977 /* The pathname doesn't have a parent directory. */ 4978 file->parentdir.length = len; 4979 archive_string_copy(&(file->basename), &(file->parentdir)); 4980 archive_string_empty(&(file->parentdir)); 4981 *file->parentdir.s = '\0'; 4982 return (ret); 4983 } 4984 4985 /* Make a basename from dirname and slash */ 4986 *slash = '\0'; 4987 file->parentdir.length = slash - dirname; 4988 archive_strcpy(&(file->basename), slash + 1); 4989 if (archive_entry_filetype(file->entry) == AE_IFDIR) 4990 file->dircnt ++; 4991 return (ret); 4992 } 4993 4994 /* 4995 * Register a entry to get a hardlink target. 4996 */ 4997 static int 4998 isofile_register_hardlink(struct archive_write *a, struct isofile *file) 4999 { 5000 struct iso9660 *iso9660 = a->format_data; 5001 struct hardlink *hl; 5002 const char *pathname; 5003 5004 archive_entry_set_nlink(file->entry, 1); 5005 pathname = archive_entry_hardlink(file->entry); 5006 if (pathname == NULL) { 5007 /* This `file` is a hardlink target. */ 5008 hl = malloc(sizeof(*hl)); 5009 if (hl == NULL) { 5010 archive_set_error(&a->archive, ENOMEM, 5011 "Can't allocate memory"); 5012 return (ARCHIVE_FATAL); 5013 } 5014 hl->nlink = 1; 5015 /* A hardlink target must be the first position. */ 5016 file->hlnext = NULL; 5017 hl->file_list.first = file; 5018 hl->file_list.last = &(file->hlnext); 5019 __archive_rb_tree_insert_node(&(iso9660->hardlink_rbtree), 5020 (struct archive_rb_node *)hl); 5021 } else { 5022 hl = (struct hardlink *)__archive_rb_tree_find_node( 5023 &(iso9660->hardlink_rbtree), pathname); 5024 if (hl != NULL) { 5025 /* Insert `file` entry into the tail. */ 5026 file->hlnext = NULL; 5027 *hl->file_list.last = file; 5028 hl->file_list.last = &(file->hlnext); 5029 hl->nlink++; 5030 } 5031 archive_entry_unset_size(file->entry); 5032 } 5033 5034 return (ARCHIVE_OK); 5035 } 5036 5037 /* 5038 * Hardlinked files have to have the same location of extent. 5039 * We have to find out hardlink target entries for the entries 5040 * which have a hardlink target name. 5041 */ 5042 static void 5043 isofile_connect_hardlink_files(struct iso9660 *iso9660) 5044 { 5045 struct archive_rb_node *n; 5046 struct hardlink *hl; 5047 struct isofile *target, *nf; 5048 5049 ARCHIVE_RB_TREE_FOREACH(n, &(iso9660->hardlink_rbtree)) { 5050 hl = (struct hardlink *)n; 5051 5052 /* The first entry must be a hardlink target. */ 5053 target = hl->file_list.first; 5054 archive_entry_set_nlink(target->entry, hl->nlink); 5055 /* Set a hardlink target to reference entries. */ 5056 for (nf = target->hlnext; 5057 nf != NULL; nf = nf->hlnext) { 5058 nf->hardlink_target = target; 5059 archive_entry_set_nlink(nf->entry, hl->nlink); 5060 } 5061 } 5062 } 5063 5064 static int 5065 isofile_hd_cmp_node(const struct archive_rb_node *n1, 5066 const struct archive_rb_node *n2) 5067 { 5068 const struct hardlink *h1 = (const struct hardlink *)n1; 5069 const struct hardlink *h2 = (const struct hardlink *)n2; 5070 5071 return (strcmp(archive_entry_pathname(h1->file_list.first->entry), 5072 archive_entry_pathname(h2->file_list.first->entry))); 5073 } 5074 5075 static int 5076 isofile_hd_cmp_key(const struct archive_rb_node *n, const void *key) 5077 { 5078 const struct hardlink *h = (const struct hardlink *)n; 5079 5080 return (strcmp(archive_entry_pathname(h->file_list.first->entry), 5081 (const char *)key)); 5082 } 5083 5084 static void 5085 isofile_init_hardlinks(struct iso9660 *iso9660) 5086 { 5087 static const struct archive_rb_tree_ops rb_ops = { 5088 isofile_hd_cmp_node, isofile_hd_cmp_key, 5089 }; 5090 5091 __archive_rb_tree_init(&(iso9660->hardlink_rbtree), &rb_ops); 5092 } 5093 5094 static void 5095 isofile_free_hardlinks(struct iso9660 *iso9660) 5096 { 5097 struct archive_rb_node *n, *next; 5098 5099 for (n = ARCHIVE_RB_TREE_MIN(&(iso9660->hardlink_rbtree)); n;) { 5100 next = __archive_rb_tree_iterate(&(iso9660->hardlink_rbtree), 5101 n, ARCHIVE_RB_DIR_RIGHT); 5102 free(n); 5103 n = next; 5104 } 5105 } 5106 5107 static struct isoent * 5108 isoent_new(struct isofile *file) 5109 { 5110 struct isoent *isoent; 5111 static const struct archive_rb_tree_ops rb_ops = { 5112 isoent_cmp_node, isoent_cmp_key, 5113 }; 5114 5115 isoent = calloc(1, sizeof(*isoent)); 5116 if (isoent == NULL) 5117 return (NULL); 5118 isoent->file = file; 5119 isoent->children.first = NULL; 5120 isoent->children.last = &(isoent->children.first); 5121 __archive_rb_tree_init(&(isoent->rbtree), &rb_ops); 5122 isoent->subdirs.first = NULL; 5123 isoent->subdirs.last = &(isoent->subdirs.first); 5124 isoent->extr_rec_list.first = NULL; 5125 isoent->extr_rec_list.last = &(isoent->extr_rec_list.first); 5126 isoent->extr_rec_list.current = NULL; 5127 if (archive_entry_filetype(file->entry) == AE_IFDIR) 5128 isoent->dir = 1; 5129 5130 return (isoent); 5131 } 5132 5133 static inline struct isoent * 5134 isoent_clone(struct isoent *src) 5135 { 5136 return (isoent_new(src->file)); 5137 } 5138 5139 static void 5140 _isoent_free(struct isoent *isoent) 5141 { 5142 struct extr_rec *er, *er_next; 5143 5144 free(isoent->children_sorted); 5145 free(isoent->identifier); 5146 er = isoent->extr_rec_list.first; 5147 while (er != NULL) { 5148 er_next = er->next; 5149 free(er); 5150 er = er_next; 5151 } 5152 free(isoent); 5153 } 5154 5155 static void 5156 isoent_free_all(struct isoent *isoent) 5157 { 5158 struct isoent *np, *np_temp; 5159 5160 if (isoent == NULL) 5161 return; 5162 np = isoent; 5163 for (;;) { 5164 if (np->dir) { 5165 if (np->children.first != NULL) { 5166 /* Enter to sub directories. */ 5167 np = np->children.first; 5168 continue; 5169 } 5170 } 5171 for (;;) { 5172 np_temp = np; 5173 if (np->chnext == NULL) { 5174 /* Return to the parent directory. */ 5175 np = np->parent; 5176 _isoent_free(np_temp); 5177 if (np == np_temp) 5178 return; 5179 } else { 5180 np = np->chnext; 5181 _isoent_free(np_temp); 5182 break; 5183 } 5184 } 5185 } 5186 } 5187 5188 static struct isoent * 5189 isoent_create_virtual_dir(struct archive_write *a, struct iso9660 *iso9660, const char *pathname) 5190 { 5191 struct isofile *file; 5192 struct isoent *isoent; 5193 5194 file = isofile_new(a, NULL); 5195 if (file == NULL) 5196 return (NULL); 5197 archive_entry_set_pathname(file->entry, pathname); 5198 archive_entry_unset_mtime(file->entry); 5199 archive_entry_unset_atime(file->entry); 5200 archive_entry_unset_ctime(file->entry); 5201 archive_entry_set_uid(file->entry, getuid()); 5202 archive_entry_set_gid(file->entry, getgid()); 5203 archive_entry_set_mode(file->entry, 0555 | AE_IFDIR); 5204 archive_entry_set_nlink(file->entry, 2); 5205 if (isofile_gen_utility_names(a, file) < ARCHIVE_WARN) { 5206 isofile_free(file); 5207 return (NULL); 5208 } 5209 isofile_add_entry(iso9660, file); 5210 5211 isoent = isoent_new(file); 5212 if (isoent == NULL) 5213 return (NULL); 5214 isoent->dir = 1; 5215 isoent->virtual = 1; 5216 5217 return (isoent); 5218 } 5219 5220 static int 5221 isoent_cmp_node(const struct archive_rb_node *n1, 5222 const struct archive_rb_node *n2) 5223 { 5224 const struct isoent *e1 = (const struct isoent *)n1; 5225 const struct isoent *e2 = (const struct isoent *)n2; 5226 5227 return (strcmp(e1->file->basename.s, e2->file->basename.s)); 5228 } 5229 5230 static int 5231 isoent_cmp_key(const struct archive_rb_node *n, const void *key) 5232 { 5233 const struct isoent *e = (const struct isoent *)n; 5234 5235 return (strcmp(e->file->basename.s, (const char *)key)); 5236 } 5237 5238 static int 5239 isoent_add_child_head(struct isoent *parent, struct isoent *child) 5240 { 5241 5242 if (!__archive_rb_tree_insert_node( 5243 &(parent->rbtree), (struct archive_rb_node *)child)) 5244 return (0); 5245 if ((child->chnext = parent->children.first) == NULL) 5246 parent->children.last = &(child->chnext); 5247 parent->children.first = child; 5248 parent->children.cnt++; 5249 child->parent = parent; 5250 5251 /* Add a child to a sub-directory chain */ 5252 if (child->dir) { 5253 if ((child->drnext = parent->subdirs.first) == NULL) 5254 parent->subdirs.last = &(child->drnext); 5255 parent->subdirs.first = child; 5256 parent->subdirs.cnt++; 5257 child->parent = parent; 5258 } else 5259 child->drnext = NULL; 5260 return (1); 5261 } 5262 5263 static int 5264 isoent_add_child_tail(struct isoent *parent, struct isoent *child) 5265 { 5266 5267 if (!__archive_rb_tree_insert_node( 5268 &(parent->rbtree), (struct archive_rb_node *)child)) 5269 return (0); 5270 child->chnext = NULL; 5271 *parent->children.last = child; 5272 parent->children.last = &(child->chnext); 5273 parent->children.cnt++; 5274 child->parent = parent; 5275 5276 /* Add a child to a sub-directory chain */ 5277 child->drnext = NULL; 5278 if (child->dir) { 5279 *parent->subdirs.last = child; 5280 parent->subdirs.last = &(child->drnext); 5281 parent->subdirs.cnt++; 5282 child->parent = parent; 5283 } 5284 return (1); 5285 } 5286 5287 static void 5288 isoent_remove_child(struct isoent *parent, struct isoent *child) 5289 { 5290 struct isoent *ent; 5291 5292 /* Remove a child entry from children chain. */ 5293 ent = parent->children.first; 5294 while (ent->chnext != child) 5295 ent = ent->chnext; 5296 if ((ent->chnext = ent->chnext->chnext) == NULL) 5297 parent->children.last = &(ent->chnext); 5298 parent->children.cnt--; 5299 5300 if (child->dir) { 5301 /* Remove a child entry from sub-directory chain. */ 5302 ent = parent->subdirs.first; 5303 while (ent->drnext != child) 5304 ent = ent->drnext; 5305 if ((ent->drnext = ent->drnext->drnext) == NULL) 5306 parent->subdirs.last = &(ent->drnext); 5307 parent->subdirs.cnt--; 5308 } 5309 5310 __archive_rb_tree_remove_node(&(parent->rbtree), 5311 (struct archive_rb_node *)child); 5312 } 5313 5314 static int 5315 isoent_clone_tree(struct archive_write *a, struct isoent **nroot, 5316 struct isoent *root) 5317 { 5318 struct isoent *np, *xroot, *newent; 5319 5320 np = root; 5321 xroot = NULL; 5322 do { 5323 newent = isoent_clone(np); 5324 if (newent == NULL) { 5325 archive_set_error(&a->archive, ENOMEM, 5326 "Can't allocate memory"); 5327 return (ARCHIVE_FATAL); 5328 } 5329 if (xroot == NULL) { 5330 *nroot = xroot = newent; 5331 newent->parent = xroot; 5332 } else 5333 isoent_add_child_tail(xroot, newent); 5334 if (np->dir && np->children.first != NULL) { 5335 /* Enter to sub directories. */ 5336 np = np->children.first; 5337 xroot = newent; 5338 continue; 5339 } 5340 while (np != np->parent) { 5341 if (np->chnext == NULL) { 5342 /* Return to the parent directory. */ 5343 np = np->parent; 5344 xroot = xroot->parent; 5345 } else { 5346 np = np->chnext; 5347 break; 5348 } 5349 } 5350 } while (np != np->parent); 5351 5352 return (ARCHIVE_OK); 5353 } 5354 5355 /* 5356 * Setup directory locations. 5357 */ 5358 static void 5359 isoent_setup_directory_location(struct iso9660 *iso9660, int location, 5360 struct vdd *vdd) 5361 { 5362 struct isoent *np; 5363 int depth; 5364 5365 vdd->total_dir_block = 0; 5366 depth = 0; 5367 np = vdd->rootent; 5368 do { 5369 int block; 5370 5371 np->dir_block = calculate_directory_descriptors( 5372 iso9660, vdd, np, depth); 5373 vdd->total_dir_block += np->dir_block; 5374 np->dir_location = location; 5375 location += np->dir_block; 5376 block = extra_setup_location(np, location); 5377 vdd->total_dir_block += block; 5378 location += block; 5379 5380 if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) { 5381 /* Enter to sub directories. */ 5382 np = np->subdirs.first; 5383 depth++; 5384 continue; 5385 } 5386 while (np != np->parent) { 5387 if (np->drnext == NULL) { 5388 /* Return to the parent directory. */ 5389 np = np->parent; 5390 depth--; 5391 } else { 5392 np = np->drnext; 5393 break; 5394 } 5395 } 5396 } while (np != np->parent); 5397 } 5398 5399 static void 5400 _isoent_file_location(struct iso9660 *iso9660, struct isoent *isoent, 5401 int *symlocation) 5402 { 5403 struct isoent **children; 5404 int n; 5405 5406 if (isoent->children.cnt == 0) 5407 return; 5408 5409 children = isoent->children_sorted; 5410 for (n = 0; n < isoent->children.cnt; n++) { 5411 struct isoent *np; 5412 struct isofile *file; 5413 5414 np = children[n]; 5415 if (np->dir) 5416 continue; 5417 if (np == iso9660->el_torito.boot) 5418 continue; 5419 file = np->file; 5420 if (file->boot || file->hardlink_target != NULL) 5421 continue; 5422 if (archive_entry_filetype(file->entry) == AE_IFLNK || 5423 file->content.size == 0) { 5424 /* 5425 * Do not point a valid location. 5426 * Make sure entry is not hardlink file. 5427 */ 5428 file->content.location = (*symlocation)--; 5429 continue; 5430 } 5431 5432 file->write_content = 1; 5433 } 5434 } 5435 5436 /* 5437 * Setup file locations. 5438 */ 5439 static void 5440 isoent_setup_file_location(struct iso9660 *iso9660, int location) 5441 { 5442 struct isoent *isoent; 5443 struct isoent *np; 5444 struct isofile *file; 5445 size_t size; 5446 int block; 5447 int depth; 5448 int joliet; 5449 int symlocation; 5450 int total_block; 5451 5452 iso9660->total_file_block = 0; 5453 if ((isoent = iso9660->el_torito.catalog) != NULL) { 5454 isoent->file->content.location = location; 5455 block = (int)((archive_entry_size(isoent->file->entry) + 5456 LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS); 5457 location += block; 5458 iso9660->total_file_block += block; 5459 } 5460 if ((isoent = iso9660->el_torito.boot) != NULL) { 5461 isoent->file->content.location = location; 5462 size = fd_boot_image_size(iso9660->el_torito.media_type); 5463 if (size == 0) 5464 size = (size_t)archive_entry_size(isoent->file->entry); 5465 block = ((int)size + LOGICAL_BLOCK_SIZE -1) 5466 >> LOGICAL_BLOCK_BITS; 5467 location += block; 5468 iso9660->total_file_block += block; 5469 isoent->file->content.blocks = block; 5470 } 5471 5472 depth = 0; 5473 symlocation = -16; 5474 if (!iso9660->opt.rr && iso9660->opt.joliet) { 5475 joliet = 1; 5476 np = iso9660->joliet.rootent; 5477 } else { 5478 joliet = 0; 5479 np = iso9660->primary.rootent; 5480 } 5481 do { 5482 _isoent_file_location(iso9660, np, &symlocation); 5483 5484 if (np->subdirs.first != NULL && 5485 (joliet || 5486 ((iso9660->opt.rr == OPT_RR_DISABLED && 5487 depth + 2 < iso9660->primary.max_depth) || 5488 (iso9660->opt.rr && 5489 depth + 1 < iso9660->primary.max_depth)))) { 5490 /* Enter to sub directories. */ 5491 np = np->subdirs.first; 5492 depth++; 5493 continue; 5494 } 5495 while (np != np->parent) { 5496 if (np->drnext == NULL) { 5497 /* Return to the parent directory. */ 5498 np = np->parent; 5499 depth--; 5500 } else { 5501 np = np->drnext; 5502 break; 5503 } 5504 } 5505 } while (np != np->parent); 5506 5507 total_block = 0; 5508 for (file = iso9660->data_file_list.first; 5509 file != NULL; file = file->datanext) { 5510 5511 if (!file->write_content) 5512 continue; 5513 5514 file->cur_content = &(file->content); 5515 do { 5516 file->cur_content->location = location; 5517 location += file->cur_content->blocks; 5518 total_block += file->cur_content->blocks; 5519 /* Next fragment */ 5520 file->cur_content = file->cur_content->next; 5521 } while (file->cur_content != NULL); 5522 } 5523 iso9660->total_file_block += total_block; 5524 } 5525 5526 static int 5527 get_path_component(char *name, size_t n, const char *fn) 5528 { 5529 char *p; 5530 size_t l; 5531 5532 p = strchr(fn, '/'); 5533 if (p == NULL) { 5534 if ((l = strlen(fn)) == 0) 5535 return (0); 5536 } else 5537 l = p - fn; 5538 if (l > n -1) 5539 return (-1); 5540 memcpy(name, fn, l); 5541 name[l] = '\0'; 5542 5543 return ((int)l); 5544 } 5545 5546 /* 5547 * Add a new entry into the tree. 5548 */ 5549 static int 5550 isoent_tree(struct archive_write *a, struct isoent **isoentpp) 5551 { 5552 #if defined(_WIN32) && !defined(__CYGWIN__) 5553 char name[_MAX_FNAME];/* Included null terminator size. */ 5554 #elif defined(NAME_MAX) && NAME_MAX >= 255 5555 char name[NAME_MAX+1]; 5556 #else 5557 char name[256]; 5558 #endif 5559 struct iso9660 *iso9660 = a->format_data; 5560 struct isoent *dent, *isoent, *np; 5561 struct isofile *f1, *f2; 5562 const char *fn, *p; 5563 int l; 5564 5565 isoent = *isoentpp; 5566 dent = iso9660->primary.rootent; 5567 if (isoent->file->parentdir.length > 0) 5568 fn = p = isoent->file->parentdir.s; 5569 else 5570 fn = p = ""; 5571 5572 /* 5573 * If the path of the parent directory of `isoent' entry is 5574 * the same as the path of `cur_dirent', add isoent to 5575 * `cur_dirent'. 5576 */ 5577 if (archive_strlen(&(iso9660->cur_dirstr)) 5578 == archive_strlen(&(isoent->file->parentdir)) && 5579 strcmp(iso9660->cur_dirstr.s, fn) == 0) { 5580 if (!isoent_add_child_tail(iso9660->cur_dirent, isoent)) { 5581 np = (struct isoent *)__archive_rb_tree_find_node( 5582 &(iso9660->cur_dirent->rbtree), 5583 isoent->file->basename.s); 5584 goto same_entry; 5585 } 5586 return (ARCHIVE_OK); 5587 } 5588 5589 for (;;) { 5590 l = get_path_component(name, sizeof(name), fn); 5591 if (l == 0) { 5592 np = NULL; 5593 break; 5594 } 5595 if (l < 0) { 5596 archive_set_error(&a->archive, 5597 ARCHIVE_ERRNO_MISC, 5598 "A name buffer is too small"); 5599 _isoent_free(isoent); 5600 return (ARCHIVE_FATAL); 5601 } 5602 5603 np = isoent_find_child(dent, name); 5604 if (np == NULL || fn[0] == '\0') 5605 break; 5606 5607 /* Find next subdirectory. */ 5608 if (!np->dir) { 5609 /* NOT Directory! */ 5610 archive_set_error(&a->archive, 5611 ARCHIVE_ERRNO_MISC, 5612 "`%s' is not directory, we cannot insert `%s' ", 5613 archive_entry_pathname(np->file->entry), 5614 archive_entry_pathname(isoent->file->entry)); 5615 _isoent_free(isoent); 5616 *isoentpp = NULL; 5617 return (ARCHIVE_FAILED); 5618 } 5619 fn += l; 5620 if (fn[0] == '/') 5621 fn++; 5622 dent = np; 5623 } 5624 if (np == NULL) { 5625 /* 5626 * Create virtual parent directories. 5627 */ 5628 while (fn[0] != '\0') { 5629 struct isoent *vp; 5630 struct archive_string as; 5631 5632 archive_string_init(&as); 5633 archive_strncat(&as, p, fn - p + l); 5634 if (as.s[as.length-1] == '/') { 5635 as.s[as.length-1] = '\0'; 5636 as.length--; 5637 } 5638 vp = isoent_create_virtual_dir(a, iso9660, as.s); 5639 if (vp == NULL) { 5640 archive_string_free(&as); 5641 archive_set_error(&a->archive, ENOMEM, 5642 "Can't allocate memory"); 5643 _isoent_free(isoent); 5644 *isoentpp = NULL; 5645 return (ARCHIVE_FATAL); 5646 } 5647 archive_string_free(&as); 5648 5649 if (vp->file->dircnt > iso9660->dircnt_max) 5650 iso9660->dircnt_max = vp->file->dircnt; 5651 isoent_add_child_tail(dent, vp); 5652 np = vp; 5653 5654 fn += l; 5655 if (fn[0] == '/') 5656 fn++; 5657 l = get_path_component(name, sizeof(name), fn); 5658 if (l < 0) { 5659 archive_string_free(&as); 5660 archive_set_error(&a->archive, 5661 ARCHIVE_ERRNO_MISC, 5662 "A name buffer is too small"); 5663 _isoent_free(isoent); 5664 *isoentpp = NULL; 5665 return (ARCHIVE_FATAL); 5666 } 5667 dent = np; 5668 } 5669 5670 /* Found out the parent directory where isoent can be 5671 * inserted. */ 5672 iso9660->cur_dirent = dent; 5673 archive_string_empty(&(iso9660->cur_dirstr)); 5674 archive_string_ensure(&(iso9660->cur_dirstr), 5675 archive_strlen(&(dent->file->parentdir)) + 5676 archive_strlen(&(dent->file->basename)) + 2); 5677 if (archive_strlen(&(dent->file->parentdir)) + 5678 archive_strlen(&(dent->file->basename)) == 0) 5679 iso9660->cur_dirstr.s[0] = 0; 5680 else { 5681 if (archive_strlen(&(dent->file->parentdir)) > 0) { 5682 archive_string_copy(&(iso9660->cur_dirstr), 5683 &(dent->file->parentdir)); 5684 archive_strappend_char(&(iso9660->cur_dirstr), '/'); 5685 } 5686 archive_string_concat(&(iso9660->cur_dirstr), 5687 &(dent->file->basename)); 5688 } 5689 5690 if (!isoent_add_child_tail(dent, isoent)) { 5691 np = (struct isoent *)__archive_rb_tree_find_node( 5692 &(dent->rbtree), isoent->file->basename.s); 5693 goto same_entry; 5694 } 5695 return (ARCHIVE_OK); 5696 } 5697 5698 same_entry: 5699 /* 5700 * We have already has the entry the filename of which is 5701 * the same. 5702 */ 5703 f1 = np->file; 5704 f2 = isoent->file; 5705 5706 /* If the file type of entries is different, 5707 * we cannot handle it. */ 5708 if (archive_entry_filetype(f1->entry) != 5709 archive_entry_filetype(f2->entry)) { 5710 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 5711 "Found duplicate entries `%s' and its file type is " 5712 "different", 5713 archive_entry_pathname(f1->entry)); 5714 _isoent_free(isoent); 5715 *isoentpp = NULL; 5716 return (ARCHIVE_FAILED); 5717 } 5718 5719 /* Swap file entries. */ 5720 np->file = f2; 5721 isoent->file = f1; 5722 np->virtual = 0; 5723 5724 _isoent_free(isoent); 5725 *isoentpp = np; 5726 return (ARCHIVE_OK); 5727 } 5728 5729 /* 5730 * Find a entry from `isoent' 5731 */ 5732 static struct isoent * 5733 isoent_find_child(struct isoent *isoent, const char *child_name) 5734 { 5735 struct isoent *np; 5736 5737 np = (struct isoent *)__archive_rb_tree_find_node( 5738 &(isoent->rbtree), child_name); 5739 return (np); 5740 } 5741 5742 /* 5743 * Find a entry full-path of which is specified by `fn' parameter, 5744 * in the tree. 5745 */ 5746 static struct isoent * 5747 isoent_find_entry(struct isoent *rootent, const char *fn) 5748 { 5749 #if defined(_WIN32) && !defined(__CYGWIN__) 5750 char name[_MAX_FNAME];/* Included null terminator size. */ 5751 #elif defined(NAME_MAX) && NAME_MAX >= 255 5752 char name[NAME_MAX+1]; 5753 #else 5754 char name[256]; 5755 #endif 5756 struct isoent *isoent, *np; 5757 int l; 5758 5759 isoent = rootent; 5760 np = NULL; 5761 for (;;) { 5762 l = get_path_component(name, sizeof(name), fn); 5763 if (l == 0) 5764 break; 5765 fn += l; 5766 if (fn[0] == '/') 5767 fn++; 5768 5769 np = isoent_find_child(isoent, name); 5770 if (np == NULL) 5771 break; 5772 if (fn[0] == '\0') 5773 break;/* We found out the entry */ 5774 5775 /* Try sub directory. */ 5776 isoent = np; 5777 np = NULL; 5778 if (!isoent->dir) 5779 break;/* Not directory */ 5780 } 5781 5782 return (np); 5783 } 5784 5785 /* 5786 * Following idr_* functions are used for resolving duplicated filenames 5787 * and unreceivable filenames to generate ISO9660/Joliet Identifiers. 5788 */ 5789 5790 static void 5791 idr_relaxed_filenames(char *map) 5792 { 5793 int i; 5794 5795 for (i = 0x21; i <= 0x2F; i++) 5796 map[i] = 1; 5797 for (i = 0x3A; i <= 0x41; i++) 5798 map[i] = 1; 5799 for (i = 0x5B; i <= 0x5E; i++) 5800 map[i] = 1; 5801 map[0x60] = 1; 5802 for (i = 0x7B; i <= 0x7E; i++) 5803 map[i] = 1; 5804 } 5805 5806 static void 5807 idr_init(struct iso9660 *iso9660, struct vdd *vdd, struct idr *idr) 5808 { 5809 5810 idr->idrent_pool = NULL; 5811 idr->pool_size = 0; 5812 if (vdd->vdd_type != VDD_JOLIET) { 5813 if (iso9660->opt.iso_level <= 3) { 5814 memcpy(idr->char_map, d_characters_map, 5815 sizeof(idr->char_map)); 5816 } else { 5817 memcpy(idr->char_map, d1_characters_map, 5818 sizeof(idr->char_map)); 5819 idr_relaxed_filenames(idr->char_map); 5820 } 5821 } 5822 } 5823 5824 static void 5825 idr_cleanup(struct idr *idr) 5826 { 5827 free(idr->idrent_pool); 5828 } 5829 5830 static int 5831 idr_ensure_poolsize(struct archive_write *a, struct idr *idr, 5832 int cnt) 5833 { 5834 5835 if (idr->pool_size < cnt) { 5836 void *p; 5837 const int bk = (1 << 7) - 1; 5838 int psize; 5839 5840 psize = (cnt + bk) & ~bk; 5841 p = realloc(idr->idrent_pool, sizeof(struct idrent) * psize); 5842 if (p == NULL) { 5843 archive_set_error(&a->archive, ENOMEM, 5844 "Can't allocate memory"); 5845 return (ARCHIVE_FATAL); 5846 } 5847 idr->idrent_pool = (struct idrent *)p; 5848 idr->pool_size = psize; 5849 } 5850 return (ARCHIVE_OK); 5851 } 5852 5853 static int 5854 idr_start(struct archive_write *a, struct idr *idr, int cnt, int ffmax, 5855 int num_size, int null_size, const struct archive_rb_tree_ops *rbt_ops) 5856 { 5857 int r; 5858 5859 (void)ffmax; /* UNUSED */ 5860 5861 r = idr_ensure_poolsize(a, idr, cnt); 5862 if (r != ARCHIVE_OK) 5863 return (r); 5864 __archive_rb_tree_init(&(idr->rbtree), rbt_ops); 5865 idr->wait_list.first = NULL; 5866 idr->wait_list.last = &(idr->wait_list.first); 5867 idr->pool_idx = 0; 5868 idr->num_size = num_size; 5869 idr->null_size = null_size; 5870 return (ARCHIVE_OK); 5871 } 5872 5873 static void 5874 idr_register(struct idr *idr, struct isoent *isoent, int weight, int noff) 5875 { 5876 struct idrent *idrent, *n; 5877 5878 idrent = &(idr->idrent_pool[idr->pool_idx++]); 5879 idrent->wnext = idrent->avail = NULL; 5880 idrent->isoent = isoent; 5881 idrent->weight = weight; 5882 idrent->noff = noff; 5883 idrent->rename_num = 0; 5884 5885 if (!__archive_rb_tree_insert_node(&(idr->rbtree), &(idrent->rbnode))) { 5886 n = (struct idrent *)__archive_rb_tree_find_node( 5887 &(idr->rbtree), idrent->isoent); 5888 if (n != NULL) { 5889 /* this `idrent' needs to rename. */ 5890 idrent->avail = n; 5891 *idr->wait_list.last = idrent; 5892 idr->wait_list.last = &(idrent->wnext); 5893 } 5894 } 5895 } 5896 5897 static void 5898 idr_extend_identifier(struct idrent *wnp, int numsize, int nullsize) 5899 { 5900 unsigned char *p; 5901 int wnp_ext_off; 5902 5903 wnp_ext_off = wnp->isoent->ext_off; 5904 if (wnp->noff + numsize != wnp_ext_off) { 5905 p = (unsigned char *)wnp->isoent->identifier; 5906 /* Extend the filename; foo.c --> foo___.c */ 5907 memmove(p + wnp->noff + numsize, p + wnp_ext_off, 5908 wnp->isoent->ext_len + nullsize); 5909 wnp->isoent->ext_off = wnp_ext_off = wnp->noff + numsize; 5910 wnp->isoent->id_len = wnp_ext_off + wnp->isoent->ext_len; 5911 } 5912 } 5913 5914 static void 5915 idr_resolve(struct idr *idr, void (*fsetnum)(unsigned char *p, int num)) 5916 { 5917 struct idrent *n; 5918 unsigned char *p; 5919 5920 for (n = idr->wait_list.first; n != NULL; n = n->wnext) { 5921 idr_extend_identifier(n, idr->num_size, idr->null_size); 5922 p = (unsigned char *)n->isoent->identifier + n->noff; 5923 do { 5924 fsetnum(p, n->avail->rename_num++); 5925 } while (!__archive_rb_tree_insert_node( 5926 &(idr->rbtree), &(n->rbnode))); 5927 } 5928 } 5929 5930 static void 5931 idr_set_num(unsigned char *p, int num) 5932 { 5933 static const char xdig[] = { 5934 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 5935 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 5936 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 5937 'U', 'V', 'W', 'X', 'Y', 'Z' 5938 }; 5939 5940 num %= sizeof(xdig) * sizeof(xdig) * sizeof(xdig); 5941 p[0] = xdig[(num / (sizeof(xdig) * sizeof(xdig)))]; 5942 num %= sizeof(xdig) * sizeof(xdig); 5943 p[1] = xdig[ (num / sizeof(xdig))]; 5944 num %= sizeof(xdig); 5945 p[2] = xdig[num]; 5946 } 5947 5948 static void 5949 idr_set_num_beutf16(unsigned char *p, int num) 5950 { 5951 static const uint16_t xdig[] = { 5952 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 5953 0x0036, 0x0037, 0x0038, 0x0039, 5954 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 5955 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 5956 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 5957 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 5958 0x0059, 0x005A 5959 }; 5960 #define XDIG_CNT (sizeof(xdig)/sizeof(xdig[0])) 5961 5962 num %= XDIG_CNT * XDIG_CNT * XDIG_CNT; 5963 archive_be16enc(p, xdig[(num / (XDIG_CNT * XDIG_CNT))]); 5964 num %= XDIG_CNT * XDIG_CNT; 5965 archive_be16enc(p+2, xdig[ (num / XDIG_CNT)]); 5966 num %= XDIG_CNT; 5967 archive_be16enc(p+4, xdig[num]); 5968 } 5969 5970 /* 5971 * Generate ISO9660 Identifier. 5972 */ 5973 static int 5974 isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, 5975 struct idr *idr) 5976 { 5977 struct iso9660 *iso9660; 5978 struct isoent *np; 5979 char *p; 5980 int l, r; 5981 const char *char_map; 5982 char allow_ldots, allow_multidot, allow_period, allow_vernum; 5983 int fnmax, ffmax, dnmax; 5984 static const struct archive_rb_tree_ops rb_ops = { 5985 isoent_cmp_node_iso9660, isoent_cmp_key_iso9660 5986 }; 5987 5988 if (isoent->children.cnt == 0) 5989 return (0); 5990 5991 iso9660 = a->format_data; 5992 char_map = idr->char_map; 5993 if (iso9660->opt.iso_level <= 3) { 5994 allow_ldots = 0; 5995 allow_multidot = 0; 5996 allow_period = 1; 5997 allow_vernum = iso9660->opt.allow_vernum; 5998 if (iso9660->opt.iso_level == 1) { 5999 fnmax = 8; 6000 ffmax = 12;/* fnmax + '.' + 3 */ 6001 dnmax = 8; 6002 } else { 6003 fnmax = 30; 6004 ffmax = 31; 6005 dnmax = 31; 6006 } 6007 } else { 6008 allow_ldots = allow_multidot = 1; 6009 allow_period = allow_vernum = 0; 6010 if (iso9660->opt.rr) 6011 /* 6012 * MDR : The maximum size of Directory Record(254). 6013 * DRL : A Directory Record Length(33). 6014 * CE : A size of SUSP CE System Use Entry(28). 6015 * MDR - DRL - CE = 254 - 33 - 28 = 193. 6016 */ 6017 fnmax = ffmax = dnmax = 193; 6018 else 6019 /* 6020 * XA : CD-ROM XA System Use Extension 6021 * Information(14). 6022 * MDR - DRL - XA = 254 - 33 -14 = 207. 6023 */ 6024 fnmax = ffmax = dnmax = 207; 6025 } 6026 6027 r = idr_start(a, idr, isoent->children.cnt, ffmax, 3, 1, &rb_ops); 6028 if (r < 0) 6029 return (r); 6030 6031 for (np = isoent->children.first; np != NULL; np = np->chnext) { 6032 char *dot, *xdot; 6033 int ext_off, noff, weight; 6034 6035 l = (int)np->file->basename.length; 6036 p = malloc(l+31+2+1); 6037 if (p == NULL) { 6038 archive_set_error(&a->archive, ENOMEM, 6039 "Can't allocate memory"); 6040 return (ARCHIVE_FATAL); 6041 } 6042 memcpy(p, np->file->basename.s, l); 6043 p[l] = '\0'; 6044 np->identifier = p; 6045 6046 dot = xdot = NULL; 6047 if (!allow_ldots) { 6048 /* 6049 * If there is a '.' character at the first byte, 6050 * it has to be replaced by '_' character. 6051 */ 6052 if (*p == '.') 6053 *p++ = '_'; 6054 } 6055 for (;*p; p++) { 6056 if (*p & 0x80) { 6057 *p = '_'; 6058 continue; 6059 } 6060 if (char_map[(unsigned char)*p]) { 6061 /* if iso-level is '4', a character '.' is 6062 * allowed by char_map. */ 6063 if (*p == '.') { 6064 xdot = dot; 6065 dot = p; 6066 } 6067 continue; 6068 } 6069 if (*p >= 'a' && *p <= 'z') { 6070 *p -= 'a' - 'A'; 6071 continue; 6072 } 6073 if (*p == '.') { 6074 xdot = dot; 6075 dot = p; 6076 if (allow_multidot) 6077 continue; 6078 } 6079 *p = '_'; 6080 } 6081 p = np->identifier; 6082 weight = -1; 6083 if (dot == NULL) { 6084 int nammax; 6085 6086 if (np->dir) 6087 nammax = dnmax; 6088 else 6089 nammax = fnmax; 6090 6091 if (l > nammax) { 6092 p[nammax] = '\0'; 6093 weight = nammax; 6094 ext_off = nammax; 6095 } else 6096 ext_off = l; 6097 } else { 6098 *dot = '.'; 6099 ext_off = (int)(dot - p); 6100 6101 if (iso9660->opt.iso_level == 1) { 6102 if (dot - p <= 8) { 6103 if (strlen(dot) > 4) { 6104 /* A length of a file extension 6105 * must be less than 4 */ 6106 dot[4] = '\0'; 6107 weight = 0; 6108 } 6109 } else { 6110 p[8] = dot[0]; 6111 p[9] = dot[1]; 6112 p[10] = dot[2]; 6113 p[11] = dot[3]; 6114 p[12] = '\0'; 6115 weight = 8; 6116 ext_off = 8; 6117 } 6118 } else if (np->dir) { 6119 if (l > dnmax) { 6120 p[dnmax] = '\0'; 6121 weight = dnmax; 6122 if (ext_off > dnmax) 6123 ext_off = dnmax; 6124 } 6125 } else if (l > ffmax) { 6126 int extlen = (int)strlen(dot); 6127 int xdoff; 6128 6129 if (xdot != NULL) 6130 xdoff = (int)(xdot - p); 6131 else 6132 xdoff = 0; 6133 6134 if (extlen > 1 && xdoff < fnmax-1) { 6135 int off; 6136 6137 if (extlen > ffmax) 6138 extlen = ffmax; 6139 off = ffmax - extlen; 6140 if (off == 0) { 6141 /* A dot('.') character 6142 * doesn't place to the first 6143 * byte of identifier. */ 6144 off ++; 6145 extlen --; 6146 } 6147 memmove(p+off, dot, extlen); 6148 p[ffmax] = '\0'; 6149 ext_off = off; 6150 weight = off; 6151 #ifdef COMPAT_MKISOFS 6152 } else if (xdoff >= fnmax-1) { 6153 /* Simulate a bug(?) of mkisofs. */ 6154 p[fnmax-1] = '\0'; 6155 ext_off = fnmax-1; 6156 weight = fnmax-1; 6157 #endif 6158 } else { 6159 p[fnmax] = '\0'; 6160 ext_off = fnmax; 6161 weight = fnmax; 6162 } 6163 } 6164 } 6165 /* Save an offset of a file name extension to sort files. */ 6166 np->ext_off = ext_off; 6167 np->ext_len = (int)strlen(&p[ext_off]); 6168 np->id_len = l = ext_off + np->ext_len; 6169 6170 /* Make an offset of the number which is used to be set 6171 * hexadecimal number to avoid duplicate identifier. */ 6172 if (iso9660->opt.iso_level == 1) { 6173 if (ext_off >= 5) 6174 noff = 5; 6175 else 6176 noff = ext_off; 6177 } else { 6178 if (l == ffmax) 6179 noff = ext_off - 3; 6180 else if (l == ffmax-1) 6181 noff = ext_off - 2; 6182 else if (l == ffmax-2) 6183 noff = ext_off - 1; 6184 else 6185 noff = ext_off; 6186 } 6187 /* Register entry to the identifier resolver. */ 6188 idr_register(idr, np, weight, noff); 6189 } 6190 6191 /* Resolve duplicate identifier. */ 6192 idr_resolve(idr, idr_set_num); 6193 6194 /* Add a period and a version number to identifiers. */ 6195 for (np = isoent->children.first; np != NULL; np = np->chnext) { 6196 if (!np->dir && np->rr_child == NULL) { 6197 p = np->identifier + np->ext_off + np->ext_len; 6198 if (np->ext_len == 0 && allow_period) { 6199 *p++ = '.'; 6200 np->ext_len = 1; 6201 } 6202 if (np->ext_len == 1 && !allow_period) { 6203 *--p = '\0'; 6204 np->ext_len = 0; 6205 } 6206 np->id_len = np->ext_off + np->ext_len; 6207 if (allow_vernum) { 6208 *p++ = ';'; 6209 *p++ = '1'; 6210 np->id_len += 2; 6211 } 6212 *p = '\0'; 6213 } else 6214 np->id_len = np->ext_off + np->ext_len; 6215 np->mb_len = np->id_len; 6216 } 6217 return (ARCHIVE_OK); 6218 } 6219 6220 /* 6221 * Generate Joliet Identifier. 6222 */ 6223 static int 6224 isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent, 6225 struct idr *idr) 6226 { 6227 struct iso9660 *iso9660; 6228 struct isoent *np; 6229 unsigned char *p; 6230 size_t l; 6231 int r; 6232 size_t ffmax, parent_len; 6233 static const struct archive_rb_tree_ops rb_ops = { 6234 isoent_cmp_node_joliet, isoent_cmp_key_joliet 6235 }; 6236 6237 if (isoent->children.cnt == 0) 6238 return (0); 6239 6240 iso9660 = a->format_data; 6241 if (iso9660->opt.joliet == OPT_JOLIET_LONGNAME) 6242 ffmax = 206; 6243 else 6244 ffmax = 128; 6245 6246 r = idr_start(a, idr, isoent->children.cnt, (int)ffmax, 6, 2, &rb_ops); 6247 if (r < 0) 6248 return (r); 6249 6250 parent_len = 1; 6251 for (np = isoent; np->parent != np; np = np->parent) 6252 parent_len += np->mb_len + 1; 6253 6254 for (np = isoent->children.first; np != NULL; np = np->chnext) { 6255 unsigned char *dot; 6256 int ext_off, noff, weight; 6257 size_t lt; 6258 6259 if ((l = np->file->basename_utf16.length) > ffmax) 6260 l = ffmax; 6261 6262 p = malloc((l+1)*2); 6263 if (p == NULL) { 6264 archive_set_error(&a->archive, ENOMEM, 6265 "Can't allocate memory"); 6266 return (ARCHIVE_FATAL); 6267 } 6268 memcpy(p, np->file->basename_utf16.s, l); 6269 p[l] = 0; 6270 p[l+1] = 0; 6271 6272 np->identifier = (char *)p; 6273 lt = l; 6274 dot = p + l; 6275 weight = 0; 6276 while (lt > 0) { 6277 if (!joliet_allowed_char(p[0], p[1])) 6278 archive_be16enc(p, 0x005F); /* '_' */ 6279 else if (p[0] == 0 && p[1] == 0x2E) /* '.' */ 6280 dot = p; 6281 p += 2; 6282 lt -= 2; 6283 } 6284 ext_off = (int)(dot - (unsigned char *)np->identifier); 6285 np->ext_off = ext_off; 6286 np->ext_len = (int)l - ext_off; 6287 np->id_len = (int)l; 6288 6289 /* 6290 * Get a length of MBS of a full-pathname. 6291 */ 6292 if (np->file->basename_utf16.length > ffmax) { 6293 if (archive_strncpy_l(&iso9660->mbs, 6294 (const char *)np->identifier, l, 6295 iso9660->sconv_from_utf16be) != 0 && 6296 errno == ENOMEM) { 6297 archive_set_error(&a->archive, errno, 6298 "No memory"); 6299 return (ARCHIVE_FATAL); 6300 } 6301 np->mb_len = (int)iso9660->mbs.length; 6302 if (np->mb_len != (int)np->file->basename.length) 6303 weight = np->mb_len; 6304 } else 6305 np->mb_len = (int)np->file->basename.length; 6306 6307 /* If a length of full-pathname is longer than 240 bytes, 6308 * it violates Joliet extensions regulation. */ 6309 if (parent_len > 240 6310 || np->mb_len > 240 6311 || parent_len + np->mb_len > 240) { 6312 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 6313 "The regulation of Joliet extensions;" 6314 " A length of a full-pathname of `%s' is " 6315 "longer than 240 bytes, (p=%d, b=%d)", 6316 archive_entry_pathname(np->file->entry), 6317 (int)parent_len, (int)np->mb_len); 6318 return (ARCHIVE_FATAL); 6319 } 6320 6321 /* Make an offset of the number which is used to be set 6322 * hexadecimal number to avoid duplicate identifier. */ 6323 if (l == ffmax) 6324 noff = ext_off - 6; 6325 else if (l == ffmax-2) 6326 noff = ext_off - 4; 6327 else if (l == ffmax-4) 6328 noff = ext_off - 2; 6329 else 6330 noff = ext_off; 6331 /* Register entry to the identifier resolver. */ 6332 idr_register(idr, np, weight, noff); 6333 } 6334 6335 /* Resolve duplicate identifier with Joliet Volume. */ 6336 idr_resolve(idr, idr_set_num_beutf16); 6337 6338 return (ARCHIVE_OK); 6339 } 6340 6341 /* 6342 * This comparing rule is according to ISO9660 Standard 9.3 6343 */ 6344 static int 6345 isoent_cmp_iso9660_identifier(const struct isoent *p1, const struct isoent *p2) 6346 { 6347 const char *s1, *s2; 6348 int cmp; 6349 int l; 6350 6351 s1 = p1->identifier; 6352 s2 = p2->identifier; 6353 6354 /* Compare File Name */ 6355 l = p1->ext_off; 6356 if (l > p2->ext_off) 6357 l = p2->ext_off; 6358 cmp = memcmp(s1, s2, l); 6359 if (cmp != 0) 6360 return (cmp); 6361 if (p1->ext_off < p2->ext_off) { 6362 s2 += l; 6363 l = p2->ext_off - p1->ext_off; 6364 while (l--) 6365 if (0x20 != *s2++) 6366 return (0x20 6367 - *(const unsigned char *)(s2 - 1)); 6368 } else if (p1->ext_off > p2->ext_off) { 6369 s1 += l; 6370 l = p1->ext_off - p2->ext_off; 6371 while (l--) 6372 if (0x20 != *s1++) 6373 return (*(const unsigned char *)(s1 - 1) 6374 - 0x20); 6375 } 6376 /* Compare File Name Extension */ 6377 if (p1->ext_len == 0 && p2->ext_len == 0) 6378 return (0); 6379 if (p1->ext_len == 1 && p2->ext_len == 1) 6380 return (0); 6381 if (p1->ext_len <= 1) 6382 return (-1); 6383 if (p2->ext_len <= 1) 6384 return (1); 6385 l = p1->ext_len; 6386 if (l > p2->ext_len) 6387 l = p2->ext_len; 6388 s1 = p1->identifier + p1->ext_off; 6389 s2 = p2->identifier + p2->ext_off; 6390 if (l > 1) { 6391 cmp = memcmp(s1, s2, l); 6392 if (cmp != 0) 6393 return (cmp); 6394 } 6395 if (p1->ext_len < p2->ext_len) { 6396 s2 += l; 6397 l = p2->ext_len - p1->ext_len; 6398 while (l--) 6399 if (0x20 != *s2++) 6400 return (0x20 6401 - *(const unsigned char *)(s2 - 1)); 6402 } else if (p1->ext_len > p2->ext_len) { 6403 s1 += l; 6404 l = p1->ext_len - p2->ext_len; 6405 while (l--) 6406 if (0x20 != *s1++) 6407 return (*(const unsigned char *)(s1 - 1) 6408 - 0x20); 6409 } 6410 /* Compare File Version Number */ 6411 /* No operation. The File Version Number is always one. */ 6412 6413 return (cmp); 6414 } 6415 6416 static int 6417 isoent_cmp_node_iso9660(const struct archive_rb_node *n1, 6418 const struct archive_rb_node *n2) 6419 { 6420 const struct idrent *e1 = (const struct idrent *)n1; 6421 const struct idrent *e2 = (const struct idrent *)n2; 6422 6423 return (isoent_cmp_iso9660_identifier(e2->isoent, e1->isoent)); 6424 } 6425 6426 static int 6427 isoent_cmp_key_iso9660(const struct archive_rb_node *node, const void *key) 6428 { 6429 const struct isoent *isoent = (const struct isoent *)key; 6430 const struct idrent *idrent = (const struct idrent *)node; 6431 6432 return (isoent_cmp_iso9660_identifier(isoent, idrent->isoent)); 6433 } 6434 6435 static int 6436 isoent_cmp_joliet_identifier(const struct isoent *p1, const struct isoent *p2) 6437 { 6438 const unsigned char *s1, *s2; 6439 int cmp; 6440 int l; 6441 6442 s1 = (const unsigned char *)p1->identifier; 6443 s2 = (const unsigned char *)p2->identifier; 6444 6445 /* Compare File Name */ 6446 l = p1->ext_off; 6447 if (l > p2->ext_off) 6448 l = p2->ext_off; 6449 cmp = memcmp(s1, s2, l); 6450 if (cmp != 0) 6451 return (cmp); 6452 if (p1->ext_off < p2->ext_off) { 6453 s2 += l; 6454 l = p2->ext_off - p1->ext_off; 6455 while (l--) 6456 if (0 != *s2++) 6457 return (- *(const unsigned char *)(s2 - 1)); 6458 } else if (p1->ext_off > p2->ext_off) { 6459 s1 += l; 6460 l = p1->ext_off - p2->ext_off; 6461 while (l--) 6462 if (0 != *s1++) 6463 return (*(const unsigned char *)(s1 - 1)); 6464 } 6465 /* Compare File Name Extension */ 6466 if (p1->ext_len == 0 && p2->ext_len == 0) 6467 return (0); 6468 if (p1->ext_len == 2 && p2->ext_len == 2) 6469 return (0); 6470 if (p1->ext_len <= 2) 6471 return (-1); 6472 if (p2->ext_len <= 2) 6473 return (1); 6474 l = p1->ext_len; 6475 if (l > p2->ext_len) 6476 l = p2->ext_len; 6477 s1 = (unsigned char *)(p1->identifier + p1->ext_off); 6478 s2 = (unsigned char *)(p2->identifier + p2->ext_off); 6479 if (l > 1) { 6480 cmp = memcmp(s1, s2, l); 6481 if (cmp != 0) 6482 return (cmp); 6483 } 6484 if (p1->ext_len < p2->ext_len) { 6485 s2 += l; 6486 l = p2->ext_len - p1->ext_len; 6487 while (l--) 6488 if (0 != *s2++) 6489 return (- *(const unsigned char *)(s2 - 1)); 6490 } else if (p1->ext_len > p2->ext_len) { 6491 s1 += l; 6492 l = p1->ext_len - p2->ext_len; 6493 while (l--) 6494 if (0 != *s1++) 6495 return (*(const unsigned char *)(s1 - 1)); 6496 } 6497 /* Compare File Version Number */ 6498 /* No operation. The File Version Number is always one. */ 6499 6500 return (cmp); 6501 } 6502 6503 static int 6504 isoent_cmp_node_joliet(const struct archive_rb_node *n1, 6505 const struct archive_rb_node *n2) 6506 { 6507 const struct idrent *e1 = (const struct idrent *)n1; 6508 const struct idrent *e2 = (const struct idrent *)n2; 6509 6510 return (isoent_cmp_joliet_identifier(e2->isoent, e1->isoent)); 6511 } 6512 6513 static int 6514 isoent_cmp_key_joliet(const struct archive_rb_node *node, const void *key) 6515 { 6516 const struct isoent *isoent = (const struct isoent *)key; 6517 const struct idrent *idrent = (const struct idrent *)node; 6518 6519 return (isoent_cmp_joliet_identifier(isoent, idrent->isoent)); 6520 } 6521 6522 static int 6523 isoent_make_sorted_files(struct archive_write *a, struct isoent *isoent, 6524 struct idr *idr) 6525 { 6526 struct archive_rb_node *rn; 6527 struct isoent **children; 6528 6529 children = malloc(isoent->children.cnt * sizeof(struct isoent *)); 6530 if (children == NULL) { 6531 archive_set_error(&a->archive, ENOMEM, 6532 "Can't allocate memory"); 6533 return (ARCHIVE_FATAL); 6534 } 6535 isoent->children_sorted = children; 6536 6537 ARCHIVE_RB_TREE_FOREACH(rn, &(idr->rbtree)) { 6538 struct idrent *idrent = (struct idrent *)rn; 6539 *children ++ = idrent->isoent; 6540 } 6541 return (ARCHIVE_OK); 6542 } 6543 6544 /* 6545 * - Generate ISO9660 and Joliet identifiers from basenames. 6546 * - Sort files by each directory. 6547 */ 6548 static int 6549 isoent_traverse_tree(struct archive_write *a, struct vdd* vdd) 6550 { 6551 struct iso9660 *iso9660 = a->format_data; 6552 struct isoent *np; 6553 struct idr idr; 6554 int depth; 6555 int r; 6556 int (*genid)(struct archive_write *, struct isoent *, struct idr *); 6557 6558 idr_init(iso9660, vdd, &idr); 6559 np = vdd->rootent; 6560 depth = 0; 6561 if (vdd->vdd_type == VDD_JOLIET) 6562 genid = isoent_gen_joliet_identifier; 6563 else 6564 genid = isoent_gen_iso9660_identifier; 6565 do { 6566 if (np->virtual && 6567 !archive_entry_mtime_is_set(np->file->entry)) { 6568 /* Set properly times to virtual directory */ 6569 archive_entry_set_mtime(np->file->entry, 6570 iso9660->birth_time, 0); 6571 archive_entry_set_atime(np->file->entry, 6572 iso9660->birth_time, 0); 6573 archive_entry_set_ctime(np->file->entry, 6574 iso9660->birth_time, 0); 6575 } 6576 if (np->children.first != NULL) { 6577 if (vdd->vdd_type != VDD_JOLIET && 6578 !iso9660->opt.rr && depth + 1 >= vdd->max_depth) { 6579 if (np->children.cnt > 0) 6580 iso9660->directories_too_deep = np; 6581 } else { 6582 /* Generate Identifier */ 6583 r = genid(a, np, &idr); 6584 if (r < 0) 6585 goto exit_traverse_tree; 6586 r = isoent_make_sorted_files(a, np, &idr); 6587 if (r < 0) 6588 goto exit_traverse_tree; 6589 6590 if (np->subdirs.first != NULL && 6591 depth + 1 < vdd->max_depth) { 6592 /* Enter to sub directories. */ 6593 np = np->subdirs.first; 6594 depth++; 6595 continue; 6596 } 6597 } 6598 } 6599 while (np != np->parent) { 6600 if (np->drnext == NULL) { 6601 /* Return to the parent directory. */ 6602 np = np->parent; 6603 depth--; 6604 } else { 6605 np = np->drnext; 6606 break; 6607 } 6608 } 6609 } while (np != np->parent); 6610 6611 r = ARCHIVE_OK; 6612 exit_traverse_tree: 6613 idr_cleanup(&idr); 6614 6615 return (r); 6616 } 6617 6618 /* 6619 * Collect directory entries into path_table by a directory depth. 6620 */ 6621 static int 6622 isoent_collect_dirs(struct vdd *vdd, struct isoent *rootent, int depth) 6623 { 6624 struct isoent *np; 6625 6626 if (rootent == NULL) 6627 rootent = vdd->rootent; 6628 np = rootent; 6629 do { 6630 /* Register current directory to pathtable. */ 6631 path_table_add_entry(&(vdd->pathtbl[depth]), np); 6632 6633 if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) { 6634 /* Enter to sub directories. */ 6635 np = np->subdirs.first; 6636 depth++; 6637 continue; 6638 } 6639 while (np != rootent) { 6640 if (np->drnext == NULL) { 6641 /* Return to the parent directory. */ 6642 np = np->parent; 6643 depth--; 6644 } else { 6645 np = np->drnext; 6646 break; 6647 } 6648 } 6649 } while (np != rootent); 6650 6651 return (ARCHIVE_OK); 6652 } 6653 6654 /* 6655 * The entry whose number of levels in a directory hierarchy is 6656 * large than eight relocate to rr_move directory. 6657 */ 6658 static int 6659 isoent_rr_move_dir(struct archive_write *a, struct isoent **rr_moved, 6660 struct isoent *curent, struct isoent **newent) 6661 { 6662 struct iso9660 *iso9660 = a->format_data; 6663 struct isoent *rrmoved, *mvent, *np; 6664 6665 if ((rrmoved = *rr_moved) == NULL) { 6666 struct isoent *rootent = iso9660->primary.rootent; 6667 /* There isn't rr_move entry. 6668 * Create rr_move entry and insert it into the root entry. 6669 */ 6670 rrmoved = isoent_create_virtual_dir(a, iso9660, "rr_moved"); 6671 if (rrmoved == NULL) { 6672 archive_set_error(&a->archive, ENOMEM, 6673 "Can't allocate memory"); 6674 return (ARCHIVE_FATAL); 6675 } 6676 /* Add "rr_moved" entry to the root entry. */ 6677 isoent_add_child_head(rootent, rrmoved); 6678 archive_entry_set_nlink(rootent->file->entry, 6679 archive_entry_nlink(rootent->file->entry) + 1); 6680 /* Register "rr_moved" entry to second level pathtable. */ 6681 path_table_add_entry(&(iso9660->primary.pathtbl[1]), rrmoved); 6682 /* Save rr_moved. */ 6683 *rr_moved = rrmoved; 6684 } 6685 /* 6686 * Make a clone of curent which is going to be relocated 6687 * to rr_moved. 6688 */ 6689 mvent = isoent_clone(curent); 6690 if (mvent == NULL) { 6691 archive_set_error(&a->archive, ENOMEM, 6692 "Can't allocate memory"); 6693 return (ARCHIVE_FATAL); 6694 } 6695 /* linking.. and use for creating "CL", "PL" and "RE" */ 6696 mvent->rr_parent = curent->parent; 6697 curent->rr_child = mvent; 6698 /* 6699 * Move subdirectories from the curent to mvent 6700 */ 6701 if (curent->children.first != NULL) { 6702 *mvent->children.last = curent->children.first; 6703 mvent->children.last = curent->children.last; 6704 } 6705 for (np = mvent->children.first; np != NULL; np = np->chnext) 6706 np->parent = mvent; 6707 mvent->children.cnt = curent->children.cnt; 6708 curent->children.cnt = 0; 6709 curent->children.first = NULL; 6710 curent->children.last = &curent->children.first; 6711 6712 if (curent->subdirs.first != NULL) { 6713 *mvent->subdirs.last = curent->subdirs.first; 6714 mvent->subdirs.last = curent->subdirs.last; 6715 } 6716 mvent->subdirs.cnt = curent->subdirs.cnt; 6717 curent->subdirs.cnt = 0; 6718 curent->subdirs.first = NULL; 6719 curent->subdirs.last = &curent->subdirs.first; 6720 6721 /* 6722 * The mvent becomes a child of the rr_moved entry. 6723 */ 6724 isoent_add_child_tail(rrmoved, mvent); 6725 archive_entry_set_nlink(rrmoved->file->entry, 6726 archive_entry_nlink(rrmoved->file->entry) + 1); 6727 /* 6728 * This entry which relocated to the rr_moved directory 6729 * has to set the flag as a file. 6730 * See also RRIP 4.1.5.1 Description of the "CL" System Use Entry. 6731 */ 6732 curent->dir = 0; 6733 6734 *newent = mvent; 6735 6736 return (ARCHIVE_OK); 6737 } 6738 6739 static int 6740 isoent_rr_move(struct archive_write *a) 6741 { 6742 struct iso9660 *iso9660 = a->format_data; 6743 struct path_table *pt; 6744 struct isoent *rootent, *rr_moved; 6745 struct isoent *np, *last; 6746 int r; 6747 6748 pt = &(iso9660->primary.pathtbl[MAX_DEPTH-1]); 6749 /* There aren't level 8 directories reaching a deeper level. */ 6750 if (pt->cnt == 0) 6751 return (ARCHIVE_OK); 6752 6753 rootent = iso9660->primary.rootent; 6754 /* If "rr_moved" directory is already existing, 6755 * we have to use it. */ 6756 rr_moved = isoent_find_child(rootent, "rr_moved"); 6757 if (rr_moved != NULL && 6758 rr_moved != rootent->children.first) { 6759 /* 6760 * It's necessary that rr_move is the first entry 6761 * of the root. 6762 */ 6763 /* Remove "rr_moved" entry from children chain. */ 6764 isoent_remove_child(rootent, rr_moved); 6765 6766 /* Add "rr_moved" entry into the head of children chain. */ 6767 isoent_add_child_head(rootent, rr_moved); 6768 } 6769 6770 /* 6771 * Check level 8 path_table. 6772 * If find out sub directory entries, that entries move to rr_move. 6773 */ 6774 np = pt->first; 6775 while (np != NULL) { 6776 last = path_table_last_entry(pt); 6777 for (; np != NULL; np = np->ptnext) { 6778 struct isoent *mvent; 6779 struct isoent *newent; 6780 6781 if (!np->dir) 6782 continue; 6783 for (mvent = np->subdirs.first; 6784 mvent != NULL; mvent = mvent->drnext) { 6785 r = isoent_rr_move_dir(a, &rr_moved, 6786 mvent, &newent); 6787 if (r < 0) 6788 return (r); 6789 isoent_collect_dirs(&(iso9660->primary), 6790 newent, 2); 6791 } 6792 } 6793 /* If new entries are added to level 8 path_talbe, 6794 * its sub directory entries move to rr_move too. 6795 */ 6796 np = last->ptnext; 6797 } 6798 6799 return (ARCHIVE_OK); 6800 } 6801 6802 /* 6803 * This comparing rule is according to ISO9660 Standard 6.9.1 6804 */ 6805 static int 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 _compare_path_table_joliet(const void *v1, const void *v2) 6849 { 6850 const struct isoent *p1, *p2; 6851 const unsigned char *s1, *s2; 6852 int cmp, l; 6853 6854 p1 = *((const struct isoent **)(uintptr_t)v1); 6855 p2 = *((const struct isoent **)(uintptr_t)v2); 6856 6857 /* Compare parent directory number */ 6858 cmp = p1->parent->dir_number - p2->parent->dir_number; 6859 if (cmp != 0) 6860 return (cmp); 6861 6862 /* Compare identifier */ 6863 s1 = (const unsigned char *)p1->identifier; 6864 s2 = (const unsigned char *)p2->identifier; 6865 l = p1->ext_off; 6866 if (l > p2->ext_off) 6867 l = p2->ext_off; 6868 cmp = memcmp(s1, s2, l); 6869 if (cmp != 0) 6870 return (cmp); 6871 if (p1->ext_off < p2->ext_off) { 6872 s2 += l; 6873 l = p2->ext_off - p1->ext_off; 6874 while (l--) 6875 if (0 != *s2++) 6876 return (- *(const unsigned char *)(s2 - 1)); 6877 } else if (p1->ext_off > p2->ext_off) { 6878 s1 += l; 6879 l = p1->ext_off - p2->ext_off; 6880 while (l--) 6881 if (0 != *s1++) 6882 return (*(const unsigned char *)(s1 - 1)); 6883 } 6884 return (0); 6885 } 6886 6887 static inline void 6888 path_table_add_entry(struct path_table *pathtbl, struct isoent *ent) 6889 { 6890 ent->ptnext = NULL; 6891 *pathtbl->last = ent; 6892 pathtbl->last = &(ent->ptnext); 6893 pathtbl->cnt ++; 6894 } 6895 6896 static inline struct isoent * 6897 path_table_last_entry(struct path_table *pathtbl) 6898 { 6899 if (pathtbl->first == NULL) 6900 return (NULL); 6901 return (((struct isoent *)(void *) 6902 ((char *)(pathtbl->last) - offsetof(struct isoent, ptnext)))); 6903 } 6904 6905 /* 6906 * Sort directory entries in path_table 6907 * and assign directory number to each entries. 6908 */ 6909 static int 6910 isoent_make_path_table_2(struct archive_write *a, struct vdd *vdd, 6911 int depth, int *dir_number) 6912 { 6913 struct isoent *np; 6914 struct isoent **enttbl; 6915 struct path_table *pt; 6916 int i; 6917 6918 pt = &vdd->pathtbl[depth]; 6919 if (pt->cnt == 0) { 6920 pt->sorted = NULL; 6921 return (ARCHIVE_OK); 6922 } 6923 enttbl = malloc(pt->cnt * sizeof(struct isoent *)); 6924 if (enttbl == NULL) { 6925 archive_set_error(&a->archive, ENOMEM, 6926 "Can't allocate memory"); 6927 return (ARCHIVE_FATAL); 6928 } 6929 pt->sorted = enttbl; 6930 for (np = pt->first; np != NULL; np = np->ptnext) 6931 *enttbl ++ = np; 6932 enttbl = pt->sorted; 6933 6934 switch (vdd->vdd_type) { 6935 case VDD_PRIMARY: 6936 case VDD_ENHANCED: 6937 #ifdef __COMPAR_FN_T 6938 qsort(enttbl, pt->cnt, sizeof(struct isoent *), 6939 (__compar_fn_t)_compare_path_table); 6940 #else 6941 qsort(enttbl, pt->cnt, sizeof(struct isoent *), 6942 _compare_path_table); 6943 #endif 6944 break; 6945 case VDD_JOLIET: 6946 #ifdef __COMPAR_FN_T 6947 qsort(enttbl, pt->cnt, sizeof(struct isoent *), 6948 (__compar_fn_t)_compare_path_table_joliet); 6949 #else 6950 qsort(enttbl, pt->cnt, sizeof(struct isoent *), 6951 _compare_path_table_joliet); 6952 #endif 6953 break; 6954 } 6955 for (i = 0; i < pt->cnt; i++) 6956 enttbl[i]->dir_number = (*dir_number)++; 6957 6958 return (ARCHIVE_OK); 6959 } 6960 6961 static int 6962 isoent_alloc_path_table(struct archive_write *a, struct vdd *vdd, 6963 int max_depth) 6964 { 6965 int i; 6966 6967 vdd->max_depth = max_depth; 6968 vdd->pathtbl = malloc(sizeof(*vdd->pathtbl) * vdd->max_depth); 6969 if (vdd->pathtbl == NULL) { 6970 archive_set_error(&a->archive, ENOMEM, 6971 "Can't allocate memory"); 6972 return (ARCHIVE_FATAL); 6973 } 6974 for (i = 0; i < vdd->max_depth; i++) { 6975 vdd->pathtbl[i].first = NULL; 6976 vdd->pathtbl[i].last = &(vdd->pathtbl[i].first); 6977 vdd->pathtbl[i].sorted = NULL; 6978 vdd->pathtbl[i].cnt = 0; 6979 } 6980 return (ARCHIVE_OK); 6981 } 6982 6983 /* 6984 * Make Path Tables 6985 */ 6986 static int 6987 isoent_make_path_table(struct archive_write *a) 6988 { 6989 struct iso9660 *iso9660 = a->format_data; 6990 int depth, r; 6991 int dir_number; 6992 6993 /* 6994 * Init Path Table. 6995 */ 6996 if (iso9660->dircnt_max >= MAX_DEPTH && 6997 (!iso9660->opt.limit_depth || iso9660->opt.iso_level == 4)) 6998 r = isoent_alloc_path_table(a, &(iso9660->primary), 6999 iso9660->dircnt_max + 1); 7000 else 7001 /* The number of levels in the hierarchy cannot exceed 7002 * eight. */ 7003 r = isoent_alloc_path_table(a, &(iso9660->primary), 7004 MAX_DEPTH); 7005 if (r < 0) 7006 return (r); 7007 if (iso9660->opt.joliet) { 7008 r = isoent_alloc_path_table(a, &(iso9660->joliet), 7009 iso9660->dircnt_max + 1); 7010 if (r < 0) 7011 return (r); 7012 } 7013 7014 /* Step 0. 7015 * - Collect directories for primary and joliet. 7016 */ 7017 isoent_collect_dirs(&(iso9660->primary), NULL, 0); 7018 if (iso9660->opt.joliet) 7019 isoent_collect_dirs(&(iso9660->joliet), NULL, 0); 7020 /* 7021 * Rockridge; move deeper depth directories to rr_moved. 7022 */ 7023 if (iso9660->opt.rr) { 7024 r = isoent_rr_move(a); 7025 if (r < 0) 7026 return (r); 7027 } 7028 7029 /* Update nlink. */ 7030 isofile_connect_hardlink_files(iso9660); 7031 7032 /* Step 1. 7033 * - Renew a value of the depth of that directories. 7034 * - Resolve hardlinks. 7035 * - Convert pathnames to ISO9660 name or UCS2(joliet). 7036 * - Sort files by each directory. 7037 */ 7038 r = isoent_traverse_tree(a, &(iso9660->primary)); 7039 if (r < 0) 7040 return (r); 7041 if (iso9660->opt.joliet) { 7042 r = isoent_traverse_tree(a, &(iso9660->joliet)); 7043 if (r < 0) 7044 return (r); 7045 } 7046 7047 /* Step 2. 7048 * - Sort directories. 7049 * - Assign all directory number. 7050 */ 7051 dir_number = 1; 7052 for (depth = 0; depth < iso9660->primary.max_depth; depth++) { 7053 r = isoent_make_path_table_2(a, &(iso9660->primary), 7054 depth, &dir_number); 7055 if (r < 0) 7056 return (r); 7057 } 7058 if (iso9660->opt.joliet) { 7059 dir_number = 1; 7060 for (depth = 0; depth < iso9660->joliet.max_depth; depth++) { 7061 r = isoent_make_path_table_2(a, &(iso9660->joliet), 7062 depth, &dir_number); 7063 if (r < 0) 7064 return (r); 7065 } 7066 } 7067 if (iso9660->opt.limit_dirs && dir_number > 0xffff) { 7068 /* 7069 * Maximum number of directories is 65535(0xffff) 7070 * doe to size(16bit) of Parent Directory Number of 7071 * the Path Table. 7072 * See also ISO9660 Standard 9.4. 7073 */ 7074 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 7075 "Too many directories(%d) over 65535.", dir_number); 7076 return (ARCHIVE_FATAL); 7077 } 7078 7079 /* Get the size of the Path Table. */ 7080 calculate_path_table_size(&(iso9660->primary)); 7081 if (iso9660->opt.joliet) 7082 calculate_path_table_size(&(iso9660->joliet)); 7083 7084 return (ARCHIVE_OK); 7085 } 7086 7087 static int 7088 isoent_find_out_boot_file(struct archive_write *a, struct isoent *rootent) 7089 { 7090 struct iso9660 *iso9660 = a->format_data; 7091 7092 /* Find a isoent of the boot file. */ 7093 iso9660->el_torito.boot = isoent_find_entry(rootent, 7094 iso9660->el_torito.boot_filename.s); 7095 if (iso9660->el_torito.boot == NULL) { 7096 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 7097 "Can't find the boot image file ``%s''", 7098 iso9660->el_torito.boot_filename.s); 7099 return (ARCHIVE_FATAL); 7100 } 7101 iso9660->el_torito.boot->file->boot = BOOT_IMAGE; 7102 return (ARCHIVE_OK); 7103 } 7104 7105 static int 7106 isoent_create_boot_catalog(struct archive_write *a, struct isoent *rootent) 7107 { 7108 struct iso9660 *iso9660 = a->format_data; 7109 struct isofile *file; 7110 struct isoent *isoent; 7111 struct archive_entry *entry; 7112 7113 (void)rootent; /* UNUSED */ 7114 /* 7115 * Create the entry which is the "boot.catalog" file. 7116 */ 7117 file = isofile_new(a, NULL); 7118 if (file == NULL) { 7119 archive_set_error(&a->archive, ENOMEM, 7120 "Can't allocate memory"); 7121 return (ARCHIVE_FATAL); 7122 } 7123 archive_entry_set_pathname(file->entry, 7124 iso9660->el_torito.catalog_filename.s); 7125 archive_entry_set_size(file->entry, LOGICAL_BLOCK_SIZE); 7126 archive_entry_set_mtime(file->entry, iso9660->birth_time, 0); 7127 archive_entry_set_atime(file->entry, iso9660->birth_time, 0); 7128 archive_entry_set_ctime(file->entry, iso9660->birth_time, 0); 7129 archive_entry_set_uid(file->entry, getuid()); 7130 archive_entry_set_gid(file->entry, getgid()); 7131 archive_entry_set_mode(file->entry, AE_IFREG | 0444); 7132 archive_entry_set_nlink(file->entry, 1); 7133 7134 if (isofile_gen_utility_names(a, file) < ARCHIVE_WARN) { 7135 isofile_free(file); 7136 return (ARCHIVE_FATAL); 7137 } 7138 file->boot = BOOT_CATALOG; 7139 file->content.size = LOGICAL_BLOCK_SIZE; 7140 isofile_add_entry(iso9660, file); 7141 7142 isoent = isoent_new(file); 7143 if (isoent == NULL) { 7144 archive_set_error(&a->archive, ENOMEM, 7145 "Can't allocate memory"); 7146 return (ARCHIVE_FATAL); 7147 } 7148 isoent->virtual = 1; 7149 7150 /* Add the "boot.catalog" entry into tree */ 7151 if (isoent_tree(a, &isoent) != ARCHIVE_OK) 7152 return (ARCHIVE_FATAL); 7153 7154 iso9660->el_torito.catalog = isoent; 7155 /* 7156 * Get a boot media type. 7157 */ 7158 switch (iso9660->opt.boot_type) { 7159 default: 7160 case OPT_BOOT_TYPE_AUTO: 7161 /* Try detecting a media type of the boot image. */ 7162 entry = iso9660->el_torito.boot->file->entry; 7163 if (archive_entry_size(entry) == FD_1_2M_SIZE) 7164 iso9660->el_torito.media_type = 7165 BOOT_MEDIA_1_2M_DISKETTE; 7166 else if (archive_entry_size(entry) == FD_1_44M_SIZE) 7167 iso9660->el_torito.media_type = 7168 BOOT_MEDIA_1_44M_DISKETTE; 7169 else if (archive_entry_size(entry) == FD_2_88M_SIZE) 7170 iso9660->el_torito.media_type = 7171 BOOT_MEDIA_2_88M_DISKETTE; 7172 else 7173 /* We cannot decide whether the boot image is 7174 * hard-disk. */ 7175 iso9660->el_torito.media_type = 7176 BOOT_MEDIA_NO_EMULATION; 7177 break; 7178 case OPT_BOOT_TYPE_NO_EMU: 7179 iso9660->el_torito.media_type = BOOT_MEDIA_NO_EMULATION; 7180 break; 7181 case OPT_BOOT_TYPE_HARD_DISK: 7182 iso9660->el_torito.media_type = BOOT_MEDIA_HARD_DISK; 7183 break; 7184 case OPT_BOOT_TYPE_FD: 7185 entry = iso9660->el_torito.boot->file->entry; 7186 if (archive_entry_size(entry) <= FD_1_2M_SIZE) 7187 iso9660->el_torito.media_type = 7188 BOOT_MEDIA_1_2M_DISKETTE; 7189 else if (archive_entry_size(entry) <= FD_1_44M_SIZE) 7190 iso9660->el_torito.media_type = 7191 BOOT_MEDIA_1_44M_DISKETTE; 7192 else if (archive_entry_size(entry) <= FD_2_88M_SIZE) 7193 iso9660->el_torito.media_type = 7194 BOOT_MEDIA_2_88M_DISKETTE; 7195 else { 7196 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 7197 "Boot image file(``%s'') size is too big " 7198 "for fd type.", 7199 iso9660->el_torito.boot_filename.s); 7200 return (ARCHIVE_FATAL); 7201 } 7202 break; 7203 } 7204 7205 /* 7206 * Get a system type. 7207 * TODO: `El Torito' specification says "A copy of byte 5 from the 7208 * Partition Table found in the boot image". 7209 */ 7210 iso9660->el_torito.system_type = 0; 7211 7212 /* 7213 * Get an ID. 7214 */ 7215 if (iso9660->opt.publisher) 7216 archive_string_copy(&(iso9660->el_torito.id), 7217 &(iso9660->publisher_identifier)); 7218 7219 7220 return (ARCHIVE_OK); 7221 } 7222 7223 /* 7224 * If a media type is floppy, return its image size. 7225 * otherwise return 0. 7226 */ 7227 static size_t 7228 fd_boot_image_size(int media_type) 7229 { 7230 switch (media_type) { 7231 case BOOT_MEDIA_1_2M_DISKETTE: 7232 return (FD_1_2M_SIZE); 7233 case BOOT_MEDIA_1_44M_DISKETTE: 7234 return (FD_1_44M_SIZE); 7235 case BOOT_MEDIA_2_88M_DISKETTE: 7236 return (FD_2_88M_SIZE); 7237 default: 7238 return (0); 7239 } 7240 } 7241 7242 /* 7243 * Make a boot catalog image data. 7244 */ 7245 static int 7246 make_boot_catalog(struct archive_write *a) 7247 { 7248 struct iso9660 *iso9660 = a->format_data; 7249 unsigned char *block; 7250 unsigned char *p; 7251 uint16_t sum, *wp; 7252 7253 block = wb_buffptr(a); 7254 memset(block, 0, LOGICAL_BLOCK_SIZE); 7255 p = block; 7256 /* 7257 * Validation Entry 7258 */ 7259 /* Header ID */ 7260 p[0] = 1; 7261 /* Platform ID */ 7262 p[1] = iso9660->el_torito.platform_id; 7263 /* Reserved */ 7264 p[2] = p[3] = 0; 7265 /* ID */ 7266 if (archive_strlen(&(iso9660->el_torito.id)) > 0) 7267 strncpy((char *)p+4, iso9660->el_torito.id.s, 23); 7268 p[27] = 0; 7269 /* Checksum */ 7270 p[28] = p[29] = 0; 7271 /* Key */ 7272 p[30] = 0x55; 7273 p[31] = 0xAA; 7274 7275 sum = 0; 7276 wp = (uint16_t *)block; 7277 while (wp < (uint16_t *)&block[32]) 7278 sum += archive_le16dec(wp++); 7279 set_num_721(&block[28], (~sum) + 1); 7280 7281 /* 7282 * Initial/Default Entry 7283 */ 7284 p = &block[32]; 7285 /* Boot Indicator */ 7286 p[0] = 0x88; 7287 /* Boot media type */ 7288 p[1] = iso9660->el_torito.media_type; 7289 /* Load Segment */ 7290 if (iso9660->el_torito.media_type == BOOT_MEDIA_NO_EMULATION) 7291 set_num_721(&p[2], iso9660->el_torito.boot_load_seg); 7292 else 7293 set_num_721(&p[2], 0); 7294 /* System Type */ 7295 p[4] = iso9660->el_torito.system_type; 7296 /* Unused */ 7297 p[5] = 0; 7298 /* Sector Count */ 7299 if (iso9660->el_torito.media_type == BOOT_MEDIA_NO_EMULATION) 7300 set_num_721(&p[6], iso9660->el_torito.boot_load_size); 7301 else 7302 set_num_721(&p[6], 1); 7303 /* Load RBA */ 7304 set_num_731(&p[8], 7305 iso9660->el_torito.boot->file->content.location); 7306 /* Unused */ 7307 memset(&p[12], 0, 20); 7308 7309 return (wb_consume(a, LOGICAL_BLOCK_SIZE)); 7310 } 7311 7312 static int 7313 setup_boot_information(struct archive_write *a) 7314 { 7315 struct iso9660 *iso9660 = a->format_data; 7316 struct isoent *np; 7317 int64_t size; 7318 uint32_t sum; 7319 unsigned char buff[4096]; 7320 7321 np = iso9660->el_torito.boot; 7322 lseek(iso9660->temp_fd, 7323 np->file->content.offset_of_temp + 64, SEEK_SET); 7324 size = archive_entry_size(np->file->entry) - 64; 7325 if (size <= 0) { 7326 archive_set_error(&a->archive, errno, 7327 "Boot file(%jd) is too small", (intmax_t)size + 64); 7328 return (ARCHIVE_FATAL); 7329 } 7330 sum = 0; 7331 while (size > 0) { 7332 size_t rsize; 7333 ssize_t i, rs; 7334 7335 if (size > (int64_t)sizeof(buff)) 7336 rsize = sizeof(buff); 7337 else 7338 rsize = (size_t)size; 7339 7340 rs = read(iso9660->temp_fd, buff, rsize); 7341 if (rs <= 0) { 7342 archive_set_error(&a->archive, errno, 7343 "Can't read temporary file(%jd)", 7344 (intmax_t)rs); 7345 return (ARCHIVE_FATAL); 7346 } 7347 for (i = 0; i < rs; i += 4) 7348 sum += archive_le32dec(buff + i); 7349 size -= rs; 7350 } 7351 /* Set the location of Primary Volume Descriptor. */ 7352 set_num_731(buff, SYSTEM_AREA_BLOCK); 7353 /* Set the location of the boot file. */ 7354 set_num_731(buff+4, np->file->content.location); 7355 /* Set the size of the boot file. */ 7356 size = fd_boot_image_size(iso9660->el_torito.media_type); 7357 if (size == 0) 7358 size = archive_entry_size(np->file->entry); 7359 set_num_731(buff+8, (uint32_t)size); 7360 /* Set the sum of the boot file. */ 7361 set_num_731(buff+12, sum); 7362 /* Clear reserved bytes. */ 7363 memset(buff+16, 0, 40); 7364 7365 /* Overwrite the boot file. */ 7366 lseek(iso9660->temp_fd, 7367 np->file->content.offset_of_temp + 8, SEEK_SET); 7368 return (write_to_temp(a, buff, 56)); 7369 } 7370 7371 #ifdef HAVE_ZLIB_H 7372 7373 static int 7374 zisofs_init_zstream(struct archive_write *a) 7375 { 7376 struct iso9660 *iso9660 = a->format_data; 7377 int r; 7378 7379 iso9660->zisofs.stream.next_in = NULL; 7380 iso9660->zisofs.stream.avail_in = 0; 7381 iso9660->zisofs.stream.total_in = 0; 7382 iso9660->zisofs.stream.total_out = 0; 7383 if (iso9660->zisofs.stream_valid) 7384 r = deflateReset(&(iso9660->zisofs.stream)); 7385 else { 7386 r = deflateInit(&(iso9660->zisofs.stream), 7387 iso9660->zisofs.compression_level); 7388 iso9660->zisofs.stream_valid = 1; 7389 } 7390 switch (r) { 7391 case Z_OK: 7392 break; 7393 default: 7394 case Z_STREAM_ERROR: 7395 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 7396 "Internal error initializing " 7397 "compression library: invalid setup parameter"); 7398 return (ARCHIVE_FATAL); 7399 case Z_MEM_ERROR: 7400 archive_set_error(&a->archive, ENOMEM, 7401 "Internal error initializing " 7402 "compression library"); 7403 return (ARCHIVE_FATAL); 7404 case Z_VERSION_ERROR: 7405 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 7406 "Internal error initializing " 7407 "compression library: invalid library version"); 7408 return (ARCHIVE_FATAL); 7409 } 7410 return (ARCHIVE_OK); 7411 } 7412 7413 #endif /* HAVE_ZLIB_H */ 7414 7415 static int 7416 zisofs_init(struct archive_write *a, struct isofile *file) 7417 { 7418 struct iso9660 *iso9660 = a->format_data; 7419 #ifdef HAVE_ZLIB_H 7420 uint64_t tsize; 7421 size_t _ceil, bpsize; 7422 int r; 7423 #endif 7424 7425 iso9660->zisofs.detect_magic = 0; 7426 iso9660->zisofs.making = 0; 7427 7428 if (!iso9660->opt.rr || !iso9660->opt.zisofs) 7429 return (ARCHIVE_OK); 7430 7431 if (archive_entry_size(file->entry) >= 24 && 7432 archive_entry_size(file->entry) < MULTI_EXTENT_SIZE) { 7433 /* Acceptable file size for zisofs. */ 7434 iso9660->zisofs.detect_magic = 1; 7435 iso9660->zisofs.magic_cnt = 0; 7436 } 7437 if (!iso9660->zisofs.detect_magic) 7438 return (ARCHIVE_OK); 7439 7440 #ifdef HAVE_ZLIB_H 7441 /* The number of Logical Blocks which uncompressed data 7442 * will use in iso-image file is the same as the number of 7443 * Logical Blocks which zisofs(compressed) data will use 7444 * in ISO-image file. It won't reduce iso-image file size. */ 7445 if (archive_entry_size(file->entry) <= LOGICAL_BLOCK_SIZE) 7446 return (ARCHIVE_OK); 7447 7448 /* Initialize compression library */ 7449 r = zisofs_init_zstream(a); 7450 if (r != ARCHIVE_OK) 7451 return (ARCHIVE_FATAL); 7452 7453 /* Mark file->zisofs to create RRIP 'ZF' Use Entry. */ 7454 file->zisofs.header_size = ZF_HEADER_SIZE >> 2; 7455 file->zisofs.log2_bs = ZF_LOG2_BS; 7456 file->zisofs.uncompressed_size = 7457 (uint32_t)archive_entry_size(file->entry); 7458 7459 /* Calculate a size of Block Pointers of zisofs. */ 7460 _ceil = (file->zisofs.uncompressed_size + ZF_BLOCK_SIZE -1) 7461 >> file->zisofs.log2_bs; 7462 iso9660->zisofs.block_pointers_cnt = (int)_ceil + 1; 7463 iso9660->zisofs.block_pointers_idx = 0; 7464 7465 /* Ensure a buffer size used for Block Pointers */ 7466 bpsize = iso9660->zisofs.block_pointers_cnt * 7467 sizeof(iso9660->zisofs.block_pointers[0]); 7468 if (iso9660->zisofs.block_pointers_allocated < bpsize) { 7469 free(iso9660->zisofs.block_pointers); 7470 iso9660->zisofs.block_pointers = malloc(bpsize); 7471 if (iso9660->zisofs.block_pointers == NULL) { 7472 archive_set_error(&a->archive, ENOMEM, 7473 "Can't allocate data"); 7474 return (ARCHIVE_FATAL); 7475 } 7476 iso9660->zisofs.block_pointers_allocated = bpsize; 7477 } 7478 7479 /* 7480 * Skip zisofs header and Block Pointers, which we will write 7481 * after all compressed data of a file written to the temporary 7482 * file. 7483 */ 7484 tsize = ZF_HEADER_SIZE + bpsize; 7485 if (write_null(a, (size_t)tsize) != ARCHIVE_OK) 7486 return (ARCHIVE_FATAL); 7487 7488 /* 7489 * Initialize some variables to make zisofs. 7490 */ 7491 archive_le32enc(&(iso9660->zisofs.block_pointers[0]), 7492 (uint32_t)tsize); 7493 iso9660->zisofs.remaining = file->zisofs.uncompressed_size; 7494 iso9660->zisofs.making = 1; 7495 iso9660->zisofs.allzero = 1; 7496 iso9660->zisofs.block_offset = tsize; 7497 iso9660->zisofs.total_size = tsize; 7498 iso9660->cur_file->cur_content->size = tsize; 7499 #endif 7500 7501 return (ARCHIVE_OK); 7502 } 7503 7504 static void 7505 zisofs_detect_magic(struct archive_write *a, const void *buff, size_t s) 7506 { 7507 struct iso9660 *iso9660 = a->format_data; 7508 struct isofile *file = iso9660->cur_file; 7509 const unsigned char *p, *endp; 7510 const unsigned char *magic_buff; 7511 uint32_t uncompressed_size; 7512 unsigned char header_size; 7513 unsigned char log2_bs; 7514 size_t _ceil, doff; 7515 uint32_t bst, bed; 7516 int magic_max; 7517 int64_t entry_size; 7518 7519 entry_size = archive_entry_size(file->entry); 7520 if ((int64_t)sizeof(iso9660->zisofs.magic_buffer) > entry_size) 7521 magic_max = (int)entry_size; 7522 else 7523 magic_max = sizeof(iso9660->zisofs.magic_buffer); 7524 7525 if (iso9660->zisofs.magic_cnt == 0 && s >= (size_t)magic_max) 7526 /* It's unnecessary we copy buffer. */ 7527 magic_buff = buff; 7528 else { 7529 if (iso9660->zisofs.magic_cnt < magic_max) { 7530 size_t l; 7531 7532 l = sizeof(iso9660->zisofs.magic_buffer) 7533 - iso9660->zisofs.magic_cnt; 7534 if (l > s) 7535 l = s; 7536 memcpy(iso9660->zisofs.magic_buffer 7537 + iso9660->zisofs.magic_cnt, buff, l); 7538 iso9660->zisofs.magic_cnt += (int)l; 7539 if (iso9660->zisofs.magic_cnt < magic_max) 7540 return; 7541 } 7542 magic_buff = iso9660->zisofs.magic_buffer; 7543 } 7544 iso9660->zisofs.detect_magic = 0; 7545 p = magic_buff; 7546 7547 /* Check the magic code of zisofs. */ 7548 if (memcmp(p, zisofs_magic, sizeof(zisofs_magic)) != 0) 7549 /* This is not zisofs file which made by mkzftree. */ 7550 return; 7551 p += sizeof(zisofs_magic); 7552 7553 /* Read a zisofs header. */ 7554 uncompressed_size = archive_le32dec(p); 7555 header_size = p[4]; 7556 log2_bs = p[5]; 7557 if (uncompressed_size < 24 || header_size != 4 || 7558 log2_bs > 30 || log2_bs < 7) 7559 return;/* Invalid or not supported header. */ 7560 7561 /* Calculate a size of Block Pointers of zisofs. */ 7562 _ceil = (uncompressed_size + 7563 (ARCHIVE_LITERAL_LL(1) << log2_bs) -1) >> log2_bs; 7564 doff = (_ceil + 1) * 4 + 16; 7565 if (entry_size < (int64_t)doff) 7566 return;/* Invalid data. */ 7567 7568 /* Check every Block Pointer has valid value. */ 7569 p = magic_buff + 16; 7570 endp = magic_buff + magic_max; 7571 while (_ceil && p + 8 <= endp) { 7572 bst = archive_le32dec(p); 7573 if (bst != doff) 7574 return;/* Invalid data. */ 7575 p += 4; 7576 bed = archive_le32dec(p); 7577 if (bed < bst || bed > entry_size) 7578 return;/* Invalid data. */ 7579 doff += bed - bst; 7580 _ceil--; 7581 } 7582 7583 file->zisofs.uncompressed_size = uncompressed_size; 7584 file->zisofs.header_size = header_size; 7585 file->zisofs.log2_bs = log2_bs; 7586 7587 /* Disable making a zisofs image. */ 7588 iso9660->zisofs.making = 0; 7589 } 7590 7591 #ifdef HAVE_ZLIB_H 7592 7593 /* 7594 * Compress data and write it to a temporary file. 7595 */ 7596 static int 7597 zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s) 7598 { 7599 struct iso9660 *iso9660 = a->format_data; 7600 struct isofile *file = iso9660->cur_file; 7601 const unsigned char *b; 7602 z_stream *zstrm; 7603 size_t avail, csize; 7604 int flush, r; 7605 7606 zstrm = &(iso9660->zisofs.stream); 7607 zstrm->next_out = wb_buffptr(a); 7608 zstrm->avail_out = (uInt)wb_remaining(a); 7609 b = (const unsigned char *)buff; 7610 do { 7611 avail = ZF_BLOCK_SIZE - zstrm->total_in; 7612 if (s < avail) { 7613 avail = s; 7614 flush = Z_NO_FLUSH; 7615 } else 7616 flush = Z_FINISH; 7617 iso9660->zisofs.remaining -= avail; 7618 if (iso9660->zisofs.remaining <= 0) 7619 flush = Z_FINISH; 7620 7621 zstrm->next_in = (Bytef *)(uintptr_t)(const void *)b; 7622 zstrm->avail_in = (uInt)avail; 7623 7624 /* 7625 * Check if current data block are all zero. 7626 */ 7627 if (iso9660->zisofs.allzero) { 7628 const unsigned char *nonzero = b; 7629 const unsigned char *nonzeroend = b + avail; 7630 7631 while (nonzero < nonzeroend) 7632 if (*nonzero++) { 7633 iso9660->zisofs.allzero = 0; 7634 break; 7635 } 7636 } 7637 b += avail; 7638 s -= avail; 7639 7640 /* 7641 * If current data block are all zero, we do not use 7642 * compressed data. 7643 */ 7644 if (flush == Z_FINISH && iso9660->zisofs.allzero && 7645 avail + zstrm->total_in == ZF_BLOCK_SIZE) { 7646 if (iso9660->zisofs.block_offset != 7647 file->cur_content->size) { 7648 int64_t diff; 7649 7650 r = wb_set_offset(a, 7651 file->cur_content->offset_of_temp + 7652 iso9660->zisofs.block_offset); 7653 if (r != ARCHIVE_OK) 7654 return (r); 7655 diff = file->cur_content->size - 7656 iso9660->zisofs.block_offset; 7657 file->cur_content->size -= diff; 7658 iso9660->zisofs.total_size -= diff; 7659 } 7660 zstrm->avail_in = 0; 7661 } 7662 7663 /* 7664 * Compress file data. 7665 */ 7666 while (zstrm->avail_in > 0) { 7667 csize = zstrm->total_out; 7668 r = deflate(zstrm, flush); 7669 switch (r) { 7670 case Z_OK: 7671 case Z_STREAM_END: 7672 csize = zstrm->total_out - csize; 7673 if (wb_consume(a, csize) != ARCHIVE_OK) 7674 return (ARCHIVE_FATAL); 7675 iso9660->zisofs.total_size += csize; 7676 iso9660->cur_file->cur_content->size += csize; 7677 zstrm->next_out = wb_buffptr(a); 7678 zstrm->avail_out = (uInt)wb_remaining(a); 7679 break; 7680 default: 7681 archive_set_error(&a->archive, 7682 ARCHIVE_ERRNO_MISC, 7683 "Compression failed:" 7684 " deflate() call returned status %d", 7685 r); 7686 return (ARCHIVE_FATAL); 7687 } 7688 } 7689 7690 if (flush == Z_FINISH) { 7691 /* 7692 * Save the information of one zisofs block. 7693 */ 7694 iso9660->zisofs.block_pointers_idx ++; 7695 archive_le32enc(&(iso9660->zisofs.block_pointers[ 7696 iso9660->zisofs.block_pointers_idx]), 7697 (uint32_t)iso9660->zisofs.total_size); 7698 r = zisofs_init_zstream(a); 7699 if (r != ARCHIVE_OK) 7700 return (ARCHIVE_FATAL); 7701 iso9660->zisofs.allzero = 1; 7702 iso9660->zisofs.block_offset = file->cur_content->size; 7703 } 7704 } while (s); 7705 7706 return (ARCHIVE_OK); 7707 } 7708 7709 static int 7710 zisofs_finish_entry(struct archive_write *a) 7711 { 7712 struct iso9660 *iso9660 = a->format_data; 7713 struct isofile *file = iso9660->cur_file; 7714 unsigned char buff[16]; 7715 size_t s; 7716 int64_t tail; 7717 7718 /* Direct temp file stream to zisofs temp file stream. */ 7719 archive_entry_set_size(file->entry, iso9660->zisofs.total_size); 7720 7721 /* 7722 * Save a file pointer which points the end of current zisofs data. 7723 */ 7724 tail = wb_offset(a); 7725 7726 /* 7727 * Make a header. 7728 * 7729 * +-----------------+----------------+-----------------+ 7730 * | Header 16 bytes | Block Pointers | Compressed data | 7731 * +-----------------+----------------+-----------------+ 7732 * 0 16 +X 7733 * Block Pointers : 7734 * 4 * (((Uncompressed file size + block_size -1) / block_size) + 1) 7735 * 7736 * Write zisofs header. 7737 * Magic number 7738 * +----+----+----+----+----+----+----+----+ 7739 * | 37 | E4 | 53 | 96 | C9 | DB | D6 | 07 | 7740 * +----+----+----+----+----+----+----+----+ 7741 * 0 1 2 3 4 5 6 7 8 7742 * 7743 * +------------------------+------------------+ 7744 * | Uncompressed file size | header_size >> 2 | 7745 * +------------------------+------------------+ 7746 * 8 12 13 7747 * 7748 * +-----------------+----------------+ 7749 * | log2 block_size | Reserved(0000) | 7750 * +-----------------+----------------+ 7751 * 13 14 16 7752 */ 7753 memcpy(buff, zisofs_magic, 8); 7754 set_num_731(buff+8, file->zisofs.uncompressed_size); 7755 buff[12] = file->zisofs.header_size; 7756 buff[13] = file->zisofs.log2_bs; 7757 buff[14] = buff[15] = 0;/* Reserved */ 7758 7759 /* Move to the right position to write the header. */ 7760 wb_set_offset(a, file->content.offset_of_temp); 7761 7762 /* Write the header. */ 7763 if (wb_write_to_temp(a, buff, 16) != ARCHIVE_OK) 7764 return (ARCHIVE_FATAL); 7765 7766 /* 7767 * Write zisofs Block Pointers. 7768 */ 7769 s = iso9660->zisofs.block_pointers_cnt * 7770 sizeof(iso9660->zisofs.block_pointers[0]); 7771 if (wb_write_to_temp(a, iso9660->zisofs.block_pointers, s) 7772 != ARCHIVE_OK) 7773 return (ARCHIVE_FATAL); 7774 7775 /* Set a file pointer back to the end of the temporary file. */ 7776 wb_set_offset(a, tail); 7777 7778 return (ARCHIVE_OK); 7779 } 7780 7781 static int 7782 zisofs_free(struct archive_write *a) 7783 { 7784 struct iso9660 *iso9660 = a->format_data; 7785 int ret = ARCHIVE_OK; 7786 7787 free(iso9660->zisofs.block_pointers); 7788 if (iso9660->zisofs.stream_valid && 7789 deflateEnd(&(iso9660->zisofs.stream)) != Z_OK) { 7790 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 7791 "Failed to clean up compressor"); 7792 ret = ARCHIVE_FATAL; 7793 } 7794 iso9660->zisofs.block_pointers = NULL; 7795 iso9660->zisofs.stream_valid = 0; 7796 return (ret); 7797 } 7798 7799 struct zisofs_extract { 7800 int pz_log2_bs; /* Log2 of block size */ 7801 uint64_t pz_uncompressed_size; 7802 size_t uncompressed_buffer_size; 7803 7804 int initialized:1; 7805 int header_passed:1; 7806 7807 uint32_t pz_offset; 7808 unsigned char *block_pointers; 7809 size_t block_pointers_size; 7810 size_t block_pointers_avail; 7811 size_t block_off; 7812 uint32_t block_avail; 7813 7814 z_stream stream; 7815 int stream_valid; 7816 }; 7817 7818 static ssize_t 7819 zisofs_extract_init(struct archive_write *a, struct zisofs_extract *zisofs, 7820 const unsigned char *p, size_t bytes) 7821 { 7822 size_t avail = bytes; 7823 size_t _ceil, xsize; 7824 7825 /* Allocate block pointers buffer. */ 7826 _ceil = (size_t)((zisofs->pz_uncompressed_size + 7827 (((int64_t)1) << zisofs->pz_log2_bs) - 1) 7828 >> zisofs->pz_log2_bs); 7829 xsize = (_ceil + 1) * 4; 7830 if (zisofs->block_pointers == NULL) { 7831 size_t alloc = ((xsize >> 10) + 1) << 10; 7832 zisofs->block_pointers = malloc(alloc); 7833 if (zisofs->block_pointers == NULL) { 7834 archive_set_error(&a->archive, ENOMEM, 7835 "No memory for zisofs decompression"); 7836 return (ARCHIVE_FATAL); 7837 } 7838 } 7839 zisofs->block_pointers_size = xsize; 7840 7841 /* Allocate uncompressed data buffer. */ 7842 zisofs->uncompressed_buffer_size = (size_t)1UL << zisofs->pz_log2_bs; 7843 7844 /* 7845 * Read the file header, and check the magic code of zisofs. 7846 */ 7847 if (!zisofs->header_passed) { 7848 int err = 0; 7849 if (avail < 16) { 7850 archive_set_error(&a->archive, 7851 ARCHIVE_ERRNO_FILE_FORMAT, 7852 "Illegal zisofs file body"); 7853 return (ARCHIVE_FATAL); 7854 } 7855 7856 if (memcmp(p, zisofs_magic, sizeof(zisofs_magic)) != 0) 7857 err = 1; 7858 else if (archive_le32dec(p + 8) != zisofs->pz_uncompressed_size) 7859 err = 1; 7860 else if (p[12] != 4 || p[13] != zisofs->pz_log2_bs) 7861 err = 1; 7862 if (err) { 7863 archive_set_error(&a->archive, 7864 ARCHIVE_ERRNO_FILE_FORMAT, 7865 "Illegal zisofs file body"); 7866 return (ARCHIVE_FATAL); 7867 } 7868 avail -= 16; 7869 p += 16; 7870 zisofs->header_passed = 1; 7871 } 7872 7873 /* 7874 * Read block pointers. 7875 */ 7876 if (zisofs->header_passed && 7877 zisofs->block_pointers_avail < zisofs->block_pointers_size) { 7878 xsize = zisofs->block_pointers_size 7879 - zisofs->block_pointers_avail; 7880 if (avail < xsize) 7881 xsize = avail; 7882 memcpy(zisofs->block_pointers 7883 + zisofs->block_pointers_avail, p, xsize); 7884 zisofs->block_pointers_avail += xsize; 7885 avail -= xsize; 7886 if (zisofs->block_pointers_avail 7887 == zisofs->block_pointers_size) { 7888 /* We've got all block pointers and initialize 7889 * related variables. */ 7890 zisofs->block_off = 0; 7891 zisofs->block_avail = 0; 7892 /* Complete a initialization */ 7893 zisofs->initialized = 1; 7894 } 7895 } 7896 return ((ssize_t)avail); 7897 } 7898 7899 static ssize_t 7900 zisofs_extract(struct archive_write *a, struct zisofs_extract *zisofs, 7901 const unsigned char *p, size_t bytes) 7902 { 7903 size_t avail; 7904 int r; 7905 7906 if (!zisofs->initialized) { 7907 ssize_t rs = zisofs_extract_init(a, zisofs, p, bytes); 7908 if (rs < 0) 7909 return (rs); 7910 if (!zisofs->initialized) { 7911 /* We need more data. */ 7912 zisofs->pz_offset += (uint32_t)bytes; 7913 return (bytes); 7914 } 7915 avail = rs; 7916 p += bytes - avail; 7917 } else 7918 avail = bytes; 7919 7920 /* 7921 * Get block offsets from block pointers. 7922 */ 7923 if (zisofs->block_avail == 0) { 7924 uint32_t bst, bed; 7925 7926 if (zisofs->block_off + 4 >= zisofs->block_pointers_size) { 7927 /* There isn't a pair of offsets. */ 7928 archive_set_error(&a->archive, 7929 ARCHIVE_ERRNO_FILE_FORMAT, 7930 "Illegal zisofs block pointers"); 7931 return (ARCHIVE_FATAL); 7932 } 7933 bst = archive_le32dec( 7934 zisofs->block_pointers + zisofs->block_off); 7935 if (bst != zisofs->pz_offset + (bytes - avail)) { 7936 archive_set_error(&a->archive, 7937 ARCHIVE_ERRNO_FILE_FORMAT, 7938 "Illegal zisofs block pointers(cannot seek)"); 7939 return (ARCHIVE_FATAL); 7940 } 7941 bed = archive_le32dec( 7942 zisofs->block_pointers + zisofs->block_off + 4); 7943 if (bed < bst) { 7944 archive_set_error(&a->archive, 7945 ARCHIVE_ERRNO_FILE_FORMAT, 7946 "Illegal zisofs block pointers"); 7947 return (ARCHIVE_FATAL); 7948 } 7949 zisofs->block_avail = bed - bst; 7950 zisofs->block_off += 4; 7951 7952 /* Initialize compression library for new block. */ 7953 if (zisofs->stream_valid) 7954 r = inflateReset(&zisofs->stream); 7955 else 7956 r = inflateInit(&zisofs->stream); 7957 if (r != Z_OK) { 7958 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 7959 "Can't initialize zisofs decompression."); 7960 return (ARCHIVE_FATAL); 7961 } 7962 zisofs->stream_valid = 1; 7963 zisofs->stream.total_in = 0; 7964 zisofs->stream.total_out = 0; 7965 } 7966 7967 /* 7968 * Make uncompressed data. 7969 */ 7970 if (zisofs->block_avail == 0) { 7971 /* 7972 * It's basically 32K bytes NUL data. 7973 */ 7974 unsigned char *wb; 7975 size_t size, wsize; 7976 7977 size = zisofs->uncompressed_buffer_size; 7978 while (size) { 7979 wb = wb_buffptr(a); 7980 if (size > wb_remaining(a)) 7981 wsize = wb_remaining(a); 7982 else 7983 wsize = size; 7984 memset(wb, 0, wsize); 7985 r = wb_consume(a, wsize); 7986 if (r < 0) 7987 return (r); 7988 size -= wsize; 7989 } 7990 } else { 7991 zisofs->stream.next_in = (Bytef *)(uintptr_t)(const void *)p; 7992 if (avail > zisofs->block_avail) 7993 zisofs->stream.avail_in = zisofs->block_avail; 7994 else 7995 zisofs->stream.avail_in = (uInt)avail; 7996 zisofs->stream.next_out = wb_buffptr(a); 7997 zisofs->stream.avail_out = (uInt)wb_remaining(a); 7998 7999 r = inflate(&zisofs->stream, 0); 8000 switch (r) { 8001 case Z_OK: /* Decompressor made some progress.*/ 8002 case Z_STREAM_END: /* Found end of stream. */ 8003 break; 8004 default: 8005 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 8006 "zisofs decompression failed (%d)", r); 8007 return (ARCHIVE_FATAL); 8008 } 8009 avail -= zisofs->stream.next_in - p; 8010 zisofs->block_avail -= (uint32_t)(zisofs->stream.next_in - p); 8011 r = wb_consume(a, wb_remaining(a) - zisofs->stream.avail_out); 8012 if (r < 0) 8013 return (r); 8014 } 8015 zisofs->pz_offset += (uint32_t)bytes; 8016 return (bytes - avail); 8017 } 8018 8019 static int 8020 zisofs_rewind_boot_file(struct archive_write *a) 8021 { 8022 struct iso9660 *iso9660 = a->format_data; 8023 struct isofile *file; 8024 unsigned char *rbuff; 8025 ssize_t r; 8026 size_t remaining, rbuff_size; 8027 struct zisofs_extract zext; 8028 int64_t read_offset, write_offset, new_offset; 8029 int fd, ret = ARCHIVE_OK; 8030 8031 file = iso9660->el_torito.boot->file; 8032 /* 8033 * There is nothing to do if this boot file does not have 8034 * zisofs header. 8035 */ 8036 if (file->zisofs.header_size == 0) 8037 return (ARCHIVE_OK); 8038 8039 /* 8040 * Uncompress the zisofs'ed file contents. 8041 */ 8042 memset(&zext, 0, sizeof(zext)); 8043 zext.pz_uncompressed_size = file->zisofs.uncompressed_size; 8044 zext.pz_log2_bs = file->zisofs.log2_bs; 8045 8046 fd = iso9660->temp_fd; 8047 new_offset = wb_offset(a); 8048 read_offset = file->content.offset_of_temp; 8049 remaining = (size_t)file->content.size; 8050 if (remaining > 1024 * 32) 8051 rbuff_size = 1024 * 32; 8052 else 8053 rbuff_size = remaining; 8054 8055 rbuff = malloc(rbuff_size); 8056 if (rbuff == NULL) { 8057 archive_set_error(&a->archive, ENOMEM, "Can't allocate memory"); 8058 return (ARCHIVE_FATAL); 8059 } 8060 while (remaining) { 8061 size_t rsize; 8062 ssize_t rs; 8063 8064 /* Get the current file pointer. */ 8065 write_offset = lseek(fd, 0, SEEK_CUR); 8066 8067 /* Change the file pointer to read. */ 8068 lseek(fd, read_offset, SEEK_SET); 8069 8070 rsize = rbuff_size; 8071 if (rsize > remaining) 8072 rsize = remaining; 8073 rs = read(iso9660->temp_fd, rbuff, rsize); 8074 if (rs <= 0) { 8075 archive_set_error(&a->archive, errno, 8076 "Can't read temporary file(%jd)", (intmax_t)rs); 8077 ret = ARCHIVE_FATAL; 8078 break; 8079 } 8080 remaining -= rs; 8081 read_offset += rs; 8082 8083 /* Put the file pointer back to write. */ 8084 lseek(fd, write_offset, SEEK_SET); 8085 8086 r = zisofs_extract(a, &zext, rbuff, rs); 8087 if (r < 0) { 8088 ret = (int)r; 8089 break; 8090 } 8091 } 8092 8093 if (ret == ARCHIVE_OK) { 8094 /* 8095 * Change the boot file content from zisofs'ed data 8096 * to plain data. 8097 */ 8098 file->content.offset_of_temp = new_offset; 8099 file->content.size = file->zisofs.uncompressed_size; 8100 archive_entry_set_size(file->entry, file->content.size); 8101 /* Set to be no zisofs. */ 8102 file->zisofs.header_size = 0; 8103 file->zisofs.log2_bs = 0; 8104 file->zisofs.uncompressed_size = 0; 8105 r = wb_write_padding_to_temp(a, file->content.size); 8106 if (r < 0) 8107 ret = ARCHIVE_FATAL; 8108 } 8109 8110 /* 8111 * Free the resource we used in this function only. 8112 */ 8113 free(rbuff); 8114 free(zext.block_pointers); 8115 if (zext.stream_valid && inflateEnd(&(zext.stream)) != Z_OK) { 8116 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 8117 "Failed to clean up compressor"); 8118 ret = ARCHIVE_FATAL; 8119 } 8120 8121 return (ret); 8122 } 8123 8124 #else 8125 8126 static int 8127 zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s) 8128 { 8129 (void)buff; /* UNUSED */ 8130 (void)s; /* UNUSED */ 8131 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Programing error"); 8132 return (ARCHIVE_FATAL); 8133 } 8134 8135 static int 8136 zisofs_rewind_boot_file(struct archive_write *a) 8137 { 8138 struct iso9660 *iso9660 = a->format_data; 8139 8140 if (iso9660->el_torito.boot->file->zisofs.header_size != 0) { 8141 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 8142 "We cannot extract the zisofs imaged boot file;" 8143 " this may not boot in being zisofs imaged"); 8144 return (ARCHIVE_FAILED); 8145 } 8146 return (ARCHIVE_OK); 8147 } 8148 8149 static int 8150 zisofs_finish_entry(struct archive_write *a) 8151 { 8152 (void)a; /* UNUSED */ 8153 return (ARCHIVE_OK); 8154 } 8155 8156 static int 8157 zisofs_free(struct archive_write *a) 8158 { 8159 (void)a; /* UNUSED */ 8160 return (ARCHIVE_OK); 8161 } 8162 8163 #endif /* HAVE_ZLIB_H */ 8164 8165