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