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