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