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