Compare commits
423 Commits
release-1.
...
master
Author | SHA1 | Date |
---|---|---|
Thomas Schmitt | 78708015af | |
Thomas Schmitt | 57fcd4bfbb | |
Thomas Schmitt | 483a68aaf2 | |
Thomas Schmitt | 8ffd3b381b | |
Thomas Schmitt | d9c548dbfc | |
Thomas Schmitt | 8ed27c6255 | |
Thomas Schmitt | 405f0f04d4 | |
Thomas Schmitt | 8a8439768c | |
Thomas Schmitt | 9ec998f9fc | |
Thomas Schmitt | 8a4f1f88ae | |
Thomas Schmitt | 09ec2fa4b7 | |
Thomas Schmitt | 5a867c43ab | |
Thomas Schmitt | 170318c42e | |
Thomas Schmitt | c2d17b1c4b | |
Thomas Schmitt | cdc7f52187 | |
Thomas Schmitt | bd415402f4 | |
Thomas Schmitt | 7109ba5675 | |
Thomas Schmitt | d35435b5a0 | |
Thomas Schmitt | acb4bd143c | |
Thomas Schmitt | 71772baab7 | |
Thomas Schmitt | 83e5832ed0 | |
Thomas Schmitt | 9b7ccc9727 | |
Thomas Schmitt | c6cb7dfa3e | |
Thomas Schmitt | ad55ec78e4 | |
Thomas Schmitt | 011e2e85e6 | |
Thomas Schmitt | f457a4f8b9 | |
Thomas Schmitt | 2af17490a0 | |
Thomas Schmitt | da00291519 | |
Thomas Schmitt | 1d61b518b5 | |
Thomas Schmitt | 99251ade08 | |
Thomas Schmitt | da8e3e66e7 | |
Thomas Schmitt | 3e61a61a21 | |
Thomas Schmitt | 80a0691660 | |
Thomas Schmitt | 1c4c04d4e2 | |
Thomas Schmitt | 75499bcda9 | |
Thomas Schmitt | 9e389186f7 | |
Thomas Schmitt | 7d248c46e1 | |
Thomas Schmitt | 98aea0c18a | |
Thomas Schmitt | 058f18d37a | |
Thomas Schmitt | 5add62bda0 | |
Thomas Schmitt | 2d1fec2569 | |
Thomas Schmitt | 4219bf4950 | |
Thomas Schmitt | 2a20e93b13 | |
Thomas Schmitt | 62411411db | |
Thomas Schmitt | 8f3ff65c04 | |
Thomas Schmitt | c068a19a8c | |
Thomas Schmitt | cece6fb371 | |
Thomas Schmitt | 29cc5c8d31 | |
Thomas Schmitt | 92af0c9752 | |
Thomas Schmitt | daaee5e7e6 | |
Thomas Schmitt | 7e3b01b53c | |
Thomas Schmitt | 1d5566f8bb | |
Thomas Schmitt | ac9d55330d | |
Thomas Schmitt | b0687643c5 | |
Thomas Schmitt | 5a98a4cda5 | |
Thomas Schmitt | b7a90c5194 | |
Thomas Schmitt | 8d70c75d4a | |
Thomas Schmitt | 9605bbe748 | |
Thomas Schmitt | 46186e5f06 | |
Thomas Schmitt | 2ac62f0cac | |
Thomas Schmitt | dc61e7d298 | |
Thomas Schmitt | d5ffecf2f5 | |
Thomas Schmitt | 80449f0dc9 | |
Thomas Schmitt | cc2e0e32a3 | |
Thomas Schmitt | 239ba69925 | |
Thomas Schmitt | 2ca3b292fb | |
Thomas Schmitt | f291e37ec1 | |
Thomas Schmitt | b107443769 | |
Thomas Schmitt | d297ce3aed | |
Thomas Schmitt | f962d0da66 | |
Thomas Schmitt | b0230b6ac8 | |
Thomas Schmitt | 69e332d17a | |
Thomas Schmitt | 6ca841e002 | |
Thomas Schmitt | c84f6ae689 | |
Thomas Schmitt | ac248877a2 | |
Thomas Schmitt | c1d9639dba | |
Thomas Schmitt | 773be790e8 | |
Thomas Schmitt | dc3d82cf36 | |
Thomas Schmitt | 560c11617e | |
Thomas Schmitt | fa43a5a25c | |
Thomas Schmitt | 4d8a467e1a | |
Thomas Schmitt | 65c4dce69a | |
Thomas Schmitt | fe98b35afb | |
Thomas Schmitt | 130b46cf71 | |
Thomas Schmitt | eb7dc408e0 | |
Thomas Schmitt | a5e209265d | |
Thomas Schmitt | 458ab43ecd | |
Thomas Schmitt | 4b21386e82 | |
Thomas Schmitt | c62d9d7b1b | |
Thomas Schmitt | 3aab1cafc5 | |
Thomas Schmitt | 8fbc2fcdfd | |
Thomas Schmitt | aed8bda955 | |
Thomas Schmitt | e1097dbb5d | |
Thomas Schmitt | a1e75003b5 | |
Thomas Schmitt | 4064a7e0ee | |
Thomas Schmitt | 96261585f1 | |
Thomas Schmitt | 01415ae208 | |
Thomas Schmitt | 241b9ea832 | |
Thomas Schmitt | 6a6343c146 | |
Thomas Schmitt | a63b16f7da | |
Thomas Schmitt | 31c4c26567 | |
Thomas Schmitt | 6b31667ee4 | |
Thomas Schmitt | 066c6f685d | |
Thomas Schmitt | e317a8d93e | |
Thomas Schmitt | d3c17d0555 | |
Thomas Schmitt | 69c8c543a9 | |
Thomas Schmitt | f39d4eefee | |
Thomas Schmitt | 848e039e6d | |
Thomas Schmitt | c5a9cc56e3 | |
Thomas Schmitt | 310612174b | |
Thomas Schmitt | ad843f1723 | |
Thomas Schmitt | 615dc7e997 | |
Thomas Schmitt | a936409a82 | |
Thomas Schmitt | 580b154773 | |
Thomas Schmitt | 1da3b17233 | |
Thomas Schmitt | 633b4d5f72 | |
Thomas Schmitt | 4b031b58ea | |
Thomas Schmitt | 7d45c88cff | |
Thomas Schmitt | 79baab3fc9 | |
Thomas Schmitt | 53b2d6dcd7 | |
Thomas Schmitt | 874dc16d92 | |
Thomas Schmitt | 34e35865fe | |
Thomas Schmitt | ce831f111c | |
Thomas Schmitt | 48ee49a7e0 | |
Thomas Schmitt | bdfd4c4a37 | |
Thomas Schmitt | dfc6de9f79 | |
Thomas Schmitt | 7234425502 | |
Thomas Schmitt | 4e5a54c2f9 | |
Thomas Schmitt | 028f9275d3 | |
Thomas Schmitt | cace41ec16 | |
Thomas Schmitt | e599a575dc | |
Thomas Schmitt | 78b0a7b111 | |
Thomas Schmitt | a7152f5794 | |
Thomas Schmitt | 2a64d89e6e | |
Thomas Schmitt | 31088d9acc | |
Thomas Schmitt | 91490d5f34 | |
Thomas Schmitt | 661b68ce8c | |
Thomas Schmitt | 16bde11076 | |
Thomas Schmitt | 36c8800ff3 | |
Thomas Schmitt | 860a91dd2f | |
Thomas Schmitt | 280108d2d5 | |
Thomas Schmitt | 1e40ed3fab | |
Thomas Schmitt | e19a338a09 | |
Thomas Schmitt | c6e4035918 | |
Thomas Schmitt | 18ab6019bc | |
Thomas Schmitt | 6282bbc0bc | |
Thomas Schmitt | d7737e3ed5 | |
Thomas Schmitt | fb8697081b | |
Thomas Schmitt | 0e7300b1a8 | |
Thomas Schmitt | 94e4bfb42b | |
Thomas Schmitt | 86f6ffc9c9 | |
Thomas Schmitt | 5600f3d726 | |
Thomas Schmitt | e66b9bfe0c | |
Thomas Schmitt | 094b3f7546 | |
Thomas Schmitt | 5c1c5cd964 | |
Thomas Schmitt | 215280448f | |
Thomas Schmitt | 3043b5f660 | |
Thomas Schmitt | afb10aac3b | |
Thomas Schmitt | 76181d0aa3 | |
Thomas Schmitt | 8ec75eea6a | |
Thomas Schmitt | 01020ef544 | |
Thomas Schmitt | 2961bdef9f | |
Thomas Schmitt | ed209e0b6e | |
Thomas Schmitt | dc6cd946ba | |
Thomas Schmitt | c51efce8d1 | |
Thomas Schmitt | 8bf32d8d14 | |
Thomas Schmitt | 561e2a6aaa | |
Thomas Schmitt | e7dd325ff6 | |
Thomas Schmitt | 0447496710 | |
Thomas Schmitt | 496b8051c5 | |
Thomas Schmitt | 63c074b0aa | |
Thomas Schmitt | 2be47f9af8 | |
Thomas Schmitt | bf5678c6d4 | |
Thomas Schmitt | 9d64318502 | |
Thomas Schmitt | 866f647fad | |
Thomas Schmitt | 2f134dcdcb | |
Thomas Schmitt | b14ee71d51 | |
Thomas Schmitt | c5c9d4e7bf | |
Thomas Schmitt | 6321ed4d97 | |
Thomas Schmitt | 188e36178b | |
Thomas Schmitt | cbfa9afcf1 | |
Thomas Schmitt | cb519b3692 | |
Thomas Schmitt | 8407d9e936 | |
Thomas Schmitt | d482eb4c96 | |
Thomas Schmitt | 1786ceb276 | |
Thomas Schmitt | f51fc50356 | |
Thomas Schmitt | 02de4570d1 | |
Thomas Schmitt | 2a41b4817c | |
Thomas Schmitt | 9440e3061c | |
Thomas Schmitt | 122dfe7b87 | |
Thomas Schmitt | 03662f0832 | |
Thomas Schmitt | eb09bcf9e5 | |
Thomas Schmitt | 5880636a50 | |
Thomas Schmitt | b5fb98a2a3 | |
Thomas Schmitt | b269557743 | |
Thomas Schmitt | 0fd7d4d7eb | |
Thomas Schmitt | d8dca37d65 | |
Thomas Schmitt | cd84f0927f | |
Thomas Schmitt | 477bbb89bb | |
Thomas Schmitt | 31fcdc0ba6 | |
Thomas Schmitt | 7c05d2a865 | |
Thomas Schmitt | 3d15642307 | |
Thomas Schmitt | 872b5c6c67 | |
Thomas Schmitt | ec35bb21c0 | |
Thomas Schmitt | 93f3cb1823 | |
Thomas Schmitt | fea7be5168 | |
Thomas Schmitt | bd25db9283 | |
Thomas Schmitt | 97eec6162c | |
Thomas Schmitt | 17e8cb6697 | |
Thomas Schmitt | 9e01d3654e | |
Thomas Schmitt | 009ce1be8f | |
Thomas Schmitt | c79299ba08 | |
Thomas Schmitt | b3701f0b18 | |
Thomas Schmitt | 83b864efd2 | |
Thomas Schmitt | cd0f57dd1a | |
Thomas Schmitt | 4c9cb6b96b | |
Thomas Schmitt | 9c334891cf | |
Thomas Schmitt | 2f6103b783 | |
Thomas Schmitt | f32ee7da83 | |
Thomas Schmitt | 52972811f8 | |
Thomas Schmitt | 089982022c | |
Thomas Schmitt | a6316ff05c | |
Thomas Schmitt | 02a972a2d7 | |
Thomas Schmitt | da8ad0d2aa | |
Thomas Schmitt | 79e6312397 | |
Thomas Schmitt | b3a183fceb | |
Thomas Schmitt | 355f1f7ea2 | |
Thomas Schmitt | 57fd669d1d | |
Thomas Schmitt | 6047464b6b | |
Thomas Schmitt | e8b94e7b50 | |
Thomas Schmitt | 49dd9dc993 | |
Thomas Schmitt | 93e1fc52d0 | |
Thomas Schmitt | 4838cd59a7 | |
Thomas Schmitt | d51b1738dd | |
Thomas Schmitt | 6252ae2065 | |
Thomas Schmitt | cb1e56478a | |
Thomas Schmitt | 05d0ee4a37 | |
Thomas Schmitt | c6aedc9eb5 | |
Thomas Schmitt | 505bf23aa4 | |
Thomas Schmitt | ccef2f29da | |
Thomas Schmitt | b904926443 | |
Thomas Schmitt | 7bdc4c96f5 | |
Thomas Schmitt | fa5e27458a | |
Thomas Schmitt | 7c29a94ab6 | |
Thomas Schmitt | a4c1e04820 | |
Thomas Schmitt | 50132d4ff7 | |
Thomas Schmitt | 4c1c1ea152 | |
Thomas Schmitt | a16d4a28f4 | |
Thomas Schmitt | 4633ea3bc8 | |
Thomas Schmitt | 430c005666 | |
Thomas Schmitt | af55722830 | |
Thomas Schmitt | d1da5718c7 | |
Thomas Schmitt | afb2878773 | |
Thomas Schmitt | 4e7432c20f | |
Thomas Schmitt | 7ef616f268 | |
Thomas Schmitt | d5f1eb9c65 | |
Thomas Schmitt | 28b41bce2c | |
Thomas Schmitt | 5ac3216933 | |
Thomas Schmitt | 05a2171e04 | |
Thomas Schmitt | 188a41f041 | |
Thomas Schmitt | fbe7f1e89d | |
Thomas Schmitt | d04abdcfbd | |
Thomas Schmitt | a6542e5fa9 | |
Thomas Schmitt | 78d2c02ad8 | |
Thomas Schmitt | 48453ef1da | |
Thomas Schmitt | 7928c4ec3f | |
Thomas Schmitt | 379e223a5c | |
Thomas Schmitt | e4750907e3 | |
Thomas Schmitt | 8f76b59541 | |
Thomas Schmitt | 0433b7ea75 | |
Thomas Schmitt | d8fb8b26a6 | |
Thomas Schmitt | b9ccdeda72 | |
Thomas Schmitt | d04f438ba1 | |
Thomas Schmitt | e35cb88328 | |
Thomas Schmitt | 83fb614462 | |
Thomas Schmitt | e5f6811795 | |
Thomas Schmitt | f3b836194c | |
Thomas Schmitt | 3a870d23e3 | |
Thomas Schmitt | 06ea46c8d5 | |
Thomas Schmitt | d427a03192 | |
Thomas Schmitt | 2b6071b445 | |
Thomas Schmitt | fc448e09c9 | |
Thomas Schmitt | 7b7da47d86 | |
Thomas Schmitt | 01c7a0d5ec | |
Thomas Schmitt | 905f4f898f | |
Thomas Schmitt | b9ec876c40 | |
Thomas Schmitt | 72ef369a40 | |
Thomas Schmitt | 218e26c974 | |
Thomas Schmitt | 395128ef5f | |
Thomas Schmitt | 7a3560035a | |
Thomas Schmitt | 7ac5b75748 | |
Thomas Schmitt | 6c3dc3ce4a | |
Thomas Schmitt | bdbaf81e9c | |
Thomas Schmitt | c8ed18695f | |
Thomas Schmitt | d3fefe4735 | |
Thomas Schmitt | 6db3f6ca44 | |
stacker | bf19f73ea6 | |
stacker | 6947bfe5ec | |
Thomas Schmitt | 94f8503b57 | |
Thomas Schmitt | cb519e221e | |
Thomas Schmitt | d09a317f51 | |
Thomas Schmitt | 2beb0d001b | |
Thomas Schmitt | 6c9b81a474 | |
Thomas Schmitt | 393cc070f3 | |
Thomas Schmitt | 006caa2fd2 | |
Thomas Schmitt | c47167058a | |
Thomas Schmitt | 5a3d84cbbb | |
Thomas Schmitt | 5f6e64b792 | |
Thomas Schmitt | d4b8cbe474 | |
Thomas Schmitt | a0719328ea | |
Thomas Schmitt | c8776e605e | |
Thomas Schmitt | 003aa5832e | |
Thomas Schmitt | a78864252e | |
Thomas Schmitt | e56a782b89 | |
Thomas Schmitt | 9e17516e0d | |
Thomas Schmitt | e29cd723dd | |
Thomas Schmitt | b0694b4e25 | |
Thomas Schmitt | 850302dde5 | |
Thomas Schmitt | 26b4222948 | |
Thomas Schmitt | 782bb7854e | |
Thomas Schmitt | 9c33eb5f10 | |
Thomas Schmitt | 8e55195edc | |
Thomas Schmitt | 527b613607 | |
Thomas Schmitt | 0819f93f79 | |
Thomas Schmitt | 3b0ba17f3d | |
Thomas Schmitt | 0611f468c2 | |
Thomas Schmitt | 5c6ce72c02 | |
Thomas Schmitt | 585a54d020 | |
Thomas Schmitt | 7ea6d4ebcb | |
Thomas Schmitt | 3e33fa5fa1 | |
Thomas Schmitt | cdc336a02b | |
Thomas Schmitt | 288eb75745 | |
Thomas Schmitt | 210b5817cb | |
Thomas Schmitt | 2fe0bf511b | |
Thomas Schmitt | af23ad0f90 | |
Thomas Schmitt | 0fc4421e15 | |
Thomas Schmitt | 6ed2404420 | |
Thomas Schmitt | a22c16d5ef | |
Thomas Schmitt | 5384342336 | |
Thomas Schmitt | a97c66ebb8 | |
Thomas Schmitt | 1c2851b5ba | |
Thomas Schmitt | cbea1335d8 | |
Thomas Schmitt | 6da58860ec | |
Thomas Schmitt | c47451d12b | |
Thomas Schmitt | a068a1349a | |
Thomas Schmitt | eae886bcb5 | |
Thomas Schmitt | 288e778875 | |
Thomas Schmitt | 8e687db01d | |
Thomas Schmitt | 273182aa2a | |
Thomas Schmitt | e26d07ee77 | |
Thomas Schmitt | 1b5caac764 | |
Thomas Schmitt | 42821af4e6 | |
Thomas Schmitt | c17ba1980a | |
Thomas Schmitt | 1df1642a61 | |
Thomas Schmitt | c07f42dfd4 | |
Thomas Schmitt | 443156e100 | |
Thomas Schmitt | 2f517301de | |
Thomas Schmitt | 0bce145343 | |
Thomas Schmitt | 6d64bc23cf | |
Thomas Schmitt | 25295d2bb0 | |
Thomas Schmitt | 3370f666f9 | |
Thomas Schmitt | ad279352e3 | |
Thomas Schmitt | dfd74d3d04 | |
Thomas Schmitt | 593844b0ed | |
Thomas Schmitt | 083795cba2 | |
Thomas Schmitt | 3b06d25a37 | |
Thomas Schmitt | 9e5158f59e | |
Thomas Schmitt | d93be961e1 | |
Thomas Schmitt | 8c1c0775d6 | |
Thomas Schmitt | 2f8bd3ac01 | |
Thomas Schmitt | 6edc1ac057 | |
Thomas Schmitt | a394f4dfd2 | |
Thomas Schmitt | dd27f579eb | |
Thomas Schmitt | 1ac59bec46 | |
Thomas Schmitt | af843e446f | |
Thomas Schmitt | e6e037f87e | |
Thomas Schmitt | ca2643b52b | |
Thomas Schmitt | ed8066580a | |
Thomas Schmitt | 97ec68530b | |
Thomas Schmitt | 185cbd99bf | |
Thomas Schmitt | 0e00aeb638 | |
Thomas Schmitt | 03b45c3151 | |
Thomas Schmitt | b82ca42f87 | |
Thomas Schmitt | 1a8a216822 | |
Thomas Schmitt | ef528f2f0e | |
Thomas Schmitt | bedfa914d5 | |
Thomas Schmitt | 5383ae2faa | |
Thomas Schmitt | d23462657b | |
Thomas Schmitt | b41e36365d | |
Thomas Schmitt | 985015cea1 | |
Thomas Schmitt | 27d4c79d0e | |
Thomas Schmitt | 5b78efb12a | |
Thomas Schmitt | 2c2fb7caf2 | |
Thomas Schmitt | d51cefb097 | |
Thomas Schmitt | 7637d13e11 | |
Thomas Schmitt | b9b5284f22 | |
Thomas Schmitt | afa65e9f2a | |
Thomas Schmitt | 5e1aaca232 | |
Thomas Schmitt | fea649835c | |
Thomas Schmitt | 44f475a4ef | |
Thomas Schmitt | 60eb7e883c | |
Thomas Schmitt | 9b4e0b611a | |
Thomas Schmitt | 1be57e34ec | |
Thomas Schmitt | b0e68bbcaa | |
Thomas Schmitt | fa61b94ac8 | |
Thomas Schmitt | 3e3c15812b | |
Thomas Schmitt | 88555bd059 | |
Thomas Schmitt | ba47d1534c | |
Thomas Schmitt | b7dc0f4057 | |
Thomas Schmitt | 0ab9f5f8d2 | |
Thomas Schmitt | 1338f29d62 | |
Thomas Schmitt | bc5e2227c8 | |
Thomas Schmitt | 654ff82345 | |
Thomas Schmitt | 6baeae70e0 | |
Thomas Schmitt | b987972660 | |
Thomas Schmitt | c78526abce | |
Thomas Schmitt | b95e1bb85c | |
Thomas Schmitt | 7aa2582129 | |
Thomas Schmitt | 3f29d70aba | |
Thomas Schmitt | 567d3ddafb | |
Thomas Schmitt | c47f85c639 | |
Thomas Schmitt | 40310b4fd7 | |
Thomas Schmitt | f34c274f21 |
|
@ -1,7 +1,9 @@
|
|||
Vreixo Formoso <metalpain2002@yahoo.es>,
|
||||
Mario Danic <mario.danic@gmail.com>,
|
||||
Vladimir Serbinenko <phcoder@gmail.com>
|
||||
Thomas Schmitt <scdbackup@gmx.net>
|
||||
Copyright (C) 2007-2011 Vreixo Formoso, Mario Danic, Thomas Schmitt
|
||||
Copyright (C) 2007-2018
|
||||
Vreixo Formoso, Mario Danic, Vladimir Serbinenko, Thomas Schmitt
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
|
215
ChangeLog
215
ChangeLog
|
@ -1,3 +1,218 @@
|
|||
git clone git@dev.lovelyhq.com:libburnia/libisofs.git
|
||||
(to become libisofs-1.5.8 or higher)
|
||||
===============================================================================
|
||||
- no novelties yet -
|
||||
|
||||
libisofs-1.5.6.pl01.tar.gz Fri Jun 09 2023
|
||||
===============================================================================
|
||||
* Bug fix: On non-GNU/Linux systems ssize_t was not defined in rockridge.h .
|
||||
Report and fix proposal by Rui Chen
|
||||
|
||||
libisofs-1.5.6.tar.gz Wed Jun 07 2023
|
||||
===============================================================================
|
||||
* Bug fix: iso_write_opts_set_part_like_isohybrid() did not cause a MBR
|
||||
partition table if the partitions are data files in the ISO
|
||||
rather than appended
|
||||
* Bug fix: The lseek methods of IsoFileSource for local filesystem and loaded
|
||||
ISO returned libisofs error codes as positive off_t numbers
|
||||
* Bug fix: Freshly cloned data files from imported image were not marked as
|
||||
imported. Thanks to Ivan Shmakov. (Closes: #1022851)
|
||||
* Bug fix: Size of further CE area was calculated wrong if its CE entry ended
|
||||
exactly at a block boundary
|
||||
* New iso_write_opts_set_system_area() option bits 16:
|
||||
GPT "Legacy BIOS bootable" and 17: GPT writable
|
||||
* New API calls iso_assess_written_features(), iso_read_image_feature_named(),
|
||||
iso_read_image_features_text()
|
||||
* Allowed lseekable device files with iso_tree_add_new_cut_out_node().
|
||||
Proof-of-concept by Ivan Shmakov.
|
||||
* New API call iso_write_opts_set_max_ce_entries()
|
||||
|
||||
libisofs-1.5.4.tar.gz Sat Jan 30 2021
|
||||
===============================================================================
|
||||
* Bug fix: Large amounts of AAIP data or many long file names could cause with
|
||||
zisofs an unreadable filesystem after the warning "Calculated and
|
||||
written ECMA-119 tree end differ"
|
||||
* Bug fix: Big-Endian MIPS Volume Header boot file size was rounded up to
|
||||
full 2048. Thanks René Rebe.
|
||||
* Bug fix: El Torito production failed if no catalog path is given and the
|
||||
first boot image path contains no slash
|
||||
* Bug fix: zisofs production was wrong on big-endian machines
|
||||
* Bug fix: Apple Partition Map entries wrote uninitialized data
|
||||
* Bug fix: Appended APM partitions without HFS+ production had start and size 1
|
||||
* Switched to usage of libjte-2.0.0
|
||||
* Implemented production and reading of zisofs2 for files larger than 4 GiB - 1.
|
||||
* New struct iso_zisofs_ctrl version 2
|
||||
* New API call iso_stream_get_zisofs_par()
|
||||
* New API call iso_stream_zisofs_discard_bpt()
|
||||
* New API call iso_image_zisofs_discard_bpt()
|
||||
* New flag bits 8 to 15 in API call iso_node_zf_by_magic()
|
||||
* New API call iso_zisofs_ctrl_susp_z2()
|
||||
* New API call iso_read_opts_set_joliet_map(), new default joliet_map=stripped
|
||||
* New API calls iso_read_image_features_tree_loaded() and
|
||||
iso_read_image_features_rr_loaded()
|
||||
|
||||
libisofs-1.5.2.tar.gz Sat Oct 26 2019
|
||||
===============================================================================
|
||||
* New API calls iso_write_opts_set_part_type_guid(),
|
||||
iso_write_opts_set_iso_type_guid()
|
||||
* New API call iso_nowtime()
|
||||
* New flag bit2 of iso_node_set_acl_text() to be verbous about failures
|
||||
* Made libisofs ready for building out-of-source. Thanks Ross Burton.
|
||||
* Bug fix: Appended GPT partitions were not covered by the protective MBR
|
||||
partition
|
||||
* Bug fix: Multi-session emulation spoiled GPT production.
|
||||
"GPT partitions ... overlap". Regression towards 1.4.8
|
||||
* Bug fix: Appending partitions 5 to 8 caused damaged ISO filesystems if not
|
||||
for SUN disk label
|
||||
* Bug fix: SIGSEGV happened if options bit 14 of
|
||||
iso_write_opts_set_system_area() is set and no El Torito boot image
|
||||
is defined
|
||||
|
||||
libisofs-1.5.0.tar.gz Sat Sep 15 2018
|
||||
===============================================================================
|
||||
* New API call iso_image_get_ignore_aclea(),
|
||||
new iso_image_set_ignore_aclea() and iso_file_source_get_aa_string()
|
||||
flag bit3 to import all xattr namespaces
|
||||
* New API calls iso_image_was_blind_attrs(), iso_local_set_attrs_errno().
|
||||
* New flag bit7 with iso_local_set_attrs() to avoid unnecessary write attempts.
|
||||
* New return value 2 of IsoFileSource.get_aa_string() and iso_local_get_attrs().
|
||||
* Now putting user defined padding after appended partitions.
|
||||
* Bug fix: Add-on sessions with partition offset claimed too many blocks as
|
||||
size. Regression of version 1.4.8.
|
||||
* Bug fix: Long Joliet names without dot were mangled with one character too
|
||||
many. Long Joliet names with leading dot were mangled one char
|
||||
too short.
|
||||
* Bug fix: Reading beyond array end for HFS+ production caused SIGSEGV with
|
||||
FreeBSD 11 CLANG -O2. Thanks ASX of GhostBSD.
|
||||
|
||||
libisofs-1.4.8.tar.gz Tue Sep 12 2017
|
||||
===============================================================================
|
||||
* Bug fix: iso_read_opts_set_no_rockridge() did not prevent reading of root
|
||||
SUSP.
|
||||
* Bug fix: Non-SUSP data in System Use Area prevented image loading if
|
||||
Rock Ridge was enabled. Thanks to Jonathan Dowland.
|
||||
* Bug fix: Protective MBR for GPT could emerge with boot flag set.
|
||||
* Bug fix: Appended partitions of size >= 4 GiB led to abort with error message
|
||||
"FATAL : ISO overwrite". Thanks to Sven Haardiek.
|
||||
* Bug fix: Bit 15 of iso_write_opts_set_system_area did not work with generic
|
||||
MBR.
|
||||
* Bug fix: Keeping and patching of loaded boot images failed.
|
||||
Regression by version 1.4.4.
|
||||
* Bug fix: Program crashes by intentionally wrong ISO image input.
|
||||
Found by American Fuzzy Lop and Jakub Wilk.
|
||||
Debian bug reports: 872372, 872475, 872545, 872590, 872761.
|
||||
* New API calls el_torito_set_full_load(), el_torito_get_full_load().
|
||||
* New API call iso_write_opts_set_iso_mbr_part_type().
|
||||
|
||||
|
||||
libisofs-1.4.6.tar.gz Fri Sep 16 2016
|
||||
===============================================================================
|
||||
* Bug fix: SIGSEGV by NULL when a data file was larger than ISO level allows.
|
||||
* Bug fix: Interpretation of 17 digit timestamps was wrong.
|
||||
* New API calls iso_generate_gpt_guid() and iso_write_opts_set_gpt_guid().
|
||||
* Made several pseudo-random ids reproducible by overriding volume modification
|
||||
time.
|
||||
|
||||
libisofs-1.4.4.tar.gz Fri Jul 01 2016
|
||||
===============================================================================
|
||||
* Bug fix: HFS+ production could cause MBR partition of type 0xEE without GPT.
|
||||
* Bug fix: Protective MBR was not produced if no System Area data are given.
|
||||
* Bug fix: Protective MBR was not recognized if partition is appended.
|
||||
* Bug fix: The HFS+ filesystem was not marked in GPT of GRUB2 hybrid layout.
|
||||
* Bug fix: HFS+ directories could announce more children than they actually
|
||||
have.
|
||||
* Bug fix: At image loading time GRUB2 MBR was not recognized if the partition
|
||||
table is not the protective one as described by UEFI.
|
||||
* Bug fix: Oversized text in ISO_SYSAREA_REPORT_DOC_ALPHA.
|
||||
Thanks to Etienne Bergeron.
|
||||
* New pseudo path for El Torito boot images:
|
||||
--interval:appened_partition_N:all::
|
||||
* New bit15 with options of iso_write_opts_set_system_area() to enforce
|
||||
MBR bootable/active flag.
|
||||
* New API calls iso_write_opts_set_appended_as_apm(),
|
||||
iso_write_opts_set_part_like_isohybrid().
|
||||
* Introduced image size tolerance of 300 kB in order to recognize SUN Disk
|
||||
Label that was generated by genisoimage -B "...".
|
||||
* Added "extern C" to libisofs.h
|
||||
* Removed option --silent from libtool runs.
|
||||
|
||||
libisofs-1.4.2.tar.gz Sat Nov 28 2015
|
||||
===============================================================================
|
||||
* Bug fix: zisofs compression caused SIGSEGV (by reading) with files larger
|
||||
than 524160 KiB.
|
||||
* Bug fix: iso_node_get_name() of root node returned NULL pointer rather than
|
||||
an empty string
|
||||
* Bug fix: Names read from Joliet tree where stripped of trailing ";1"
|
||||
* Now sorting the data file content extents by ECMA-119 tree, rather than
|
||||
by the red-black tree which shall consolidate files with identical
|
||||
source object.
|
||||
* New API call iso_read_opts_set_ecma119_map().
|
||||
* New AAIP variable isofs.nt records name truncation parameters.
|
||||
* Rectified handling of oversized filenames by new API calls:
|
||||
iso_image_set_truncate_mode, iso_image_get_truncate_mode,
|
||||
iso_truncate_leaf_name, iso_image_set_node_name, iso_image_tree_clone,
|
||||
iso_image_add_new_dir, iso_image_add_new_file, iso_image_add_new_special,
|
||||
iso_image_add_new_symlink, iso_image_dir_get_node, iso_image_path_to_node
|
||||
* Result of a Coverity audit: 50+ code changes, but no easy-to-trigger bugs
|
||||
|
||||
libisofs-1.4.0.tar.gz Sun May 17 2015
|
||||
===============================================================================
|
||||
* Bug fix: iso_image_report_system_area() caused SIGSEGV by NULL if no valid
|
||||
ISO 9660 image was loeaded. Thanks to OmegaPhil.
|
||||
* Bug fix: A SIGSEGV could happen when loading a faulty ISO filesystem.
|
||||
Debian bug 774152. Thanks to Jakub Wilk.
|
||||
* Bug fix: Rock Ridge Continuation Area could be produced crossing a block
|
||||
boundary. This is heavily disliked by the Linux kernel and spoils
|
||||
the representation of directories which contain many symbolic links.
|
||||
* Bug fix: If iso_write_opts_set_hardlinks() enabled automatic inode numbers,
|
||||
then they did not get into effect with nodes were zisofs decoder
|
||||
filters got attached during the image load process.
|
||||
* Bug fix: The header indicator of the last El Torito catalog section header
|
||||
was set to 0x90 rather than 0x91 if more than one boot image is in
|
||||
that section.
|
||||
* Bug fix: Only 128 bytes of an emerging GPT header block were zeroized.
|
||||
* Bug fix: iso_image_report_system_area() did not show GPT partitions of
|
||||
size 0.
|
||||
* Bug fix: A zero sized GPT partition was marked after the last appended
|
||||
GPT partition.
|
||||
* Bug fix: GPT production did not yield proper results with appended sessions
|
||||
or with TOC emulation enabled.
|
||||
* Increased default weight of El Torito boot catalog to 1 billion.
|
||||
* Improved handling of cylinder alignment if the resulting image size is not
|
||||
divisible by 2048. Old behavior was to not align. New is to pad up by a
|
||||
few blocks of 512 bytes.
|
||||
* New API call iso_write_opts_set_appended_as_gpt()
|
||||
and marking of appended partitions in GPT if GPT emerges for other reasons.
|
||||
* New system area type 6 = DEC Alpha SRM boot sector.
|
||||
New API calls iso_image_set_alpha_boot(), iso_image_get_alpha_boot().
|
||||
Thanks to Helge Deller.
|
||||
* New API object iso_interval_reader. Enabling flag bits for older API calls
|
||||
iso_write_opts_set_prep_img(), iso_write_opts_set_efi_bootp(),
|
||||
and iso_write_opts_set_partition_img().
|
||||
|
||||
libisofs-1.3.8.tar.gz Sat Jun 28 2014
|
||||
===============================================================================
|
||||
* Bug fix: Prevent allocation of empty hash tables. Thanks Richard Nolde.
|
||||
* Bug fix: Prevent allocation of empty directory children lists.
|
||||
Thanks Richard Nolde.
|
||||
* Bug fix: The GUIDs of main GPT and backup GPT differed if more than one
|
||||
System Area was written into the ISO image.
|
||||
* New API calls iso_image_report_el_torito() and iso_image_report_system_area()
|
||||
* New API call iso_crc32_gpt()
|
||||
|
||||
libisofs-1.3.6.tar.gz Tue Mar 04 2014
|
||||
===============================================================================
|
||||
* Bug fix: Division by zero if HFS+ was combined with TOC emulation for
|
||||
overwritable media.
|
||||
* New API call iso_write_opts_set_joliet_utf16() and ability to read Joliet
|
||||
names as UTF-16BE
|
||||
* New API call iso_conv_name_chars()
|
||||
|
||||
libisofs-1.3.4.tar.gz Thu Dec 12 2013
|
||||
===============================================================================
|
||||
* Giving sort weight 2 as default to El Torito boot images
|
||||
* Encoding HFS+ names in UTF-16 rather than UCS-2.
|
||||
|
||||
libisofs-1.3.2.tar.gz Wed Aug 07 2013
|
||||
===============================================================================
|
||||
* Bug fix: iso_finish() left an invalid global pointer, which a subsequent
|
||||
|
|
17
Makefile.am
17
Makefile.am
|
@ -1,4 +1,8 @@
|
|||
|
||||
# Copyright (c) 2007 Vreixo Formoso
|
||||
# Copyright (c) 2009 - 2019 Thomas Schmitt
|
||||
# Provided under the terms of the GNU General Public License version 2 or later.
|
||||
|
||||
# ts A90315 : LIBBURNIA_PKGCONFDIR is defined OS specific in acinclude.m4
|
||||
# was: pkgconfigdir=$(libdir)/pkgconfig
|
||||
pkgconfigdir=$(LIBBURNIA_PKGCONFDIR)
|
||||
|
@ -8,12 +12,15 @@ libincludedir=$(includedir)/libisofs
|
|||
lib_LTLIBRARIES = libisofs/libisofs.la
|
||||
ACLOCAL_AMFLAGS = -I ./
|
||||
|
||||
# Enable this if the source includes generated files like version.h
|
||||
# AM_CPPFLAGS = -I $(top_builddir)/libisofs
|
||||
|
||||
## ========================================================================= ##
|
||||
|
||||
# Build libraries
|
||||
|
||||
libisofs_libisofs_la_LDFLAGS = \
|
||||
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
|
||||
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) $(LIBLDFLAGS)
|
||||
|
||||
# Eventually enabling system adapters for ACL and EA.
|
||||
# ts A90409: Eventually enabling use of zlib.
|
||||
|
@ -89,7 +96,7 @@ libinclude_HEADERS = \
|
|||
libisofs/libisofs.h
|
||||
|
||||
install-exec-hook:
|
||||
$(LIBBURNIA_LDCONFIG_CMD) "$(DESTDIR)$(libdir)" || echo 'NOTE: Explicite dynamic library configuration failed. If needed, configure manually for:' "$(DESTDIR)$(libdir)"
|
||||
$(LIBBURNIA_LDCONFIG_CMD) "$(DESTDIR)$(libdir)" || echo 'NOTE: Explicit dynamic library configuration failed. If needed, configure manually for:' "$(DESTDIR)$(libdir)"
|
||||
|
||||
## ========================================================================= ##
|
||||
|
||||
|
@ -113,8 +120,8 @@ noinst_PROGRAMS = \
|
|||
|
||||
|
||||
# ts A90807
|
||||
# Consolidated demo code for having less linker mesages with a make run.
|
||||
demo_demo_CPPFLAGS = -Ilibisofs
|
||||
# Consolidated demo code for having less linker messages with a make run.
|
||||
demo_demo_CPPFLAGS = -I $(top_srcdir)/libisofs
|
||||
demo_demo_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
|
||||
demo_demo_SOURCES = demo/demo.c
|
||||
|
||||
|
@ -278,7 +285,9 @@ EXTRA_DIST = \
|
|||
doc/susp_aaip_2_0.txt \
|
||||
doc/susp_aaip_isofs_names.txt \
|
||||
doc/zisofs_format.txt \
|
||||
doc/zisofs2_format.txt \
|
||||
doc/checksums.txt \
|
||||
doc/boot_sectors.txt \
|
||||
libisofs/libisofs.ver \
|
||||
libisofs/aaip-os-dummy.c \
|
||||
libisofs/aaip-os-linux.c \
|
||||
|
|
26
README
26
README
|
@ -2,9 +2,10 @@
|
|||
libisofs
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Released under GPL (see COPYING file for details).
|
||||
Released under GNU General Public License version 2 or later.
|
||||
See COPYING file for details.
|
||||
|
||||
Copyright (C) 2008 - 2012 Vreixo Formoso,
|
||||
Copyright (C) 2008 - 2023 Vreixo Formoso,
|
||||
Mario Danic,
|
||||
Vladimir Serbinenko,
|
||||
Thomas Schmitt
|
||||
|
@ -14,30 +15,29 @@ libisofs is part of the libburnia project (libburnia-project.org)
|
|||
|
||||
Download, Build and Installation
|
||||
|
||||
libisofs code is mantained in a Bazaar repository at Launchpad
|
||||
(https://launchpad.net/libisofs/). You can download it with:
|
||||
libisofs code is maintained in a git repository at dev.lovelyhq.com
|
||||
(https://dev.lovelyhq.com/libburnia/libisofs). You can download it with:
|
||||
|
||||
$ bzr branch lp:libisofs/for-libisoburn
|
||||
$ git clone https://dev.lovelyhq.com/libburnia/libisofs.git
|
||||
|
||||
Our build system is based on autotools. For preparing the build you will need
|
||||
autotools of at least version 1.7. If you have download the code from the
|
||||
autotools of at least version 1.7. If you have downloaded the code from the
|
||||
repository, first of all you need to execute
|
||||
|
||||
./autogen.sh
|
||||
./bootstrap
|
||||
|
||||
on toplevel dir to execute autotools.
|
||||
in the toplevel directory ./libisofs, in order to execute autotools.
|
||||
|
||||
Alternatively you may unpack a release tarball for which you do not need
|
||||
autotools installed. For the most recent release of libisofs see:
|
||||
http://libburnia-project.org/wiki/Releases
|
||||
https://dev.lovelyhq.com/libburnia/web/wiki/Releases
|
||||
|
||||
To build libisofs it should be sufficient to go into its toplevel directory
|
||||
and execute
|
||||
To build libisofs go into its toplevel directory and execute
|
||||
|
||||
./configure --prefix=/usr
|
||||
make
|
||||
|
||||
To make the libraries accessible for running resp. developing applications
|
||||
To make the libraries accessible for running and developing applications
|
||||
make install
|
||||
|
||||
On GNU/Linux it will try to run program ldconfig with the library installation
|
||||
|
@ -208,5 +208,5 @@ We are firmly committed to allow GPLv2+ now and with future releases.
|
|||
Signed: Mario Danic, Thomas Schmitt
|
||||
Agreement joined later by: Vreixo Formoso
|
||||
|
||||
Public contact: <libburn-hackers@pykix.org>
|
||||
Public contact: <bug-xorriso@gnu.org>
|
||||
|
||||
|
|
33
acinclude.m4
33
acinclude.m4
|
@ -1,7 +1,12 @@
|
|||
|
||||
dnl Copyright (c) 2009 - 2019 Thomas Schmitt
|
||||
dnl Provided under the terms of the GNU General Public License version 2 or later.
|
||||
|
||||
|
||||
AC_DEFUN([LIBBURNIA_SET_FLAGS],
|
||||
[
|
||||
case $target_os in
|
||||
freebsd*)
|
||||
freebsd* | netbsd*)
|
||||
LDFLAGS="$LDFLAGS -L/usr/local/lib"
|
||||
CPPFLAGS="$CPPFLAGS -I/usr/local/include"
|
||||
;;
|
||||
|
@ -16,15 +21,21 @@ AC_DEFUN([TARGET_SHIZZLE],
|
|||
|
||||
AC_MSG_CHECKING([target operating system])
|
||||
|
||||
LIBBURNIA_SUPP_ACL=none
|
||||
LIBBURNIA_SUPP_FATTR=none
|
||||
LIBBURNIA_LDCONFIG_CMD="echo 'No ldconfig run performed. If needed, configure manually for:'"
|
||||
case $target in
|
||||
*-*-linux*)
|
||||
ARCH=linux
|
||||
LIBBURN_ARCH_LIBS=
|
||||
LIBBURNIA_SUPP_ACL=libacl
|
||||
LIBBURNIA_SUPP_FATTR=xattr
|
||||
LIBBURNIA_LDCONFIG_CMD=ldconfig
|
||||
;;
|
||||
*-*-freebsd*)
|
||||
ARCH=freebsd
|
||||
LIBBURNIA_SUPP_ACL=libacl
|
||||
LIBBURNIA_SUPP_FATTR=extattr
|
||||
LIBBURN_ARCH_LIBS=-lcam
|
||||
|
||||
# This may later be overridden by configure --enable-libdir-pkgconfig
|
||||
|
@ -138,13 +149,15 @@ dnl It tests whether -Wl,--version-script=... works with the compiler
|
|||
AC_DEFUN([LIBISOFS_ASSERT_VERS_LIBS],
|
||||
[
|
||||
libburnia_save_LDFLAGS="$LDFLAGS"
|
||||
LDFLAGS="$LDFLAGS -Wl,--version-script=libisofs/libisofs.ver"
|
||||
LDFLAGS="$LDFLAGS -Wl,--version-script=$srcdir/libisofs/libisofs.ver"
|
||||
AC_TRY_LINK([#include <stdio.h>], [printf("Hello\n");],
|
||||
[vers_libs_test="yes"], [vers_libs_test="no"])
|
||||
if test x$vers_libs_test = xno
|
||||
if test x$vers_libs_test = xyes
|
||||
then
|
||||
LDFLAGS="$libburnia_save_LDFLAGS"
|
||||
LIBLDFLAGS="-Wl,--version-script=$srcdir/libisofs/libisofs.ver"
|
||||
fi
|
||||
LDFLAGS="$libburnia_save_LDFLAGS"
|
||||
AC_SUBST(LIBLDFLAGS)
|
||||
])
|
||||
|
||||
|
||||
|
@ -198,3 +211,15 @@ dnl For debugging only
|
|||
|
||||
])
|
||||
|
||||
dnl LIBBURNIA_TRY_TIMEZONE is by Thomas Schmitt, libburnia project
|
||||
dnl It tests whether the global variable exists and is suitable for
|
||||
dnl integer arithmetics.
|
||||
AC_DEFUN([LIBBURNIA_TRY_TIMEZONE],
|
||||
[
|
||||
echo -n "checking for timezone variable ... "
|
||||
AC_TRY_LINK([ #include <time.h> ], [long int i; i = 1 - timezone; ],
|
||||
[LIBBURNIA_TIMEZONE="timezone"], [LIBBURNIA_TIMEZONE="0"]
|
||||
)
|
||||
echo "$LIBBURNIA_TIMEZONE"
|
||||
])
|
||||
|
||||
|
|
160
configure.ac
160
configure.ac
|
@ -1,4 +1,4 @@
|
|||
AC_INIT([libisofs], [1.3.2], [http://libburnia-project.org])
|
||||
AC_INIT([libisofs], [1.5.7], [http://libburnia-project.org])
|
||||
AC_PREREQ([2.50])
|
||||
dnl AC_CONFIG_HEADER([config.h])
|
||||
|
||||
|
@ -26,8 +26,8 @@ dnl
|
|||
dnl LT_CURRENT, LT_REVISION and LT_AGE get set directly now.
|
||||
dnl
|
||||
dnl SONAME of the emerging library is LT_CURRENT - LT_AGE.
|
||||
dnl The linker will do no finer checks. Especially no age range check for
|
||||
dnl the cdrskin binary. If SONAME matches, then the couple starts.
|
||||
dnl The linker will do no finer checks. If SONAME matches, then the couple
|
||||
dnl starts.
|
||||
dnl
|
||||
dnl Therefore a run time check is provided by libisofs function
|
||||
dnl iso_lib_version(). It returns the major, minor and micro revision of the
|
||||
|
@ -40,8 +40,8 @@ dnl
|
|||
dnl If LIBISOFS_*_VERSION changes, be sure to change AC_INIT above to match.
|
||||
dnl
|
||||
LIBISOFS_MAJOR_VERSION=1
|
||||
LIBISOFS_MINOR_VERSION=3
|
||||
LIBISOFS_MICRO_VERSION=2
|
||||
LIBISOFS_MINOR_VERSION=5
|
||||
LIBISOFS_MICRO_VERSION=7
|
||||
LIBISOFS_VERSION=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION.$LIBISOFS_MICRO_VERSION
|
||||
|
||||
AC_SUBST(LIBISOFS_MAJOR_VERSION)
|
||||
|
@ -51,10 +51,10 @@ AC_SUBST(LIBISOFS_VERSION)
|
|||
|
||||
dnl Libtool versioning
|
||||
LT_RELEASE=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION
|
||||
# 2013.08.07 development jump has not yet happened
|
||||
# SONAME = 74 - 68 = 6 . Library name = libisofs.6.68.0
|
||||
LT_CURRENT=74
|
||||
LT_AGE=68
|
||||
dnl 2023.05.07 development jump has not yet happened
|
||||
dnl SONAME = 98 - 92 = 6 . Library name = libisofs.6.92.0
|
||||
LT_CURRENT=98
|
||||
LT_AGE=92
|
||||
LT_REVISION=0
|
||||
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
|
||||
|
||||
|
@ -67,12 +67,12 @@ AC_SUBST(LT_CURRENT_MINUS_AGE)
|
|||
AC_PREFIX_DEFAULT([/usr/local])
|
||||
test "$prefix" = "NONE" && prefix=$ac_default_prefix
|
||||
|
||||
AM_MAINTAINER_MODE
|
||||
dnl ts B90405 : Disabled on advise of Ross Burton
|
||||
dnl AM_MAINTAINER_MODE
|
||||
|
||||
AM_PROG_CC_C_O
|
||||
AC_C_CONST
|
||||
AC_C_INLINE
|
||||
AC_C_BIGENDIAN
|
||||
|
||||
dnl Large file support
|
||||
AC_SYS_LARGEFILE
|
||||
|
@ -92,7 +92,7 @@ LIBBURNIA_ASSERT_ICONV
|
|||
|
||||
AC_PROG_LIBTOOL
|
||||
AC_SUBST(LIBTOOL_DEPS)
|
||||
LIBTOOL="$LIBTOOL --silent"
|
||||
# LIBTOOL="$LIBTOOL --silent"
|
||||
|
||||
AC_PROG_INSTALL
|
||||
|
||||
|
@ -114,6 +114,16 @@ AC_CHECK_DECL([timegm],
|
|||
,
|
||||
[#include <time.h>])
|
||||
|
||||
dnl Whether timezone is an integer variable
|
||||
AH_TEMPLATE([Libburnia_timezonE], [Either timezone or 0])
|
||||
LIBBURNIA_TRY_TIMEZONE
|
||||
if test x$LIBBURNIA_TIMEZONE = xtimezone
|
||||
then
|
||||
AC_DEFINE([Libburnia_timezonE], [timezone])
|
||||
else
|
||||
AC_DEFINE([Libburnia_timezonE], [0])
|
||||
fi
|
||||
|
||||
dnl Check if non standard eaccess() function is available
|
||||
AC_CHECK_DECL([eaccess],
|
||||
[AC_DEFINE(HAVE_EACCESS, 1, [Define this if eaccess function is available])],
|
||||
|
@ -140,7 +150,7 @@ if test x$enable_debug != xyes; then
|
|||
CFLAGS="-DNDEBUG $CFLAGS"
|
||||
else
|
||||
if test x$GCC = xyes; then
|
||||
CFLAGS="-g -pedantic -Wall -Wextra -Wno-unused-parameter $CFLAGS"
|
||||
CFLAGS="-g -pedantic -Wall -Wextra -Wno-unused-parameter -Wno-char-subscripts $CFLAGS"
|
||||
fi
|
||||
CFLAGS="-DDEBUG $CFLAGS"
|
||||
fi
|
||||
|
@ -162,40 +172,118 @@ dnl Add compiler-specific flags
|
|||
AC_ARG_ENABLE(libacl,
|
||||
[ --enable-libacl Enable use of ACL functions by libisofs, default=yes],
|
||||
, enable_libacl=yes)
|
||||
if test "x$enable_libacl" = xyes; then
|
||||
LIBACL_DEF=
|
||||
has_acl_h_but_no_func=0
|
||||
if test x$LIBBURNIA_SUPP_ACL = xlibacl
|
||||
then
|
||||
if test x$enable_libacl = xyes; then
|
||||
dnl Check whether there is libacl-devel and libacl-runtime.
|
||||
dnl If not, erase this macro which would enable use of acl_to_text and others
|
||||
LIBACL_DEF="-DLibisofs_with_aaip_acL"
|
||||
LIBACL_DEF="-DLibisofs_with_aaip_acL"
|
||||
dnl The empty yes case obviously causes -lacl to be linked
|
||||
has_acl_h_but_no_func=0
|
||||
AC_CHECK_HEADER(sys/acl.h, AC_CHECK_LIB(acl, acl_to_text, , has_acl_h_but_no_libacl=1 ), LIBACL_DEF= )
|
||||
if test "$has_acl_h_but_no_libacl" = 1
|
||||
AC_CHECK_HEADER(sys/acl.h, AC_CHECK_LIB(acl, acl_to_text, , has_acl_h_but_no_libacl=1 ), LIBACL_DEF= )
|
||||
if test "$has_acl_h_but_no_libacl" = 1
|
||||
then
|
||||
AC_CHECK_LIB(c, acl_to_text, X= , LIBACL_DEF= )
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test x$LIBACL_DEF = x-DLibisofs_with_aaip_acL
|
||||
then
|
||||
if test x$has_acl_h_but_no_libacl = x1
|
||||
then
|
||||
AC_CHECK_LIB(c, acl_to_text, X= , LIBACL_DEF= )
|
||||
fi
|
||||
echo "enabled local processing of ACL"
|
||||
else
|
||||
echo "enabled libacl, local processing of ACL"
|
||||
fi
|
||||
else
|
||||
LIBACL_DEF=
|
||||
echo "disabled local processing of ACL"
|
||||
fi
|
||||
AC_SUBST(LIBACL_DEF)
|
||||
|
||||
|
||||
dnl ts A90123
|
||||
dnl ts A90123 - B80508
|
||||
AC_ARG_ENABLE(xattr,
|
||||
[ --enable-xattr Enable use of xattr by libisofs, default=yes],
|
||||
, enable_xattr=yes)
|
||||
if test "x$enable_xattr" = xyes; then
|
||||
dnl Check whether there is the header for Linux xattr.
|
||||
[ --enable-xattr Enable use of extended file attributes by libisofs, default=yes],
|
||||
, enable_xattr=yes)
|
||||
AC_ARG_ENABLE(xattr_h_pref_attr,
|
||||
[ --enable-xattr-h-pref-attr Prefer include file attr/xattr.h over sys/xattr.h, default=no],
|
||||
, enable_xattr_h_pref_attr=no)
|
||||
|
||||
XATTR_DEF=
|
||||
XATTR_ADDON_DEF=
|
||||
if test x"$LIBBURNIA_SUPP_FATTR" = xxattr
|
||||
then
|
||||
if test "x$enable_xattr" = xyes; then
|
||||
dnl Check whether there is the header for Linux xattr.
|
||||
dnl If not, erase this macro which would enable use of listxattr and others
|
||||
XATTR_DEF="-DLibisofs_with_aaip_xattR"
|
||||
AC_CHECK_HEADER(attr/xattr.h, AC_CHECK_LIB(c, listxattr, X= , XATTR_DEF= ), XATTR_DEF= )
|
||||
if test "x$XATTR_DEF" = x
|
||||
then
|
||||
XATTR_DEF="-DLibisofs_with_freebsd_extattR"
|
||||
AC_CHECK_HEADER(sys/extattr.h, AC_CHECK_LIB(c, extattr_list_file, X=, XATTR_DEF= ), XATTR_DEF= )
|
||||
|
||||
XATTR_A_DEF=
|
||||
XATTR_S_DEF=
|
||||
if test x"$enable_xattr_h_pref_attr" = xyes
|
||||
then
|
||||
echo "prefering include file attr/xattr.h over sys/attr.h"
|
||||
XATTR_A_DEF=1
|
||||
AC_CHECK_HEADER(attr/xattr.h, AC_CHECK_LIB(c, listxattr, X= ,
|
||||
XATTR_A_DEF= ), XATTR_A_DEF= )
|
||||
if test x"$XATTR_A_DEF" = x1
|
||||
then
|
||||
XATTR_DEF="-DLibisofs_with_aaip_xattR"
|
||||
else
|
||||
XATTR_S_DEF=1
|
||||
AC_CHECK_HEADER(sys/xattr.h, AC_CHECK_LIB(c, listxattr, X= ,
|
||||
XATTR_S_DEF= ), XATTR_S_DEF= )
|
||||
if test x"$XATTR_S_DEF" = x1
|
||||
then
|
||||
XATTR_DEF="-DLibisofs_with_aaip_xattR"
|
||||
XATTR_ADDON_DEF="-DLibisofs_with_sys_xattR"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
XATTR_S_DEF=1
|
||||
AC_CHECK_HEADER(sys/xattr.h, AC_CHECK_LIB(c, listxattr, X= ,
|
||||
XATTR_S_DEF= ), XATTR_S_DEF= )
|
||||
if test x"$XATTR_S_DEF" = x1
|
||||
then
|
||||
XATTR_DEF="-DLibisofs_with_aaip_xattR"
|
||||
XATTR_ADDON_DEF="-DLibisofs_with_sys_xattR"
|
||||
else
|
||||
XATTR_A_DEF=1
|
||||
AC_CHECK_HEADER(attr/xattr.h, AC_CHECK_LIB(c, listxattr, X= ,
|
||||
XATTR_A_DEF= ), XATTR_A_DEF= )
|
||||
if test x"$XATTR_A_DEF" = x1
|
||||
then
|
||||
XATTR_DEF="-DLibisofs_with_aaip_xattR"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test x"$XATTR_S_DEF" = x1
|
||||
then
|
||||
echo "decided to include file sys/attr.h"
|
||||
elif test x"$XATTR_A_DEF" = x1
|
||||
then
|
||||
echo "decided to include file attr/xattr.h"
|
||||
fi
|
||||
fi
|
||||
elif test x"$LIBBURNIA_SUPP_FATTR" = xextattr
|
||||
then
|
||||
if test "x$enable_xattr" = xyes; then
|
||||
XATTR_DEF="-DLibisofs_with_freebsd_extattR"
|
||||
AC_CHECK_HEADER(sys/extattr.h, AC_CHECK_LIB(c, extattr_list_file, X=,
|
||||
XATTR_DEF= ), XATTR_DEF= )
|
||||
fi
|
||||
else
|
||||
XATTR_DEF=
|
||||
fi
|
||||
if test x$XATTR_DEF = x-DLibisofs_with_aaip_xattR
|
||||
then
|
||||
echo "enabled xattr, local processing of extended file attributes Linux style"
|
||||
elif test x$XATTR_DEF = x-DLibisofs_with_freebsd_extattR
|
||||
then
|
||||
echo "enabled extattr, local processing of extended file attributes FreeBSD style"
|
||||
else
|
||||
echo "disabled local processing of extended file attributes"
|
||||
fi
|
||||
XATTR_DEF="$XATTR_DEF $XATTR_ADDON_DEF"
|
||||
|
||||
AC_SUBST(XATTR_DEF)
|
||||
|
||||
|
||||
|
@ -218,11 +306,11 @@ AC_SUBST(ZLIB_DEF)
|
|||
|
||||
dnl ts B00927
|
||||
AC_ARG_ENABLE(libjte,
|
||||
[ --enable-libjte Enable use of libjte by libisofs, default=yes],
|
||||
[ --enable-libjte Enable use of libjte >= 2.0 by libisofs, default=yes],
|
||||
, enable_libjte=yes)
|
||||
if test "x$enable_libjte" = xyes; then
|
||||
LIBJTE_DEF="-DLibisofs_with_libjtE"
|
||||
AC_CHECK_HEADER(libjte/libjte.h, AC_CHECK_LIB(jte, libjte_new, , LIBJTE_DEF= ), LIBJTE_DEF= )
|
||||
AC_CHECK_HEADER(libjte/libjte.h, AC_CHECK_LIB(jte, libjte_set_checksum_algorithm, , LIBJTE_DEF= ), LIBJTE_DEF= )
|
||||
else
|
||||
LIBJTE_DEF=
|
||||
fi
|
||||
|
|
313
demo/demo.c
313
demo/demo.c
|
@ -1,6 +1,6 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 2007 - 2009 Vreixo Formoso, Thomas Schmitt
|
||||
* Copyright (c) 2007 - 2016 Vreixo Formoso, Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -24,7 +24,9 @@ static char helptext[][80] = {
|
|||
" Output the contents of an iso image.",
|
||||
" -iso_cat image_file path_in_image",
|
||||
" Extract a file from a given ISO image and put out its content",
|
||||
" to stdout. The file is addressed by path_in_image.",
|
||||
" to stdout. The file is addressed by path_in_image. The ISO",
|
||||
" image does not get loaded but rather the lookups are done",
|
||||
" directly in the image file.",
|
||||
" -iso_modify image_file absolute_directory_path output_file",
|
||||
" Load an iso image, add a directory, and write complete image.",
|
||||
" -iso_ms image_lba nwa image_file directory_path output_file",
|
||||
|
@ -58,6 +60,22 @@ static char helptext[][80] = {
|
|||
#endif
|
||||
|
||||
|
||||
/* ----------------------------- utilities -------------------------- */
|
||||
|
||||
|
||||
void demo_report_iso_err(int err, char *occasion)
|
||||
{
|
||||
char *severity;
|
||||
|
||||
fprintf(stderr, "%s : err = 0x%X", occasion, (unsigned int) err);
|
||||
if (err < 0) {
|
||||
iso_sev_to_text(iso_error_get_severity(err), &severity);
|
||||
fprintf(stderr, " -> %s '%s'", severity, iso_error_to_msg(err));
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------- from demo/tree.c ----------------------- */
|
||||
|
||||
static void
|
||||
|
@ -95,7 +113,8 @@ tree_print_dir(IsoDir *dir, int level)
|
|||
sp[i+1] = ' ';
|
||||
}
|
||||
|
||||
sp[level * 2-1] = '-';
|
||||
if (level > 0)
|
||||
sp[level * 2 - 1] = '-';
|
||||
sp[level * 2] = '\0';
|
||||
|
||||
iso_dir_get_children(dir, &iter);
|
||||
|
@ -356,7 +375,7 @@ int gesture_iso(int argc, char **argv)
|
|||
|
||||
result = iso_write_opts_new(&opts, 0);
|
||||
if (result < 0) {
|
||||
printf ("Cant create write opts, error %d\n", result);
|
||||
printf ("Cannot create write opts, error %d\n", result);
|
||||
goto ex;
|
||||
}
|
||||
iso_write_opts_set_iso_level(opts, level);
|
||||
|
@ -366,7 +385,7 @@ int gesture_iso(int argc, char **argv)
|
|||
|
||||
result = iso_image_create_burn_source(image, opts, &burn_src);
|
||||
if (result < 0) {
|
||||
printf ("Cant create image, error %d\n", result);
|
||||
printf ("Cannot create image, error %d\n", result);
|
||||
goto ex;
|
||||
}
|
||||
|
||||
|
@ -445,7 +464,8 @@ iso_read_print_dir(IsoFileSource *dir, int level)
|
|||
sp[i+1] = ' ';
|
||||
}
|
||||
|
||||
sp[level * 2-1] = '-';
|
||||
if (level > 0)
|
||||
sp[level * 2 - 1] = '-';
|
||||
sp[level * 2] = '\0';
|
||||
|
||||
ret = iso_file_source_open(dir);
|
||||
|
@ -473,37 +493,43 @@ iso_read_print_dir(IsoFileSource *dir, int level)
|
|||
|
||||
int gesture_iso_read(int argc, char **argv)
|
||||
{
|
||||
int result;
|
||||
IsoImageFilesystem *fs;
|
||||
IsoDataSource *src;
|
||||
IsoFileSource *root;
|
||||
IsoReadOpts *ropts;
|
||||
int result, initialized = 0, return_val = 1;
|
||||
IsoImageFilesystem *fs = NULL;
|
||||
IsoDataSource *src = NULL;
|
||||
IsoFileSource *root = NULL;
|
||||
IsoReadOpts *ropts = NULL;
|
||||
|
||||
if (argc != 2) {
|
||||
printf ("You need to specify a valid path\n");
|
||||
return 1;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
iso_init();
|
||||
result = iso_init();
|
||||
if (result < 0) {
|
||||
demo_report_iso_err(result, "Cannot init libisofs");
|
||||
goto ex;
|
||||
}
|
||||
initialized = 1;
|
||||
|
||||
iso_set_msgs_severities("NEVER", "ALL", "");
|
||||
|
||||
result = iso_data_source_new_from_file(argv[1], &src);
|
||||
if (result < 0) {
|
||||
printf ("Error creating data source\n");
|
||||
return 1;
|
||||
demo_report_iso_err(result, "Error creating data source");
|
||||
goto ex;
|
||||
}
|
||||
|
||||
result = iso_read_opts_new(&ropts, 0);
|
||||
if (result < 0) {
|
||||
fprintf(stderr, "Error creating read options\n");
|
||||
return 1;
|
||||
demo_report_iso_err(result, "Error creating read options");
|
||||
goto ex;
|
||||
}
|
||||
result = iso_image_filesystem_new(src, ropts, 1, &fs);
|
||||
iso_read_opts_free(ropts);
|
||||
if (result < 0) {
|
||||
printf ("Error creating filesystem\n");
|
||||
return 1;
|
||||
demo_report_iso_err(result, "Error creating filesystem");
|
||||
goto ex;
|
||||
}
|
||||
iso_read_opts_free(ropts);
|
||||
ropts = NULL;
|
||||
|
||||
printf("\nVOLUME INFORMATION\n");
|
||||
printf("==================\n\n");
|
||||
|
@ -522,18 +548,27 @@ int gesture_iso_read(int argc, char **argv)
|
|||
|
||||
result = fs->get_root(fs, &root);
|
||||
if (result < 0) {
|
||||
printf ("Can't get root %d\n", result);
|
||||
return 1;
|
||||
demo_report_iso_err(result, "Cannot get root object");
|
||||
goto ex;
|
||||
}
|
||||
/* iso_read_print_file_src(root); */
|
||||
iso_read_print_dir(root, 0);
|
||||
iso_file_source_unref(root);
|
||||
|
||||
fs->close(fs);
|
||||
iso_filesystem_unref((IsoFilesystem*)fs);
|
||||
iso_data_source_unref(src);
|
||||
iso_finish();
|
||||
return 0;
|
||||
return_val = 0;
|
||||
ex:;
|
||||
if (root != NULL)
|
||||
iso_file_source_unref(root);
|
||||
if (ropts != NULL)
|
||||
iso_read_opts_free(ropts);
|
||||
if (fs != NULL) {
|
||||
fs->close(fs);
|
||||
iso_filesystem_unref((IsoFilesystem*)fs);
|
||||
}
|
||||
if (src != NULL)
|
||||
iso_data_source_unref(src);
|
||||
if (initialized)
|
||||
iso_finish();
|
||||
return return_val;
|
||||
}
|
||||
|
||||
|
||||
|
@ -542,83 +577,101 @@ int gesture_iso_read(int argc, char **argv)
|
|||
|
||||
int gesture_iso_cat(int argc, char **argv)
|
||||
{
|
||||
int res, write_ret;
|
||||
IsoFilesystem *fs;
|
||||
IsoFileSource *file;
|
||||
int res, write_ret, ret;
|
||||
IsoFilesystem *fs = NULL;
|
||||
IsoFileSource *file = NULL;
|
||||
struct stat info;
|
||||
IsoDataSource *src;
|
||||
IsoReadOpts *opts;
|
||||
IsoDataSource *src = NULL;
|
||||
IsoReadOpts *opts = NULL;
|
||||
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Usage: isocat /path/to/image /path/to/file\n");
|
||||
fprintf(stderr, "Usage: -iso_cat /path/to/image /path/to/file\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
res = iso_init();
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Can't init libisofs\n");
|
||||
demo_report_iso_err(res, "Cannot init libisofs");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Important Note:
|
||||
From here on memory objects get created which need to be freed in
|
||||
the end. Therefore in case of problems no direct return, but rather
|
||||
a hop to label "ex:", where cleanup happens.
|
||||
*/
|
||||
|
||||
res = iso_data_source_new_from_file(argv[1], &src);
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Error creating data source\n");
|
||||
return 1;
|
||||
demo_report_iso_err(res, "Error creating data source object");
|
||||
ret = 1; goto ex;
|
||||
}
|
||||
|
||||
res = iso_read_opts_new(&opts, 0);
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Error creating read options\n");
|
||||
return 1;
|
||||
demo_report_iso_err(res, "Error creating read options object");
|
||||
ret = 1; goto ex;
|
||||
}
|
||||
res = iso_image_filesystem_new(src, opts, 1, &fs);
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Error creating filesystem\n");
|
||||
return 1;
|
||||
demo_report_iso_err(res, "Error creating filesystem object");
|
||||
ret = 1; goto ex;
|
||||
}
|
||||
iso_read_opts_free(opts);
|
||||
opts = NULL;
|
||||
|
||||
res = fs->get_by_path(fs, argv[2], &file);
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Can't get file, err = %d\n", res);
|
||||
return 1;
|
||||
demo_report_iso_err(res, "Cannot get file object with given path");
|
||||
ret = 1; goto ex;
|
||||
}
|
||||
|
||||
res = iso_file_source_lstat(file, &info);
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Can't stat file, err = %d\n", res);
|
||||
return 1;
|
||||
demo_report_iso_err(res,
|
||||
"Cannot inquire type of file object with given path");
|
||||
ret = 1; goto ex;
|
||||
}
|
||||
|
||||
if (S_ISDIR(info.st_mode)) {
|
||||
fprintf(stderr, "Path refers to a directory!!\n");
|
||||
return 1;
|
||||
ret = 1; goto ex;
|
||||
} else {
|
||||
char buf[1024];
|
||||
res = iso_file_source_open(file);
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Can't open file, err = %d\n", res);
|
||||
return 1;
|
||||
demo_report_iso_err(res,
|
||||
"Cannot open file object with given path");
|
||||
ret = 1; goto ex;
|
||||
}
|
||||
while ((res = iso_file_source_read(file, buf, 1024)) > 0) {
|
||||
write_ret = fwrite(buf, 1, res, stdout);
|
||||
if (write_ret < res) {
|
||||
printf ("Cannot write block to stdout. errno= %d\n", errno);
|
||||
return 1;
|
||||
iso_file_source_close(file);
|
||||
ret = 1; goto ex;
|
||||
}
|
||||
}
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Error reading, err = %d\n", res);
|
||||
return 1;
|
||||
}
|
||||
iso_file_source_close(file);
|
||||
if (res < 0) {
|
||||
demo_report_iso_err(res, "Error while reading data content");
|
||||
fprintf(stderr, "Error reading, err = 0x%X\n", (unsigned int) res);
|
||||
ret = 1; goto ex;
|
||||
}
|
||||
}
|
||||
|
||||
iso_file_source_unref(file);
|
||||
iso_filesystem_unref(fs);
|
||||
iso_data_source_unref(src);
|
||||
|
||||
ret = 0;
|
||||
ex:;
|
||||
if (file != NULL)
|
||||
iso_file_source_unref(file);
|
||||
if (fs != NULL)
|
||||
iso_filesystem_unref(fs);
|
||||
if (opts != NULL)
|
||||
iso_read_opts_free(opts);
|
||||
if (src != NULL)
|
||||
iso_data_source_unref(src);
|
||||
iso_finish();
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -632,14 +685,14 @@ void iso_modify_usage(char **argv)
|
|||
|
||||
int gesture_iso_modify(int argc, char **argv)
|
||||
{
|
||||
int result;
|
||||
IsoImage *image;
|
||||
IsoDataSource *src;
|
||||
struct burn_source *burn_src;
|
||||
int result, return_val = 1, initialized = 0;
|
||||
IsoImage *image = NULL;
|
||||
IsoDataSource *src = NULL;
|
||||
struct burn_source *burn_src = NULL;
|
||||
unsigned char buf[2048];
|
||||
FILE *fp = NULL;
|
||||
IsoWriteOpts *opts;
|
||||
IsoReadOpts *ropts;
|
||||
IsoWriteOpts *opts = NULL;
|
||||
IsoReadOpts *ropts = NULL;
|
||||
|
||||
if (argc < 4) {
|
||||
iso_modify_usage(argv);
|
||||
|
@ -652,20 +705,25 @@ int gesture_iso_modify(int argc, char **argv)
|
|||
goto ex;
|
||||
}
|
||||
|
||||
iso_init();
|
||||
result = iso_init();
|
||||
if (result < 0) {
|
||||
demo_report_iso_err(result, "Cannot init libisofs");
|
||||
goto ex;
|
||||
}
|
||||
initialized = 1;
|
||||
iso_set_msgs_severities("NEVER", "ALL", "");
|
||||
|
||||
/* create the data source to accesss previous image */
|
||||
result = iso_data_source_new_from_file(argv[1], &src);
|
||||
if (result < 0) {
|
||||
printf ("Error creating data source\n");
|
||||
demo_report_iso_err(result, "Error creating data source");
|
||||
goto ex;
|
||||
}
|
||||
|
||||
/* create the image context */
|
||||
result = iso_image_new("volume_id", &image);
|
||||
if (result < 0) {
|
||||
printf ("Error creating image\n");
|
||||
demo_report_iso_err(result, "Error creating image");
|
||||
goto ex;
|
||||
}
|
||||
iso_tree_set_follow_symlinks(image, 0);
|
||||
|
@ -674,58 +732,75 @@ int gesture_iso_modify(int argc, char **argv)
|
|||
/* import previous image */
|
||||
result = iso_read_opts_new(&ropts, 0);
|
||||
if (result < 0) {
|
||||
fprintf(stderr, "Error creating read options\n");
|
||||
demo_report_iso_err(result, "Error creating read options");
|
||||
goto ex;
|
||||
}
|
||||
result = iso_image_import(image, src, ropts, NULL);
|
||||
iso_read_opts_free(ropts);
|
||||
iso_data_source_unref(src);
|
||||
if (result < 0) {
|
||||
printf ("Error importing previous session %d\n", result);
|
||||
demo_report_iso_err(result, "Error importing previous session");
|
||||
goto ex;
|
||||
}
|
||||
/* (One could of course keep them alive until cleanup) */
|
||||
iso_read_opts_free(ropts);
|
||||
ropts = NULL;
|
||||
iso_data_source_unref(src);
|
||||
src = NULL;
|
||||
|
||||
/* add new dir */
|
||||
result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[2]);
|
||||
if (result < 0) {
|
||||
printf ("Error adding directory %d\n", result);
|
||||
demo_report_iso_err(result, "Error adding directory");
|
||||
goto ex;
|
||||
}
|
||||
|
||||
/* generate a new image with both previous and added contents */
|
||||
/* Generate a new image with both previous and added contents.
|
||||
Profile 1 means Rock Ridge and ISO level 3.
|
||||
*/
|
||||
result = iso_write_opts_new(&opts, 1);
|
||||
if (result < 0) {
|
||||
printf("Cant create write opts, error %d\n", result);
|
||||
demo_report_iso_err(result, "Cannot create write opts");
|
||||
goto ex;
|
||||
}
|
||||
/* for isolinux: iso_write_opts_set_allow_full_ascii(opts, 1); */
|
||||
|
||||
/* Prefer specs violation over relocation deep directories */
|
||||
iso_write_opts_set_allow_deep_paths(opts, 1);
|
||||
|
||||
/* For MS-Windows readers : iso_write_opts_set_joliet(opts, 1); */
|
||||
|
||||
result = iso_image_create_burn_source(image, opts, &burn_src);
|
||||
if (result < 0) {
|
||||
printf ("Cant create image, error %d\n", result);
|
||||
demo_report_iso_err(result, "Cannot create image object");
|
||||
goto ex;
|
||||
}
|
||||
|
||||
iso_write_opts_free(opts);
|
||||
opts = NULL;
|
||||
|
||||
while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
|
||||
result = fwrite(buf, 1, 2048, fp);
|
||||
if (result < 2048) {
|
||||
printf ("Cannot write block. errno= %d\n", errno);
|
||||
fprintf (stderr, "Cannot write block. errno= %d\n", errno);
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
burn_src->free_data(burn_src);
|
||||
free(burn_src);
|
||||
|
||||
iso_image_unref(image);
|
||||
iso_finish();
|
||||
return 0;
|
||||
|
||||
return_val = 0;
|
||||
ex:
|
||||
if (fp != NULL)
|
||||
fclose(fp);
|
||||
return 1;
|
||||
if (opts != NULL)
|
||||
iso_write_opts_free(opts);
|
||||
if (burn_src != NULL) {
|
||||
burn_src->free_data(burn_src);
|
||||
free(burn_src);
|
||||
}
|
||||
if (image != NULL)
|
||||
iso_image_unref(image);
|
||||
if (ropts != NULL)
|
||||
iso_read_opts_free(ropts);
|
||||
if (src != NULL)
|
||||
iso_data_source_unref(src);
|
||||
if (initialized)
|
||||
iso_finish();
|
||||
return return_val;
|
||||
}
|
||||
|
||||
|
||||
|
@ -739,14 +814,14 @@ void iso_ms_usage(char **argv)
|
|||
|
||||
int gesture_iso_ms(int argc, char **argv)
|
||||
{
|
||||
int result;
|
||||
IsoImage *image;
|
||||
IsoDataSource *src;
|
||||
struct burn_source *burn_src;
|
||||
int result, return_val = 1, initialized = 0;
|
||||
IsoImage *image = NULL;
|
||||
IsoDataSource *src = NULL;
|
||||
struct burn_source *burn_src = NULL;
|
||||
unsigned char buf[2048];
|
||||
FILE *fp = NULL;
|
||||
IsoWriteOpts *opts;
|
||||
IsoReadOpts *ropts;
|
||||
IsoWriteOpts *opts = NULL;
|
||||
IsoReadOpts *ropts = NULL;
|
||||
uint32_t ms_block;
|
||||
|
||||
if (argc < 6) {
|
||||
|
@ -766,20 +841,26 @@ int gesture_iso_ms(int argc, char **argv)
|
|||
goto ex;
|
||||
}
|
||||
|
||||
iso_init();
|
||||
result = iso_init();
|
||||
if (result < 0) {
|
||||
demo_report_iso_err(result, "Cannot init libisofs");
|
||||
goto ex;
|
||||
}
|
||||
initialized = 1;
|
||||
|
||||
iso_set_msgs_severities("NEVER", "ALL", "");
|
||||
|
||||
/* create the data source to accesss previous image */
|
||||
result = iso_data_source_new_from_file(argv[3], &src);
|
||||
if (result < 0) {
|
||||
printf ("Error creating data source\n");
|
||||
demo_report_iso_err(result, "Error creating data source");
|
||||
goto ex;
|
||||
}
|
||||
|
||||
/* create the image context */
|
||||
result = iso_image_new("volume_id", &image);
|
||||
if (result < 0) {
|
||||
printf ("Error creating image\n");
|
||||
demo_report_iso_err(result, "Error creating image");
|
||||
goto ex;
|
||||
}
|
||||
iso_tree_set_follow_symlinks(image, 0);
|
||||
|
@ -794,23 +875,25 @@ int gesture_iso_ms(int argc, char **argv)
|
|||
iso_read_opts_set_start_block(ropts, atoi(argv[1]));
|
||||
result = iso_image_import(image, src, ropts, NULL);
|
||||
iso_read_opts_free(ropts);
|
||||
ropts = NULL;
|
||||
iso_data_source_unref(src);
|
||||
src = NULL;
|
||||
if (result < 0) {
|
||||
printf ("Error importing previous session %d\n", result);
|
||||
demo_report_iso_err(result, "Error importing previous session");
|
||||
goto ex;
|
||||
}
|
||||
|
||||
/* add new dir */
|
||||
result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[4]);
|
||||
if (result < 0) {
|
||||
printf ("Error adding directory %d\n", result);
|
||||
demo_report_iso_err(result, "Error adding directory");
|
||||
goto ex;
|
||||
}
|
||||
|
||||
/* generate a multisession image with new contents */
|
||||
result = iso_write_opts_new(&opts, 1);
|
||||
if (result < 0) {
|
||||
printf("Cant create write opts, error %d\n", result);
|
||||
demo_report_iso_err(result, "Cannot create write opts");
|
||||
goto ex;
|
||||
}
|
||||
|
||||
|
@ -821,10 +904,11 @@ int gesture_iso_ms(int argc, char **argv)
|
|||
|
||||
result = iso_image_create_burn_source(image, opts, &burn_src);
|
||||
if (result < 0) {
|
||||
printf ("Cant create image, error %d\n", result);
|
||||
printf ("Cannot create image, error %d\n", result);
|
||||
goto ex;
|
||||
}
|
||||
iso_write_opts_free(opts);
|
||||
opts = NULL;
|
||||
|
||||
while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
|
||||
result = fwrite(buf, 1, 2048, fp);
|
||||
|
@ -833,17 +917,26 @@ int gesture_iso_ms(int argc, char **argv)
|
|||
goto ex;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
burn_src->free_data(burn_src);
|
||||
free(burn_src);
|
||||
|
||||
iso_image_unref(image);
|
||||
iso_finish();
|
||||
return 0;
|
||||
|
||||
return_val = 0;
|
||||
ex:;
|
||||
if (burn_src != NULL) {
|
||||
burn_src->free_data(burn_src);
|
||||
free(burn_src);
|
||||
}
|
||||
if (opts != NULL)
|
||||
iso_write_opts_free(opts);
|
||||
if (image)
|
||||
iso_image_unref(image);
|
||||
if (ropts != NULL)
|
||||
iso_read_opts_free(ropts);
|
||||
if (src != NULL)
|
||||
iso_data_source_unref(src);
|
||||
if (initialized)
|
||||
iso_finish();
|
||||
if (fp != NULL)
|
||||
fclose(fp);
|
||||
return 1;
|
||||
return return_val;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
Collection of Boot Sector Formats for ISO 9660 Images
|
||||
|
||||
|
||||
by Thomas Schmitt - mailto:scdbackup@gmx.net
|
||||
Libburnia project - mailto:libburn-hackers@pykix.org
|
||||
by Thomas Schmitt - scdbackup@gmx.net
|
||||
Libburnia project - bug-xorriso@gnu.org
|
||||
pkg-libburnia-devel@lists.alioth.debian.org
|
||||
|
||||
This information is collected from various sources. Some is backed by
|
||||
specifications, some is just rumor which happens to work (maybe not even that).
|
||||
|
@ -15,6 +16,8 @@ specifications, some is just rumor which happens to work (maybe not even that).
|
|||
|
||||
EL Torito CD booting, for PC-BIOS x86, PowerPC, (old) Mac, EFI.
|
||||
|
||||
Boot Info Table and GRUB2 Boot Info
|
||||
|
||||
Master Boot Record (MBR), for PC-BIOS x86 from (pseudo-) hard disk
|
||||
|
||||
Apple Partition Map (APM), for more modern Mac
|
||||
|
@ -26,11 +29,17 @@ MIPS Volume Header, for MIPS Big Endian, e.g. SGI Indigo2.
|
|||
DEC Boot Block, for MIPS Little Endian , e.g. DECstation.
|
||||
|
||||
SUN Disk Label and boot images, for SUN SPARC
|
||||
GRUB2 SUN SPARC Core File Address
|
||||
|
||||
PowerPC Reference Platform (PReP), for IBM PowerPC
|
||||
|
||||
Common Hardware Reference Platform (CHRP), for IBM PowerPC
|
||||
|
||||
HP-PA via PALO header version 4
|
||||
HP-PA via PALO header version 5
|
||||
|
||||
DEC Alpha SRM boot sector, for Alpha architecture
|
||||
|
||||
Combinations of boot mechanisms:
|
||||
- SYSLINUX isohybrid MBR
|
||||
- SYSLINUX isohybrid for MBR, UEFI and x86-Mac
|
||||
|
@ -48,7 +57,7 @@ Sources:
|
|||
El Torito, Bootable CD-ROM Format Specification, Version 1.0, 1995
|
||||
which refers to ECMA-119, the standard for ISO 9660 filesystems.
|
||||
libisofs/eltorito.[ch] by Vreixo Formoso.
|
||||
man mkisofs by Joerg Schilling.
|
||||
http://www.uefi.org/sites/default/files/resources/2_4_Errata_B.pdf
|
||||
|
||||
|
||||
ECMA-119 prescribes that the first 32 kB of an ISO 9660 image are System Area
|
||||
|
@ -62,9 +71,9 @@ intervals for:
|
|||
- Directory trees, tables, boot catalog, embedded partitions and filesystems.
|
||||
- Data file content, including content of El Torito boot images.
|
||||
|
||||
The Boot Record is an ECMA-119 Volume Descriptor which is eventually located
|
||||
at 2 kB block number 17 (decimal). Its content points to the location of the
|
||||
Boot Catalog.
|
||||
The Boot Record is an ECMA-119 Volume Descriptor which is located at 2 kB block
|
||||
number 17 (decimal), if present at all. Its content points to the location of
|
||||
the Boot Catalog.
|
||||
The format is described in part by ECMA-119 8.2 "Boot Record" and further
|
||||
specified by El Torito figure 7.
|
||||
|
||||
|
@ -114,16 +123,16 @@ Optional:
|
|||
| | Entries
|
||||
---------- | ---------- | ----------------------------------------------------
|
||||
|
||||
An architecture is refered by a Platform Id number.
|
||||
An architecture is referred by a Platform Id number.
|
||||
Defined by El Torito are:
|
||||
0 = "80x86" which is used for standard PCs with Intel x86 or compatible CPU
|
||||
1 = "PowerPC" (possibly for IBM machines with PowerPC CPU)
|
||||
2 = "Mac" (possibly for Apple computers with MC68000 or PowerPC CPU)
|
||||
Further in use by GRUB2 and ISOLINUX is:
|
||||
0xef = EFI, a competitor resp. successor to PC-BIOS, possibly in use with
|
||||
Intel ia64 Itanium and possibly with newer Apple machines.
|
||||
UEFI 2.4 specifies in 12.3.2.1 "ISO-9660 and El Torito":
|
||||
0xef = EFI, a competitor and successor to PC-BIOS, further in use with
|
||||
Intel ia64 Itanium and newer Apple machines.
|
||||
|
||||
Words resp. numbers are represented are little-endian.
|
||||
Words and numbers are represented as little-endian.
|
||||
|
||||
Validation Entry:
|
||||
|
||||
|
@ -171,7 +180,7 @@ Byte Range | Value | Meaning
|
|||
| |
|
||||
5 - 5 | 0 | Unused
|
||||
| |
|
||||
6 - 7 | sec_count | Sector Count.
|
||||
6 - 7 | sec_count | Sector Count. Sector size 512:
|
||||
| | "the number of virtual/emulated sectors the system
|
||||
| | will store at Load Segment during the initial boot
|
||||
| | procedure."
|
||||
|
@ -226,7 +235,7 @@ Byte Range | Value | Meaning
|
|||
| | 0 if not emulation == 4.
|
||||
5 - 5 | 0 | Unused
|
||||
| |
|
||||
6 - 7 | sec_count | Sector Count.
|
||||
6 - 7 | sec_count | Sector Count. Sector size 512.
|
||||
| | See above Initial/Default Entry
|
||||
| | libisofs stores 1 for emulated boot_media and a
|
||||
| | user defined value for boot_media == 0. Often: 4.
|
||||
|
@ -237,10 +246,22 @@ Byte Range | Value | Meaning
|
|||
12 - 31 | sel_crit | "Vendor unique selection criteria."
|
||||
---------- | ---------- | ----------------------------------------------------
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Boot Info Table and GRUB2 Boot Info
|
||||
|
||||
Sources:
|
||||
man mkisofs by Joerg Schilling
|
||||
Mail conversations with Vladimir Serbinenko.
|
||||
|
||||
|
||||
The boot image file content is mostly opaque to the ISO 9660 image generator.
|
||||
Nevertheless there is a tradition named "Boot Info Table" which prescribes
|
||||
to write information into byte fields of the boot image file content.
|
||||
Recent versions of GRUB2 expect a similar patching which has no name yet.
|
||||
For now let's call it "GRUB2 Boot Info"
|
||||
|
||||
There are no general means known how a producer of ISO 9660 images could
|
||||
detect the need for Boot Info Table production.
|
||||
It rather needs a hint from the user who has to know whether the boot image
|
||||
|
@ -249,19 +270,31 @@ The Boot Info Table begins at byte 8 of the boot image content.
|
|||
|
||||
Byte Range | Value | Meaning
|
||||
---------- | ---------- | ----------------------------------------------------
|
||||
8 - 11 | pvd_lba | Block address of the Primary Volume Descriptor
|
||||
8 - 11 | pvd_lba | Block address of the Primary Volume Descriptor.
|
||||
| | This is the session start LBA + 16.
|
||||
| |
|
||||
12 - 15 | file_lba | Block address of the start of the boot image file
|
||||
| | content.
|
||||
| | content. Block size is 2048.
|
||||
| |
|
||||
16 - 19 | file_len | Number of bytes in boot image file content.
|
||||
| |
|
||||
20 - 23 | checksum | Little-endian: The sum of all 32-bit words of the
|
||||
| | file content from byte 64 to file end.
|
||||
20 - 23 | checksum | The sum of all 32-bit words of the file content
|
||||
| | from byte 64 to file end.
|
||||
| |
|
||||
24 - 63 | 0 | Reserved
|
||||
---------- | ---------- | ----------------------------------------------------
|
||||
All numbers are stored little-endian.
|
||||
|
||||
GRUB2 Boot Info represents a particular block address inside the boot image.
|
||||
It may well be combined with Boot Info Table. See GRUB2 script grub-mkrescue
|
||||
use of xorrisofs options -boot-info-table and --grub2-boot-info.
|
||||
|
||||
Byte Range | Value | Meaning
|
||||
---------- | ---------- | ----------------------------------------------------
|
||||
2548 -2555 | grub2_adr | Block address of the start of the boot image file
|
||||
| | content plus 5. Block size is 512.
|
||||
| | 64 bit Little-endian.
|
||||
---------- | ---------- | ----------------------------------------------------
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
@ -271,28 +304,44 @@ Byte Range | Value | Meaning
|
|||
|
||||
Sources:
|
||||
http://en.wikipedia.org/wiki/Master_boot_record
|
||||
https://en.wikipedia.org/wiki/INT_13H
|
||||
Mailing list conversations with H. Peter Anvin and Vladimir Serbinenko.
|
||||
Mail conversations with Natalia Portillo.
|
||||
|
||||
|
||||
The candidates for MBR booting will normally use El Torito rather than MBR
|
||||
if the ISO image is presented on CD, DVD, or BD media.
|
||||
The eventual MBR comes into effect if the image is on a media that is
|
||||
interpreted by the BIOS as some kind of hard disk. Usually real hard disks,
|
||||
floppy disks, USB sticks, memory cards.
|
||||
The MBR comes into effect if the image is on a media that is interpreted by
|
||||
the BIOS as some kind of hard disk. Usually real hard disks, floppy disks,
|
||||
USB sticks, memory cards.
|
||||
|
||||
An important part of an MBR is the DOS style partition table. It describes up
|
||||
to four primary partitions. There are two formats used for block address:
|
||||
Cylinder/Head/Sector (C/H/S) and Logical Block Address (LBA). Both are based
|
||||
on units of 512 bytes. So MBR_LBA = ISO_LBA * 4.
|
||||
|
||||
Contemporary x86 BIOS normally supports LBA addressing directly.
|
||||
If INT 0x13 AH 0x41 returns with CX bit0 set, then INT 0x13 AH 0x42 may be used
|
||||
for reading. (Sometimes even if the bit is not set to indicate the capability.)
|
||||
|
||||
For C/H/S, the sector address is broken up into whole cylinders, remaining
|
||||
heads, and remaining sectors + 1. The nomenclature seems to stem from antique
|
||||
drum storage.
|
||||
There are two parameters, sectors_per_head and heads_per_cylinder which are not
|
||||
stored in the MBR. So it is more or less arbitray how to convert a LBA into
|
||||
a C/H/S address and vice versa. For maximum range of C/H/S addresses one
|
||||
may use sectors_per_head = 63 , heads_per_cylinder = 255.
|
||||
stored in the MBR. So at ISO production time it is more or less arbitrary how
|
||||
to convert a LBA into a C/H/S address and vice versa.
|
||||
At boot time the x86 BIOS decides about the two parameters. The boot loader may
|
||||
inquire these values by INT 0x13 AH 0x08 and use them to convert LBA to C/H/S
|
||||
for the read operation INT 0x13 AH 0x02. So the C/H/S values in an ISO's
|
||||
partition table are quite fictional and of few impact on boot loaders.
|
||||
|
||||
More important seems to align partition ends to a consistent cylinder size,
|
||||
because some partition editors deduce their idea of disk geometry from there
|
||||
and raise protest if they deem it inconsistent.
|
||||
For maximum range of C/H/S addresses one may use sectors_per_head = 63 ,
|
||||
heads_per_cylinder = 255. But that is not divisible by 4 and imposes alignment
|
||||
problems with ISO 9660 filesystems. So (32,64) for images up to 1 GiB
|
||||
or (63,252) for larger images are better.
|
||||
|
||||
Words are composed little-endian style.
|
||||
|
||||
|
@ -301,8 +350,9 @@ Byte Range | Value | Meaning
|
|||
0 - 439 | = opaque = | Code Area filled with bytes for some boot system,
|
||||
| | typically machine code.
|
||||
| |
|
||||
440 - 443 | disk_sgntr | Disc signature, an individual disk id of obscure
|
||||
| | usability.
|
||||
440 - 443 | disk_sgntr | Disc signature: An individual disk id. Some software
|
||||
| | might use it to recognize the same storage medium
|
||||
| | at different device addresses.
|
||||
| | (The Code Area might extend up to this field.)
|
||||
| |
|
||||
444 - 445 | 0 | "usually nulls"
|
||||
|
@ -310,8 +360,11 @@ Byte Range | Value | Meaning
|
|||
| |
|
||||
446 - 461 | ========== | Partition Table Entry for partition 1
|
||||
| |
|
||||
446 - 446 | status | Governs bootability:
|
||||
| | 0x80 = bootable/active , 0x00 non-bootable/inactive
|
||||
446 - 446 | status | For some generic MBRs this marks the one partition
|
||||
| | from which the MBR should load and run more code.
|
||||
| | 0x80 = bootflag/active , 0x00 = noboot/inactive
|
||||
| | Some BIOSes ignore MBRs with no bootflag in any of
|
||||
| | their partition table entries.
|
||||
| |
|
||||
447 - 449 | ========== | C/H/S address of partition start
|
||||
447 - 447 | start_head | Heads part of start address.
|
||||
|
@ -329,7 +382,7 @@ Byte Range | Value | Meaning
|
|||
| | Bits 6 to 7 : Bits 8 to 9 of cylinders part.
|
||||
453 - 453 | end_cyl | Lower 8 bits of cylinders part of end address
|
||||
| |
|
||||
454 - 457 | start_lba | LBA of first absolute sector in partiton.
|
||||
454 - 457 | start_lba | LBA of first absolute sector in partition.
|
||||
| | Block size is 512. Counting starts at 0.
|
||||
| |
|
||||
458 - 461 | num_blocks | Number of sectors in partition.
|
||||
|
@ -356,7 +409,7 @@ on Linux a partition device file (e.g. /dev/sdb1) which cannot be used to mount
|
|||
the ISO filesystem.
|
||||
|
||||
libisofs is able to produce a second set of trees and meta data which is
|
||||
suitable for being mounted at start block 16 (ISO) resp. 64 (MBR).
|
||||
suitable for being mounted at start block 16 (ISO) which is block 64 in MBR.
|
||||
See <libisofs/libisofs.h> for call iso_write_opts_set_part_offset()
|
||||
and http://libburnia-project.org/wiki/PartitionOffset for examples with
|
||||
program xorriso.
|
||||
|
@ -374,6 +427,8 @@ Sources:
|
|||
http://www.informit.com/articles/article.aspx?p=376123&seqNum=3
|
||||
syslinux-4.05/utils/isohybrid.c
|
||||
Mail conversations with Vladimir Serbinenko.
|
||||
Mail conversations with Natalia Portillo of DiskImageChef,
|
||||
who quoted "Inside Macintosh" Volumes IV and V.
|
||||
|
||||
|
||||
APM has an adjustable block size. Because the ISO images shall always work
|
||||
|
@ -382,11 +437,19 @@ additional GPT, only block size 2048 is considered here.
|
|||
The role of APM in the boot process is to guide the firmware to a
|
||||
HFS+ filesystem.
|
||||
|
||||
Block0 of an APM begins at byte 0 of the medium. Thus it collides with MBR and
|
||||
other boot sector formats. By lucky coincidence it is possible to compose
|
||||
a mock-up of a Block0 which is acceptable to firmware which expects APM,
|
||||
and is also harmless x86 machine code with no negative side effects.
|
||||
So it is possible to combine APM with an especially prepared MBR.
|
||||
Block0 (aka Driver Descriptor Map) of an APM begins at byte 0 of the medium.
|
||||
Thus it collides with MBR and other boot sector formats. By lucky coincidence
|
||||
it is possible to compose a mock-up of a Block0 which is acceptable to firmware
|
||||
which expects APM, and is also harmless x86 machine code with no negative
|
||||
side effects. So it is possible to combine APM with an especially prepared MBR.
|
||||
|
||||
Block0 is optional. But in the context of bootable hybrid ISOs it is not only
|
||||
needed to announce block size 2048, but also it is much better suited for
|
||||
staging as harmless x86 machine code than is an APM partition entry.
|
||||
|
||||
Usually there is no Device Partition Map block (signature "TS"), although it
|
||||
is demanded by the book "Inside Macintosh". It would sit where GPT has its
|
||||
header block. So DPM is not described here.
|
||||
|
||||
The layout of a Block0 of an APM is:
|
||||
|
||||
|
@ -397,13 +460,17 @@ Byte Range | Value | Meaning (all numbers are stored big endian)
|
|||
4 - 7 | block_count| Number of blocks covered by APM
|
||||
| | Often some x86-harmless dummy. E.g. 0x9090 = 37008
|
||||
| | or 0xeb02ffff = 3,942,842,367
|
||||
8 - 9 | dev_type | obscure: "device type"
|
||||
10 - 11 | dev_id | obscure: "device id"
|
||||
12 - 15 | drv_data | obscure: "driver data"
|
||||
16 - 17 | drv_count | obscure: "driver descriptor count"
|
||||
18 - 81 | drv_map | obscure: "driver descriptor table"
|
||||
| | with 8 entries of 16 bytes each
|
||||
82 - 511 | reserved |
|
||||
8 - 9 | dev_type | Device type: The id of the Mac driver which is in
|
||||
| | charge of the storage device.
|
||||
10 - 11 | dev_id | Device id: Address in an i/o bus system.
|
||||
12 - 15 | drv_data | Driver data: Not used.
|
||||
16 - 17 | drv_count | Driver count: Count of entries in drv_map.
|
||||
18 - 505 | drv_map | Driver descriptor table:
|
||||
| | Up to 61 entries of 8 bytes each.
|
||||
| | They contain the 32 bit 512-byte LBA of the driver's
|
||||
| | storage location, its 16 bit size in 512-byte blocks,
|
||||
| | and value 0x0001.
|
||||
506 - 511 | reserved |
|
||||
---------- | ---------- | ----------------------------------------------------
|
||||
|
||||
The SYSLINUX program isohybrid.c overwrites the first 32 bytes of this
|
||||
|
@ -433,9 +500,12 @@ Byte Range | Value | Meaning (all numbers are stored big endian)
|
|||
84 - 87 | lb_count | Logical block count (same as block_count)
|
||||
88 - 91 | flags | Status flags
|
||||
| | bit0= entry is valid
|
||||
| | bit1= entry is allocated
|
||||
| | bit1= partition is allocated
|
||||
| | bit2= partition is in use
|
||||
| | bit3= partition contains valid boot information
|
||||
| | bit4= partition is readable
|
||||
| | bit5= partition is writable
|
||||
| | bit7= boot code is position independent
|
||||
| | bit30= automatic mount (legacy Mac)
|
||||
92 - 95 | boot_block | Logical start block number of boot code = 0
|
||||
96 - 99 | boot_bytes | Number of bytes in boot code = 0
|
||||
|
@ -499,6 +569,7 @@ Sources:
|
|||
http://mjg59.fedorapeople.org/Fedora-LiveCD.iso
|
||||
http://en.wikipedia.org/wiki/GUID_Partition_Table
|
||||
http://en.wikipedia.org/wiki/GUID
|
||||
http://www.uefi.org/sites/default/files/resources/2_4_Errata_B.pdf
|
||||
|
||||
|
||||
GPT is the partition map format of EFI, a successor of PC-BIOS.
|
||||
|
@ -506,8 +577,11 @@ Block size is always 512. GPT consists of a header block at block address 1 and
|
|||
a partition table near the start of the medium. This is called the primary GPT.
|
||||
There is a backup copy of header and table near the end of the medium.
|
||||
|
||||
GPT is particularly designed to co-exist with MBR. If it is present, then the
|
||||
booting firmware may or may not prefer it over the MBR partition table.
|
||||
GPT is particularly designed to co-exist with MBR. Officially only with a
|
||||
Protective MBR which covers the whole medium (except the MBR itself) by
|
||||
a single partition of type 0xee. Inofficially often with filesystem partitions
|
||||
marked in both, GPT and MBR. In the latter case the booting firmware may
|
||||
or may not prefer GPT over the MBR partition table.
|
||||
GPT can co-exist with APM if APM block size is at least 1024. In this case,
|
||||
the primary partition table will begin after the last APM entry block.
|
||||
|
||||
|
@ -520,7 +594,7 @@ Byte Range | Value | Meaning (little endian numbers, LBA unit is 512 byte)
|
|||
16 - 19 | head_crc | CRC-32 of this header while head_crc is 0
|
||||
20 - 23 | reserved | = 0
|
||||
24 - 31 | curr_lba | Location of this header block = 1
|
||||
32 - 39 | back_lba | Location of header backup block. See below.
|
||||
32 - 39 | backup_lba | Location of header backup block. See below.
|
||||
40 - 47 | first_lba | First usable LBA for partitions
|
||||
48 - 55 | last_lba | Last usable LBA for partitions
|
||||
56 - 71 | guid | Disk GUID, Random
|
||||
|
@ -545,13 +619,12 @@ bit1 becomes bit30, and so on. Further it gets exored with 0xffffffff.
|
|||
|
||||
A GUID consists of a 32-bit integer, two 16-bit integers, and an array of
|
||||
8 bytes. The integers are to be stored big-endian.
|
||||
A globally registered class of GUID are the partition type GUIDs.
|
||||
This example uses two of them
|
||||
A globally registered class of GUID are the partition type GUIDs:
|
||||
Basic data partition: a2 a0 d0 eb , e5 b9 , 33 44 , 87 c0 68 b6 b7 26 99 c7
|
||||
HFS+ partition : 00 53 46 48 , 00 00 , aa 11 , aa 11 00 30 65 43 ec ac
|
||||
EFI System partition: 28 73 2a c1 , 1f f8 , d2 11 , ba 4b 00 a0 c9 3e c9 3b
|
||||
Note that the wikipedia list shows the first 32-bit word and the next two
|
||||
16-bit words in little-endia interpretation.
|
||||
16-bit words in little-endian interpretation.
|
||||
|
||||
The partition table is an array of entries. Each has a size of 128 bytes.
|
||||
A partition table entry looks like:
|
||||
|
@ -589,7 +662,7 @@ Byte Range | Value | Meaning (little endian numbers, LBA unit is 512 byte)
|
|||
| | Is recomputed after the following changes.
|
||||
24 - 31 | curr_lba | Location of this header block.
|
||||
| | Shows own block address.
|
||||
32 - 39 | back_lba | Location of header backup block.
|
||||
32 - 39 | backup_lba | Location of header backup block.
|
||||
| | Points to primary header block = 1
|
||||
72 - 79 | part_start | Partition entries start.
|
||||
| | Points to start of backup partition table.
|
||||
|
@ -616,6 +689,7 @@ Sources:
|
|||
There are traces in the web which relate this to specs by
|
||||
MIPS Computer Systems, Inc. , 1985
|
||||
Silicon Graphics Computer Systems, Inc. , 2000
|
||||
Mail conversations with Natalia Portillo.
|
||||
|
||||
|
||||
The first 512 bytes of the media constitute the Volume Header.
|
||||
|
@ -626,7 +700,11 @@ Byte Range | Value | Meaning
|
|||
0 - 3 | 0x0be5a941 | Magic number
|
||||
4 - 5 | 0 | Root partition number
|
||||
6 - 7 | 0 | Swap partition number
|
||||
8 - 23 | 0 | Name of file to boot (unclear what this means)
|
||||
8 - 23 | 0 | One of the boot_name items from the Volume Directory
|
||||
| | may be put here to choose for booting the entry with
|
||||
| | that name.
|
||||
| | (Obviously it may be empty if only one non-zero entry
|
||||
| | exists in the Volume Directory.)
|
||||
| |
|
||||
24 - 71 | ========== | Device Parameters
|
||||
| |
|
||||
|
@ -661,7 +739,7 @@ Byte Range | Value | Meaning
|
|||
72 - 311 | ========== | Volume Directory with 15 entries of 16 bytes each
|
||||
| |
|
||||
72 - 87 | ========== | Volume Directory Entry 1
|
||||
72 - 79 | boot_name | Boot file basename, eventually padded by 0 to lenght 8
|
||||
72 - 79 | boot_name | Boot file basename, eventually padded by 0 to length 8
|
||||
80 - 83 | boot_block | ISO 9660 LBA of boot file * 4, i.e. in blocks of 512
|
||||
84 - 87 | boot_bytes | File length in bytes
|
||||
| |
|
||||
|
@ -741,8 +819,8 @@ Byte Range | Value | Meaning
|
|||
| | (Elf32_Phdr field p_filesz + 511) / 512;
|
||||
| |
|
||||
28 - 31 | seg_start | Segment file offset. Blocks 512 bytes.
|
||||
| | ISO 9660 LBA of boot file * 4 plus offset
|
||||
| | + offset which stems from ELF header of boot file:
|
||||
| | ISO 9660 LBA of boot file * 4 plus offset which
|
||||
| | stems from ELF header of boot file:
|
||||
| | (Elf32_Phdr field p_offset + 511) / 512;
|
||||
| |
|
||||
32 - 431 | ========== | Boot Map Entries 2 to 51
|
||||
|
@ -798,7 +876,7 @@ Sources:
|
|||
The Disk Label is written to the first 512 bytes of the image. It can mark
|
||||
8 partitions (slices ) of which the first contains the ISO image. The other
|
||||
7 may contain boot images.
|
||||
Words are composed big-endian style.
|
||||
Words are composed big-endian style. Block size is 512.
|
||||
|
||||
Boot images are provided externally. mkisofs arranges them after the end of
|
||||
the ISO image so that each starts at a cylinder boundary (320 kB).
|
||||
|
@ -810,7 +888,6 @@ their predecessor in the partition table:
|
|||
If mkisofs is called with -G image -B ... all boot partitions are
|
||||
mapped to the partition that contains the ISO9660 filesystem."
|
||||
|
||||
|
||||
Disk Label components:
|
||||
|
||||
Byte Range | Value | Meaning
|
||||
|
@ -873,7 +950,7 @@ Byte Range | Value | Meaning
|
|||
| |
|
||||
444 - 447 | start_cyl | Start cylinder
|
||||
| |
|
||||
448 - 451 | num_blocks | Number of blocks in partition
|
||||
448 - 451 | num_blocks | Number of 512-byte blocks in partition
|
||||
| |
|
||||
452 - 507 | ========== | Partition table entries #2 to #8
|
||||
| ... | See above Partition table entry #1
|
||||
|
@ -884,6 +961,30 @@ Byte Range | Value | Meaning
|
|||
| |
|
||||
---------- | ---------- | ----------------------------------------------------
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
GRUB2 SUN SPARC Core File Address
|
||||
|
||||
Sources:
|
||||
Mail conversations with Vladimir Serbinenko.
|
||||
|
||||
GRUB2 lets libisofs write after the disk label block the address and size of a
|
||||
data file in the ISO image. E.g. of /boot/grub/sparc64-ieee1275/core.img.
|
||||
This is combined with a SUN Disk Label which exposes only the single partition
|
||||
describing the overall ISO filesystem size.
|
||||
|
||||
Byte Range | Value | Meaning
|
||||
------------ | ---------- | --------------------------------------------------
|
||||
512 - 551 | opaque | Code and data provided by GRUB2
|
||||
| |
|
||||
552 - 559 | offset | Start byte number of the file. 64-bit big-endian.
|
||||
| |
|
||||
560 - 563 | size | Number of bytes in the file. 32-bit big-endian.
|
||||
| |
|
||||
564 - 32767 | opaque | Code and data provided by GRUB2
|
||||
| |
|
||||
------------ | ---------- | --------------------------------------------------
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
@ -907,6 +1008,7 @@ PReP boots via a MBR partition containing only raw ELF and having type 0x41.
|
|||
Sources:
|
||||
Mail conversations with Vladimir Serbinenko.
|
||||
http://stuff.mit.edu/afs/sipb/contrib/doc/specs/protocol/chrp/chrp1_7a.pdf
|
||||
https://www.ibm.com/developerworks/community/wikis/home?lang=en#!/wiki/W51a7ffcf4dfd_4b40_9d82_446ebc23c550/page/PowerLinux%20Boot%20howto
|
||||
|
||||
CHRP is marked by an MBR partition entry of type 0x96 spanning the whole
|
||||
ISO 9660 image.
|
||||
|
@ -914,19 +1016,182 @@ ISO 9660 image.
|
|||
The specs in chrp1_7a.pdf promise that CHRP also recognizes ISO 9660 file
|
||||
systems on unpartitioned disks. (See 11.1.1. Media Layout Format)
|
||||
|
||||
The firmware looks up a file /ppc/bootinfo.txt which in SGML-ish tag
|
||||
<boot-script> contains firmware commands.
|
||||
E.g. to execute the binary /boot/grub/powerpc.elf as first stage of GRUB2:
|
||||
<boot-script>boot &device;:\boot\grub\powerpc.elf</boot-script>
|
||||
|
||||
Vladimir Serbinenko stated:
|
||||
PReP boot may be preferable. At least it can co-exist with other partitions
|
||||
in the ISO image [without causing overlapping between partitions].
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
HP-PA via PALO header version 4
|
||||
for HP PA-RISC
|
||||
|
||||
Sources:
|
||||
cdrkit-1.1.10/genisoimage/boot-hppa.c
|
||||
by Steve McIntyre <steve@einval.com>
|
||||
who states "Heavily inspired by palo"
|
||||
|
||||
This format is expected by PALO versions before 1.92. Their source code defines
|
||||
PALOHDRVERSION as 4. The format also serves as fallback for newer versions,
|
||||
which expect header version 5, if a 0-byte is found at byte position 1024.
|
||||
|
||||
There are five parameters which get encoded into the first 248 bytes of the
|
||||
System Area: cmdline, bootloader, 32-bit kernel, 64-bit kernel, and ramdisk.
|
||||
They are all mandatory.
|
||||
While cmdline is simply a string of at most 127 characters, the other four
|
||||
point to data files inside the ISO image.
|
||||
|
||||
All numbers are recorded big endian.
|
||||
|
||||
Boot sector components:
|
||||
|
||||
Byte Range | Value | Meaning
|
||||
---------- | ---------- | ----------------------------------------------------
|
||||
0 - 1 | 0x8000 | Magic
|
||||
| |
|
||||
2 - 6 | "PALO" | Zero terminated string
|
||||
| |
|
||||
7 - 7 | 4 | Version
|
||||
| |
|
||||
8 - 11 | kern32_adr | Byte address of the "HPPA 32-bit kernel" file
|
||||
| | genisoimage option -hppa-kernel-32
|
||||
12 - 15 | kern32_len | Byte count of the "HPPA 32-bit kernel" file
|
||||
| |
|
||||
16 - 19 | ramdsk_adr | Byte address of the "HPPA ramdisk" file
|
||||
| | genisoimage option -hppa-ramdisk
|
||||
20 - 23 | ramdsk_len | Byte count of the "HPPA ramdisk" file
|
||||
| |
|
||||
24 - 151 | cmdline | "Command line"
|
||||
| | genisoimage option -hppa-cmdline
|
||||
| |
|
||||
232 - 235 | kern64_adr | Byte address of the "HPPA 64-bit kernel" file
|
||||
| | genisoimage option -hppa-kernel-64
|
||||
236 - 239 | kern64_len | Byte count of the "HPPA 64-bit kernel" file
|
||||
| |
|
||||
240 - 243 | bootld_adr | Byte address of the "HPPA bootloader" file
|
||||
| | genisoimage option -hppa-bootloader
|
||||
244 - 247 | bootld_len | Byte count of the "HPPA bootloader" file
|
||||
| |
|
||||
---------- | ---------- | ----------------------------------------------------
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> ??? HP-PA
|
||||
HP-PA via PALO header version 5
|
||||
for HP PA-RISC
|
||||
|
||||
Sources:
|
||||
Public mail conversations with Helge Deller, beginning with
|
||||
https://lists.debian.org/debian-hppa/2014/01/msg00016.html
|
||||
http://git.kernel.org/cgit/linux/kernel/git/deller/palo.git/tree/lib/
|
||||
(especially struct firstblock in common.h and struct partition in part.h)
|
||||
|
||||
This format is expected by PALO versions 1.92 or higher. They fall back to
|
||||
header version 4 if a 0-byte is found at byte position 1024.
|
||||
Their source code defines PALOHDRVERSION as 5.
|
||||
|
||||
There are five parameters which get encoded into the first 2048 bytes of the
|
||||
System Area: cmdline, bootloader, 32-bit kernel, 64-bit kernel, and ramdisk.
|
||||
They are all mandatory.
|
||||
While cmdline is simply a string of at most 1023 characters, the other four
|
||||
point to data files inside the ISO image.
|
||||
|
||||
Several fields of the firstblock shall be hardcoded to 0, on advise of
|
||||
Helge Deller. Their description is shown in round brackets.
|
||||
|
||||
All numbers are recorded big endian.
|
||||
Except flags, all 4-byte integers are signed.
|
||||
|
||||
Boot sector components:
|
||||
|
||||
Byte Range | Value | Meaning
|
||||
---------- | ---------- | ----------------------------------------------------
|
||||
0 - 1 | 0x8000 | Magic
|
||||
| |
|
||||
2 - 6 | "PALO" | Zero terminated string
|
||||
| |
|
||||
7 - 7 | 5 | Version
|
||||
| |
|
||||
8 - 11 | kern32_adr | Byte address of the 32-bit kernel file
|
||||
| |
|
||||
12 - 15 | kern32_len | Byte count of the 32-bit kernel file
|
||||
| |
|
||||
16 - 19 | ramdsk_adr | Byte address of the ramdisk file
|
||||
| |
|
||||
20 - 23 | ramdsk_len | Byte count of the ramdisk file
|
||||
| |
|
||||
24 - 141 | 0 | All 0s. Old command line of version 4.
|
||||
| |
|
||||
| |
|
||||
220 - 223 | 0 | (Length of uncompressed 32-bit kernel)
|
||||
| |
|
||||
224 - 227 | 0 | (Length of uncompressed 64-bit kernel)
|
||||
| |
|
||||
228 - 231 | 0 | (flags)
|
||||
| |
|
||||
232 - 235 | kern64_adr | Byte address of the 64-bit kernel file
|
||||
| |
|
||||
236 - 239 | kern64_len | Byte count of the 64-bit kernel file
|
||||
| |
|
||||
240 - 243 | ipl_adr | Byte address of the bootloader file
|
||||
| |
|
||||
244 - 247 | ipl_len | Byte count of the bootloader file
|
||||
| |
|
||||
248 - 251 | 0 | (ipl_entry: offset to first command in bootloader)
|
||||
| |
|
||||
446 - 511 | 0 | (MBR partition table and signature)
|
||||
| |
|
||||
1024 -2047 | cmdline | Zero terminated command line of up to
|
||||
| | 1023 characters
|
||||
| |
|
||||
---------- | ---------- | ----------------------------------------------------
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
>>> ??? DEC Alpha
|
||||
DEC Alpha SRM boot sector
|
||||
for Alpha architecture
|
||||
|
||||
Sources:
|
||||
http://www.tldp.org/HOWTO/text/SRM-HOWTO
|
||||
SRM Firmware Howto - Rich Payne, and David Huggins-Daines
|
||||
cdrkit-1.1.10/genisoimage/boot-alpha.c
|
||||
by Steve McIntyre
|
||||
who states "Heavily inspired by isomarkboot by David Mosberger in 1996"
|
||||
mail conversations with Helge Deller
|
||||
|
||||
The SRM firmware expects a Secondary Bootstrap Loader program, which usually
|
||||
is a data file of the ISO filesystem. This loader is announced by size and
|
||||
block address in the first 512 bytes of the System Area.
|
||||
SRM accepts the boot sector and executes the loader if the checksum matches.
|
||||
|
||||
All numbers are recorded as unsigned 64 bit little endian.
|
||||
|
||||
Boot sector components:
|
||||
|
||||
Byte Range | Value | Meaning
|
||||
---------- | ---------- | ----------------------------------------------------
|
||||
0 - ? | boot_string| genisoimage writes
|
||||
| | "Linux/Alpha aboot for ISO filesystem."
|
||||
| | with terminating zero byte.
|
||||
| |
|
||||
? - 479 | 0 | Unused / undefined.
|
||||
| |
|
||||
480 - 487 | length | Size of boot loader file in units of 512 bytes.
|
||||
| |
|
||||
488 - 495 | address | LBA of the boot loader file in units of 512 bytes.
|
||||
| |
|
||||
496 - 503 | flag | "Always 0"
|
||||
| |
|
||||
504 - 511 | checksum | Sum of 64 bit words 0 to 63 (bytes 0 to 503).
|
||||
| |
|
||||
---------- | ---------- | ----------------------------------------------------
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
@ -1045,8 +1310,8 @@ intentionally non-essential:
|
|||
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||
They may be overwritten by other bytes which must not produce errors or
|
||||
undesirable side effects when executed as x86 machine code.
|
||||
The following 32 bytes from block 0 of an Apple Partiton Map (APM) are such
|
||||
harmless code. They stem from Fedora-LiveCD.iso by Matthew Garret:
|
||||
The following 32 bytes from block 0 of an Apple Partition Map (APM) are such
|
||||
harmless code. They stem from Fedora-LiveCD.iso by Matthew Garrett:
|
||||
45 52 08 00 00 00 90 90 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
They do not depend on any properties of the ISO image or the information
|
||||
|
@ -1113,7 +1378,7 @@ Byte Range | Value | Meaning (little endian numbers, LBA unit is 512 byte)
|
|||
---------- | ---------- | ----------------------------------------------------
|
||||
12 - 15 | head_size | Header size = 0x5c = 92
|
||||
24 - 31 | curr_lba | Location of this header block = 0x1
|
||||
32 - 39 | back_lba | Location of header backup block = 0x144ffe = 1331198
|
||||
32 - 39 | backup_lba | Location of header backup block = 0x144ffe = 1331198
|
||||
| | This is 1 KiB before the end of MBR partition 1
|
||||
| | (but should be 512 bytes).
|
||||
| | (Potential isohybrid.c bug #1:
|
||||
|
@ -1264,6 +1529,9 @@ Start at block 0xa4 = 164 * 512 = 41 * 2048. The VFAT image file.
|
|||
Last block is 0x0513 = 1299 = 164 + 1135. This end is correct.
|
||||
(Potential isohybrid.c bug #4:
|
||||
Wrong character set and incidential bytes in GPT partition name.)
|
||||
(Potential isohybrid.c bug #5:
|
||||
The EFI System Partition should have type GUID :
|
||||
"C12A7328-F81F-11D2-BA4B-00A0C93EC93B")
|
||||
|
||||
Next entry at byte 0x02100 = 8448:
|
||||
|
||||
|
@ -1292,8 +1560,8 @@ The ISO image file gets padded up to full MiB with sufficient room for the GPT
|
|||
backup which is stored near the very end of the image file. There is need for
|
||||
at least 16.5 KiB, which effectively occupy 18 KiB.
|
||||
|
||||
The backup partition array is stored 17 KiB before the end of MBR partition 1
|
||||
resp. the image file.
|
||||
The backup partition array is stored 17 KiB before the end of MBR partition 1,
|
||||
which is also the end of the image file.
|
||||
(Potential isohybrid.c bug #1:
|
||||
Wikipedia suggests "LBA -33" counted from end. This would be 16.5 KiB before
|
||||
end.)
|
||||
|
@ -1326,12 +1594,21 @@ Sources:
|
|||
Mailing list conversations with Vladimir Serbinenko.
|
||||
|
||||
|
||||
The MBR file that is used with GRUB2 script grub-mkrescue needs only a
|
||||
partition table entry which describes the image size.
|
||||
The MBR file that is used with older versions of GRUB2 script grub-mkrescue
|
||||
needs only a partition table entry which describes the image size.
|
||||
Newer versions get patched by the block address of the content of the first
|
||||
El Torito boot image. See grub-mkrescue use of xorrisofs option --grub2-mbr.
|
||||
|
||||
Byte Range | Value | Meaning
|
||||
---------- | ---------- | ----------------------------------------------------
|
||||
0 - 445 | = opaque = | GRUB2 machine code provided by MBR template
|
||||
0 - 431 | = opaque = | GRUB2 machine code provided by MBR template
|
||||
| |
|
||||
432 - 439 | bootimg_adr| With newer versions of grub-mkrescue:
|
||||
| | Block address of the start of the boot image file
|
||||
| | content plus 4. Block size is 512.
|
||||
| | 64 bit Little-endian.
|
||||
| |
|
||||
440 - 445 | = opaque = | provided by MBR template
|
||||
| |
|
||||
446 - 509 | ========== | Partition table
|
||||
| |
|
||||
|
|
|
@ -79,7 +79,7 @@ Tag_id distinguishes the following tag types
|
|||
"libisofs_checksum_tag_v1" Session tag
|
||||
|
||||
A relocated superblock may appear at LBA 0 of an image which was produced for
|
||||
being stored in a disk file or on overwriteable media (e.g. DVD+RW, BD-RE).
|
||||
being stored in a disk file or on overwritable media (e.g. DVD+RW, BD-RE).
|
||||
Typically there is a first session recorded with a superblock at LBA 32 and
|
||||
the next session may follow shortly after its session tag. (Typically at the
|
||||
next block address which is divisible by 32.) Normally no session starts after
|
||||
|
@ -131,10 +131,10 @@ checksums as strings of 32 hex digits.
|
|||
range_start=
|
||||
The block address where the session is supposed to start. If this does not
|
||||
match the session start on media then the volume descriptors of the
|
||||
image have been relocated. (This can happen with overwriteable media. If
|
||||
image have been relocated. (This can happen with overwritable media. If
|
||||
checksumming started at LBA 0 and finds range_start=32, then one has to
|
||||
restart checksumming at LBA 32. See libburn/doc/cookbook.txt
|
||||
"ISO 9660 multi-session emulation on overwriteable media" for background
|
||||
"ISO 9660 multi-session emulation on overwritable media" for background
|
||||
information.)
|
||||
|
||||
range_size=
|
||||
|
@ -189,7 +189,7 @@ With tag type 2:
|
|||
|
||||
Keep the original MD5 context of the data blocks and clone one for obtaining
|
||||
the MD5 bytes.
|
||||
If the MD5s match, then compute the checksum block and all folowing ones into
|
||||
If the MD5s match, then compute the checksum block and all following ones into
|
||||
the kept MD5 context and go on with reading and computing for the tree checksum
|
||||
tag. This will be found at block address next_tag, verified and parsed by:
|
||||
iso_util_decode_md5_tag(block, &tag_type, &pos,
|
||||
|
@ -211,7 +211,7 @@ next_tag. Go on by looking for tag type 2 and follow above prescription.
|
|||
|
||||
Checking the Data Part of the Session
|
||||
|
||||
In order to check the trustworthyness of a whole session, continue reading
|
||||
In order to check the trustworthiness of a whole session, continue reading
|
||||
and checksumming after the tree was verified.
|
||||
|
||||
Read and checksum the blocks. When reaching block address next_tag (from the
|
||||
|
@ -232,7 +232,7 @@ If the media is sequentially recordable, obtain a table of content and check
|
|||
the first track of each session as prescribed above in Checking Before Image
|
||||
Tree Loading and in Checking the Data Part of the Session.
|
||||
|
||||
With disk files or overwriteable media, look for a relocated superblock tag
|
||||
With disk files or overwritable media, look for a relocated superblock tag
|
||||
but do not hop to address next_tag (given by session_start=). Instead look at
|
||||
LBA 32 for the first session and check it as prescribed above.
|
||||
After reaching its end, round up the read address to the next multiple of 32
|
||||
|
|
|
@ -394,12 +394,6 @@ MAX_INITIALIZER_LINES = 30
|
|||
|
||||
SHOW_USED_FILES = YES
|
||||
|
||||
# If the sources in your project are distributed over multiple directories
|
||||
# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
|
||||
# in the documentation. The default is NO.
|
||||
|
||||
SHOW_DIRECTORIES = NO
|
||||
|
||||
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
|
||||
# doxygen should invoke to get the current version for each file (typically from the
|
||||
# version control system). Doxygen will invoke the program by executing (via
|
||||
|
@ -527,7 +521,7 @@ EXCLUDE_SYMBOLS =
|
|||
# directories that contain example code fragments that are included (see
|
||||
# the \include command).
|
||||
|
||||
EXAMPLE_PATH = test
|
||||
EXAMPLE_PATH = demo/demo.c
|
||||
|
||||
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
|
||||
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
|
@ -698,12 +692,6 @@ HTML_FOOTER =
|
|||
|
||||
HTML_STYLESHEET =
|
||||
|
||||
# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
|
||||
# files or namespaces will be aligned in HTML using tables. If set to
|
||||
# NO a bullet list will be used.
|
||||
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
|
||||
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
|
||||
# will be generated that can be used as input for tools like the
|
||||
# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
|
||||
|
@ -938,18 +926,6 @@ GENERATE_XML = NO
|
|||
|
||||
XML_OUTPUT = xml
|
||||
|
||||
# The XML_SCHEMA tag can be used to specify an XML schema,
|
||||
# which can be used by a validating XML parser to check the
|
||||
# syntax of the XML files.
|
||||
|
||||
XML_SCHEMA =
|
||||
|
||||
# The XML_DTD tag can be used to specify an XML DTD,
|
||||
# which can be used by a validating XML parser to check the
|
||||
# syntax of the XML files.
|
||||
|
||||
XML_DTD =
|
||||
|
||||
# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
|
||||
# dump the program listings (including syntax highlighting
|
||||
# and cross-referencing information) to the XML output. Note that
|
||||
|
|
|
@ -45,7 +45,7 @@ more data bytes than with SL, though, and any of the 256 possible byte values.
|
|||
The reader shall be prepared to detect and handle oversized data.
|
||||
|
||||
One or more AL entries form the Attribute List of a file object with
|
||||
an even number of components. Each two consequtive components form a pair of
|
||||
an even number of components. Each two consecutive components form a pair of
|
||||
Name and Value.
|
||||
|
||||
The empty name indicates that the value is a compact representation of ACLs.
|
||||
|
@ -109,8 +109,6 @@ Each Component Record shall have the following format:
|
|||
[B] "BP 2 - Component Length (LEN_CP)" shall specify as an 8-bit number the
|
||||
number of component bytes in the Component Record. This length shall not
|
||||
include the first two bytes of the Component Record.
|
||||
If any of the bit positions 1-3 is set, the value of this field shall be
|
||||
set to ZERO and no Component Content shall be recorded.
|
||||
This field shall be recorded according to ISO 9660 Format section 7.1.1.
|
||||
|
||||
[C] "BP 3 to 2 + LEN_CP - Component Content" shall contain the component
|
||||
|
@ -219,7 +217,7 @@ S_IRWXG. If there is ACL_USER_N or ACL_GROUP_N there must also be ACL_MASK.
|
|||
|
||||
A numeric qualifier is a binary number of variable length up to 4 bytes. The
|
||||
Most Significant Byte comes first. The number shall be the "POSIX File User ID"
|
||||
resp. "POSIX File Group ID" as also used in RRIP PX entries. The ids of owning
|
||||
or "POSIX File Group ID" as also used in RRIP PX entries. The ids of owning
|
||||
user and owning group shall be taken from the PX entry of the file object.
|
||||
|
||||
Optional TRANSLATE entries may associate user or group names with numeric
|
||||
|
@ -237,7 +235,7 @@ An eventually needed qualifier is stored in one or more Qualifier Records.
|
|||
[b] "BP 2 - Qualifier Record Head" shall be present only if QUALIFIER is set
|
||||
to 1. It shall give the number of Qualifier Bytes and eventually
|
||||
indicate that the qualifier continues in a Qualifier Record which comes
|
||||
imediately after this record.
|
||||
immediately after this record.
|
||||
0 to 127 Q_LENGTH, the qualifier is complete by this record
|
||||
128 to 255 Q_LENGTH+128, the qualifier is continued by next record
|
||||
So a Qualifier Record can contain at most 127 Qualifier Bytes.
|
||||
|
@ -361,7 +359,7 @@ SUSP-1.10 does not specify ES entries at all and allows to have extension
|
|||
entries without announcing them by an ER entry. So if a second ER entry is
|
||||
not bearable, then the SUSP-1.10 downgrade of AAIP allows to omit the
|
||||
AAIP ER and the ES entries. But if there is the AAIP ER then there must be ES
|
||||
at the appropriate places. Else the format would explicitely violate SUSP-1.12.
|
||||
at the appropriate places. Else the format would explicitly violate SUSP-1.12.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Model Relations:
|
||||
|
@ -445,7 +443,7 @@ Program mkisofs emits entry XA
|
|||
-------------------------------------------------------------------------------
|
||||
|
||||
This text is under
|
||||
Copyright (c) 2009 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Copyright (c) 2009 - 2013 Thomas Schmitt <scdbackup@gmx.net>
|
||||
It shall only be modified in sync with libisofs and other software which
|
||||
makes use of AAIP. Please mail change requests to mailing list
|
||||
<libburn-hackers@pykix.org> or to the copyright holder in private.
|
||||
|
|
|
@ -4,11 +4,13 @@
|
|||
Directory of Namespace "isofs."
|
||||
|
||||
by Thomas Schmitt - mailto:scdbackup@gmx.net
|
||||
Libburnia project - mailto:libburn-hackers@pykix.org
|
||||
Libburnia project - mailto:bug-xorriso@gnu.org
|
||||
|
||||
|
||||
The following names are defined for AAIP namespace "isofs." as mentioned in
|
||||
specification of AAIP :
|
||||
specification of AAIP. Unless explicitly stated otherwise, numbers with
|
||||
names like *_LEN are 8 bit unsigned integers, those with *_BYTES are 32 bit
|
||||
unsigned integers.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
@ -22,7 +24,7 @@ Purpose:
|
|||
END is also the block address of the start of the checksum recording
|
||||
area in the image.
|
||||
See also isofs.cx .
|
||||
This attribute shall eventually be attached to the root directory entry
|
||||
This attribute shall be attached to the root directory entry
|
||||
and be global for the whole image.
|
||||
|
||||
Format of Value:
|
||||
|
@ -65,8 +67,8 @@ Purpose:
|
|||
Records the name of the character set that was used as output character
|
||||
set when writing the RRIP name tree of the ISO 9660 image. It shall be
|
||||
suitable as parameter for function iconv_open(3).
|
||||
This attribute shall eventually be attached to the root directory entry
|
||||
and be global for the whole image.
|
||||
This attribute shall be attached to the root directory entry and be
|
||||
global for the whole image.
|
||||
|
||||
Format of Value:
|
||||
Shall hold the character set name without terminating 0-byte.
|
||||
|
@ -107,6 +109,7 @@ Name:
|
|||
Purpose:
|
||||
Records .st_dev and .st_ino of struct stat of the file source in the
|
||||
local filesystem. See man 2 stat.
|
||||
Both values may be unsigned integers up to 255 bytes.
|
||||
|
||||
Format of Value:
|
||||
DEV_LEN | DEV_BYTES | INO_LEN | INO_BYTES
|
||||
|
@ -128,7 +131,7 @@ Name:
|
|||
|
||||
Purpose:
|
||||
Records the IsoHfsplusBlessings blessing of a IsoNode as defined
|
||||
in libisofs.h. At image load time, this info shall be converted back
|
||||
in libisofs.h. At image load time, this info may be converted back
|
||||
into a relation between IsoImage and IsoNode so that it is available for
|
||||
the HFS+ writer when a new ISO 9660 / HFS+ image gets produced.
|
||||
|
||||
|
@ -152,7 +155,7 @@ Name:
|
|||
|
||||
Purpose:
|
||||
Records the iso_hfsplus_xinfo_data information as defined in libisofs.h.
|
||||
At image load time, this info shall be converted back into an xinfo
|
||||
At image load time, this info may be converted back into an xinfo
|
||||
attachment for iso_hfsplus_xinfo_func so that it is available for
|
||||
the HFS+ writer when a new ISO 9660 / HFS+ image gets produced.
|
||||
|
||||
|
@ -172,6 +175,26 @@ Registered:
|
|||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name:
|
||||
isofs.nt
|
||||
|
||||
Purpose:
|
||||
Records the name truncation mode and the truncation length for Rock Ridge
|
||||
names. See iso_image_set_truncate_mode() in libisofs.h.
|
||||
This attribute shall be attached to the root directory entry and be
|
||||
global for the whole image.
|
||||
|
||||
Format of Value:
|
||||
MODE_LEN | MODE_BYTES | LENGTH_LEN | LENGTH_BYTES
|
||||
|
||||
Example:
|
||||
{ 1, 1, 1, 255 }
|
||||
|
||||
Registered:
|
||||
24 Sep 2015 by Thomas Schmitt for libisofs.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name:
|
||||
isofs.st
|
||||
|
||||
|
@ -183,7 +206,7 @@ Purpose:
|
|||
The RRIP timestamps have a blind second during which a change after
|
||||
node registration would not be recognizable for incremental backups
|
||||
which are based in "isofs.di" rather than on content comparison.
|
||||
This attribute shall eventually be attached to the root directory entry
|
||||
This attribute shall be attached to the root directory entry
|
||||
and be global for the whole image.
|
||||
|
||||
Format of Value:
|
||||
|
@ -201,13 +224,13 @@ Registered:
|
|||
-------------------------------------------------------------------------------
|
||||
|
||||
This text is under
|
||||
Copyright (c) 2009 - 2011 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Copyright (c) 2009 - 2015 Thomas Schmitt <scdbackup@gmx.net>
|
||||
It shall only be modified in sync with libisofs and other software which
|
||||
makes use of AAIP. Please mail change requests to mailing list
|
||||
<libburn-hackers@pykix.org> or to the copyright holder in private.
|
||||
<bug-xorriso@gnu.org> or to the copyright holder in private.
|
||||
Only if you cannot reach the copyright holder for at least one month it is
|
||||
permissible to modify this text under the same license as the affected
|
||||
copy of libisofs.
|
||||
copy of libisofs. Currently: GNU General Public License version 2 or later.
|
||||
If you do so, you commit yourself to taking reasonable effort to stay in
|
||||
sync with the other interested users of this text.
|
||||
|
||||
|
|
|
@ -0,0 +1,262 @@
|
|||
|
||||
Description of the zisofs2 Format
|
||||
Revision 2.0-dev
|
||||
|
||||
as of zisofs2-tools by
|
||||
Valentín KIVACHUK BURDÁ and Thomas SCHMITT
|
||||
|
||||
1 Oct 2020
|
||||
|
||||
|
||||
The zisofs2 format was invented by Valentín KIVACHUK BURDÁ and
|
||||
Thomas SCHMITT (as extension of zisofs by H. Peter Anvin). It compresses
|
||||
data file content, marks it by a header and provides a pointer array for
|
||||
coarse random access. Within a RRIP enhanced ISO 9660 image the format
|
||||
is additionally marked by a System Use entry with signature "ZF" or "Z2".
|
||||
|
||||
The uncompressed size of a single zisofs2 compressed file is restricted
|
||||
to 2^64 - 1 bytes. Larger files shall not be compressed.
|
||||
|
||||
The format of version 1 of zisofs is supported by this specification.
|
||||
Using it for files with uncompressed size smaller than 4 GiB is friendly
|
||||
towards software which does not know about zisofs2.
|
||||
See section **LEGACY** for a summary of version 1 of zisofs.
|
||||
|
||||
|
||||
|
||||
Data Types
|
||||
|
||||
ISO 9660:7.3.1 - little endian 4-byte words
|
||||
ISO 9660:7.1.1 - unsigned single bytes
|
||||
ISO 9660:7.3.3 - 8-bytes value, first in little endian, then big endian.
|
||||
#uint64 - 8-bytes unsigned value in little endian
|
||||
|
||||
Supported compressors
|
||||
|
||||
The file header has this layout:
|
||||
@alg_id @alg_char Description
|
||||
1 'PZ' (50)(5A) Zlib
|
||||
2 'XZ' (78)(7A) XZ
|
||||
3 'L4' (6C)(34) LZ4
|
||||
4 'ZD' (7A)(64) Zstandard
|
||||
5 'B2' (62)(32) Bzip2
|
||||
|
||||
@alg_id is a 7.1.1 value. @alg_char is 2 ASCII characters stored as 2 bytes
|
||||
Values of @alg_id = 0 and @alg_char = 'pz'(70)(7A) are reserved and
|
||||
must not be used. Other compressors are allowed and may be added to this
|
||||
list in the future
|
||||
|
||||
Compressor strategy
|
||||
|
||||
The default strategy for a compressor is to compress each input data block
|
||||
independently. The zisofs2 spec may define in the future other strategies,
|
||||
which will have a new @alg_id, @alg_char and a description in this section.
|
||||
|
||||
|
||||
File Header
|
||||
|
||||
The file header has this layout:
|
||||
Offset Type Identifier Contents
|
||||
--------------------------------------------------------------------------
|
||||
0 (8 bytes) @hdr_magic Magic num (EF 22 55 A1 BC 1B 95 A0)
|
||||
8 7.1.1 @hdr_version File header version (0)
|
||||
9 7.1.1 @hdr_size header_size >> 2 (6)
|
||||
10 7.1.1 @alg_id Algorithm Type (>=1)
|
||||
11 7.1.1 @hdr_bsize log2(block_size) (15, 16, or 17)
|
||||
12 #uint64 @size Uncompressed file size
|
||||
20 (4 bytes) - Padding. Ignored
|
||||
|
||||
So its size is 24.
|
||||
|
||||
Readers shall be able to handle log2(block_size) values 15, 16 and 17
|
||||
i.e. block sizes 32 kB, 64 kB, and 128 kB. Writers must not use
|
||||
other sizes.
|
||||
|
||||
Block Pointers
|
||||
|
||||
There are ceil(input_size / block_size) input resp. output blocks.
|
||||
Each input block is of fixed size whereas the output blocks have varying
|
||||
size (down to 0). For each output block there is an offset pointer giving
|
||||
its byte address in the overall file content. The next block pointer in the
|
||||
array tells the start of the next block which begins immediately after the
|
||||
end of its predecessor. A final pointer (*eob*) gives the first invalid
|
||||
byte address and thus marks the end of the last block.
|
||||
|
||||
So there are ceil(input_size / block_size) + 1 block pointers.
|
||||
They are stored directly after the file header, i.e. beginning at byte 24,
|
||||
as an array of values in #uint64 format (8 bytes).
|
||||
|
||||
Legacy format (zisofs) may be used, which is described in section *LEGACY*
|
||||
|
||||
|
||||
|
||||
Data Part
|
||||
|
||||
The data part begins immediately after the pointer array (*eob*). In
|
||||
principle it consists of the variable length output blocks as delivered by
|
||||
different compression algorithms when fed with the fixed size input blocks.
|
||||
|
||||
A special case of input and output block is defined:
|
||||
Zero-length blocks represent a block full of 0-bytes.
|
||||
Such input blocks do not get processed by compress2() but shall be mapped
|
||||
to 0-sized output directly. Vice versa 0-sized blocks have to bypass
|
||||
uncompress() when being read.
|
||||
|
||||
|
||||
ZF System Use Entry Format
|
||||
|
||||
The ZF entry follows the general layout of SUSP resp. RRIP.
|
||||
Its fields are:
|
||||
|
||||
[1] "BP 1 to BP 2 - Signature Word" shall be (5A)(46) ("ZF").
|
||||
|
||||
[2] "BP 3 - Length" shall specify as an 8-bit number the length in
|
||||
bytes of the ZF entry recorded according to ISO 9660:7.1.1.
|
||||
This length is 16 decimal.
|
||||
Refer to **LEGACY**
|
||||
|
||||
[3] "BP 4 - System Use Entry Version" shall be 2 as in ISO 9660:7.1.1.
|
||||
Refer to **LEGACY**
|
||||
|
||||
[4] "BP 5 to BP 6 - Algorithm" shall be two chars to indicate the
|
||||
compression algorithm. For example, (50)(5A) ("PZ")
|
||||
(This is a copy of @alg_char). Refer to **LEGACY**
|
||||
|
||||
[5] "BP 7 - Header Size Div 4" shall specify as an 8-bit number the
|
||||
number of 4-byte words in the header part of the file data recorded
|
||||
according to ISO 9660:7.1.1.
|
||||
(This is a copy of @hdr_size).
|
||||
|
||||
[6] "BP 8 - Log2 of Block Size" shall specify as an 8-bit number the
|
||||
binary logarithm of the compression block size recorded according to
|
||||
ISO 9660:7.1.1.
|
||||
(This is a copy of header byte 13 (@hdr_bsize), resp. header BP 14.
|
||||
The value has to be 15, 16 or 17 i.e. 32 kiB, 64 kiB, or 128 kiB.)
|
||||
|
||||
[7] "BP 9 to BP 16 - Virtual Uncompressed File Size" shall contain
|
||||
as a 64-bit unsigned little endian number the uncompressed
|
||||
file size represented by the given extent. Refer to **LEGACY**
|
||||
|
||||
|
||||
| 'Z' | 'F' | LENGTH | 2 | 'P' | 'Z' | HEADER SIZE DIV 4 |
|
||||
| LOG2 BLOCK SIZE | UNCOMPRESSED SIZE |
|
||||
|
||||
Example (block size 128 kiB, uncompressed file size = 40 TB):
|
||||
{ 'Z', 'F', 16, 2, 'P', 'Z', 8, 17,
|
||||
0x00, 0x80, 0xCA, 0x39, 0x61, 0x24, 0x00, 0x00 }
|
||||
|
||||
|
||||
Z2 System Use Entry Format
|
||||
|
||||
Linux kernels which are configured by CONFIG_ZISOFS to recognize zisofs
|
||||
but are not aware of zisofs2 will complain about ZF entries which announce
|
||||
algorithms other than "pz". The system log will show for each zisofs2
|
||||
compressed file at first stat(2) or open(2) a line like this:
|
||||
|
||||
isofs: Unknown ZF compression algorithm: PZ
|
||||
|
||||
To avoid these complaints, it is possible to use
|
||||
|
||||
[1] "BP 1 to BP 2 - Signature Word" shall be (5A)(32) ("Z2").
|
||||
|
||||
instead of "ZF" with the System Use Entry Format specified above.
|
||||
Everything else shall be like in ZF format version 2, including the version
|
||||
number itself:
|
||||
|
||||
[3] "BP 4 - System Use Entry Version" shall be 2 as in ISO 9660:7.1.1.
|
||||
|
||||
|
||||
**LEGACY**
|
||||
|
||||
zisofs2 supports old readers by respecting the zisofs format. This section
|
||||
describes which definitions from zisofs2 must change to be compatible
|
||||
with zisofs.
|
||||
|
||||
- General behaviour
|
||||
The uncompressed size of a single zisofs compressed file is restricted
|
||||
to 4 GiB - 1. Larger files shall not be compressed.
|
||||
|
||||
- Supported algorithms
|
||||
Only algorithm Zlib with default strategy is supported.
|
||||
|
||||
- The file header must follow this structure:
|
||||
|
||||
Offset Type Identifier Contents
|
||||
0 (8 bytes) @hdr_magic Magic number (37 E4 53 96 C9 DB D6 07)
|
||||
8 7.3.1 @size Uncompressed file size
|
||||
12 7.1.1 @hdr_size header_size >> 2 (4)
|
||||
13 7.1.1 @hdr_bsize log2(block_size) (15, 16, or 17)
|
||||
14 (2 bytes) - Reserved, must be zero
|
||||
|
||||
So its size is 16.
|
||||
|
||||
- Block pointers
|
||||
The array must use ISO 9660:7.3.1 (4 bytes) values.
|
||||
|
||||
- ZF entry
|
||||
|
||||
Its fields are:
|
||||
|
||||
[1] "BP 1 to BP 2 - Signature Word" shall be (5A)(46) ("ZF").
|
||||
|
||||
[2] "BP 3 - Length" must be 16 decimal.
|
||||
|
||||
[3] "BP 4 - System Use Entry Version" must be 1.
|
||||
|
||||
[4] "BP 5 to BP 6 - Algorithm" must be (70)(7A) ("pz").
|
||||
|
||||
[5] "BP 7 - Header Size Div 4" - same as zisofs2.
|
||||
|
||||
[6] "BP 8 - Log2 of Block Size" - same as zisofs2.
|
||||
|
||||
[7] "BP 9 to BP 16 - Uncompressed Size" This field shall be recorded
|
||||
according to ISO 9660:7.3.3.
|
||||
(This number is the same as @size )
|
||||
|
||||
| 'Z' | 'F' | LENGTH | 1 | 'p' | 'z' | HEADER SIZE DIV 4 |
|
||||
| LOG2 BLOCK SIZE | UNCOMPRESSED SIZE |
|
||||
|
||||
Example (block size 32 kiB, uncompressed file size = 1,234,567 bytes):
|
||||
{ 'Z', 'F', 16, 1, 'p', 'z', 4, 15,
|
||||
0x87, 0xD6, 0x12, 0x00, 0x00, 0x12, 0xD6, 0x87 }
|
||||
|
||||
|
||||
References:
|
||||
|
||||
zisofs2-tools
|
||||
https://github.com/vk496/zisofs2-tools
|
||||
|
||||
zisofs-tools
|
||||
http://freshmeat.net/projects/zisofs-tools/
|
||||
|
||||
zlib:
|
||||
/usr/include/zlib.h
|
||||
|
||||
cdrtools with mkisofs
|
||||
ftp://ftp.berlios.de/pub/cdrecord/alpha
|
||||
|
||||
ECMA-119 aka ISO 9660
|
||||
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-119.pdf
|
||||
|
||||
SUSP 1.12
|
||||
ftp://ftp.ymi.com/pub/rockridge/susp112.ps
|
||||
|
||||
RRIP 1.12
|
||||
ftp://ftp.ymi.com/pub/rockridge/rrip112.ps
|
||||
|
||||
zisofs version 1
|
||||
libisofs-*/doc/zisofs_format.txt
|
||||
https://dev.lovelyhq.com/libburnia/libisofs/raw/branch/master/doc/zisofs_format.txt
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
This text is under
|
||||
Copyright (c) 2009 - 2010, 2020 Thomas SCHMITT <scdbackup@gmx.net>
|
||||
Copyright (c) 2020 - Valentín KIVACHUK BURDÁ <vk18496@gmail.com>
|
||||
It shall reflect the effective technical specifications as implemented in
|
||||
zisofs2-tools and the Linux kernel. So please contact mailing list
|
||||
<bug-xorriso@gnu.org> or to the copyright holders in private, if you
|
||||
want to make changes.
|
||||
Only if you cannot reach the copyright holder for at least one month it is
|
||||
permissible to modify and distribute this text under the license "GPLv3".
|
||||
|
|
@ -37,7 +37,7 @@ i.e. block sizes 32 kB, 64 kB, and 128 kB. Writers must not use other sizes.
|
|||
|
||||
Block Pointers
|
||||
|
||||
There are ceil(input_size / block_size) input resp. output blocks.
|
||||
There are ceil(input_size / block_size) input and output blocks.
|
||||
Each input block is of fixed size whereas the output blocks have varying
|
||||
size (down to 0). For each output block there is an offset pointer giving
|
||||
its byte address in the overall file content. The next block pointer in the
|
||||
|
@ -68,7 +68,7 @@ when being read.
|
|||
ZF may only be applied to files with a single extent and less than 4 GiB of
|
||||
uncompressed size.
|
||||
|
||||
The ZF entry follows the general layout of SUSP resp. RRIP.
|
||||
The ZF entry follows the general layout of SUSP and RRIP.
|
||||
Its fields are:
|
||||
|
||||
[1] "BP 1 to BP 2 - Signature Word" shall be (5A)(46) ("ZF").
|
||||
|
@ -85,19 +85,18 @@ Its fields are:
|
|||
[5] "BP 7 - Header Size Div 4" shall specify as an 8-bit number the number of
|
||||
4-byte words in the header part of the file data recorded according
|
||||
to ISO 9660:7.1.1.
|
||||
(This is a copy of header byte 12, resp. header BP 13).
|
||||
(This is a copy of header byte 12 / BP 13).
|
||||
|
||||
[6] "BP 8 - Log2 of Block Size" shall specify as an 8-bit number the binary
|
||||
logarithm of the compression block size recorded according to
|
||||
ISO 9660:7.1.1.
|
||||
(This is a copy of header byte 13, resp. header BP 14.
|
||||
(This is a copy of header byte 13 / BP 14.
|
||||
The value has to be 15, 16 or 17 i.e. 32 kiB, 64 kiB, or 128 kiB.)
|
||||
|
||||
[7] "BP 9 to BP 16 - Uncompressed Size" shall tell the number of uncompressed
|
||||
bytes represented by the given extent. This field shall be recorded
|
||||
according to ISO 9660:7.3.3.
|
||||
(This number is the same as in header bytes 8 to 11, resp header BP 9
|
||||
to BP 12.)
|
||||
(This number is the same as in header bytes 8 to 11 / BP 9 to BP 12.)
|
||||
|
||||
| 'Z' | 'F' | LENGTH | 1 | 'p' | 'z' | HEADER SIZE DIV 4 | LOG2 BLOCK SIZE
|
||||
| UNCOMPRESSED SIZE |
|
||||
|
|
|
@ -11,7 +11,12 @@
|
|||
|
||||
To be included by aaip_0_2.c
|
||||
|
||||
Copyright (c) 2009 - 2011 Thomas Schmitt, libburnia project, GPLv2+
|
||||
Copyright (c) 2009 - 2011 Thomas Schmitt
|
||||
|
||||
This file is part of the libisofs project; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
or later as published by the Free Software Foundation.
|
||||
See COPYING file for details.
|
||||
|
||||
*/
|
||||
|
||||
|
@ -39,7 +44,7 @@
|
|||
It is permissibile to set them to 1 already now.
|
||||
bit8 and higher: reserved, submit 0
|
||||
@return
|
||||
Bitfield corresponding to flag. If bits are set, th
|
||||
Bitfield corresponding to flag.
|
||||
bit0= ACL adapter is enabled
|
||||
bit1= xattr adapter is enabled
|
||||
bit2 - bit7= Reserved for future types.
|
||||
|
@ -99,10 +104,14 @@ int aaip_set_acl_text(char *path, char *text, int flag)
|
|||
-7 support of ACL not enabled at compile time
|
||||
*/
|
||||
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||
size_t *value_lengths, char **values, int flag)
|
||||
size_t *value_lengths, char **values, int *errnos,
|
||||
int flag)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for(i= 0; i < num_attrs; i++)
|
||||
errnos[i]= 0;
|
||||
|
||||
for(i= 0; i < num_attrs; i++) {
|
||||
if(names[i] == NULL || values[i] == NULL)
|
||||
continue;
|
||||
|
|
|
@ -5,9 +5,14 @@
|
|||
Arbitrary Attribute Interchange Protocol , system adapter for getting and
|
||||
setting of ACLs and xattr.
|
||||
|
||||
To be included by aaip_0_2.c
|
||||
To be included by aaip_0_2.c for FreeBSD, NetBSD, and OpenBSD
|
||||
|
||||
Copyright (c) 2009 - 2011 Thomas Schmitt, libburnia project, GPLv2+
|
||||
Copyright (c) 2009 - 2016 Thomas Schmitt
|
||||
|
||||
This file is part of the libisofs project; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
or later as published by the Free Software Foundation.
|
||||
See COPYING file for details.
|
||||
|
||||
*/
|
||||
|
||||
|
@ -32,6 +37,8 @@
|
|||
#include <sys/extattr.h>
|
||||
#endif
|
||||
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
/* <<< Use old ACL adapter code that is unable to deal with extattr */
|
||||
/* # define Libisofs_old_freebsd_acl_adapteR */
|
||||
|
||||
|
@ -47,7 +54,7 @@
|
|||
It is permissibile to set them to 1 already now.
|
||||
bit8 and higher: reserved, submit 0
|
||||
@return
|
||||
Bitfield corresponding to flag. If bits are set, th
|
||||
Bitfield corresponding to flag.
|
||||
bit0= ACL adapter is enabled
|
||||
bit1= xattr adapter is enabled
|
||||
bit2 - bit7= Reserved for future types.
|
||||
|
@ -70,6 +77,32 @@ int aaip_local_attr_support(int flag)
|
|||
}
|
||||
|
||||
|
||||
#ifdef Libisofs_with_freebsd_extattR
|
||||
|
||||
static int aaip_extattr_path_supp(char *path, int flag)
|
||||
{
|
||||
|
||||
#ifdef MNT_EXTATTR
|
||||
|
||||
int ret;
|
||||
struct statvfs statvfs_buf;
|
||||
|
||||
ret = statvfs(path, &statvfs_buf);
|
||||
if(ret == -1)
|
||||
return(1);
|
||||
return(!!(statvfs_buf.f_flag & MNT_EXTATTR));
|
||||
|
||||
#else /* MNT_EXTATTR */
|
||||
|
||||
return(1);
|
||||
|
||||
#endif /* ! MNT_EXTATTR */
|
||||
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_freebsd_extattR */
|
||||
|
||||
|
||||
/* ------------------------------ Getters --------------------------------- */
|
||||
|
||||
/* Obtain the ACL of the given file in long text form.
|
||||
|
@ -195,8 +228,17 @@ static int aaip_extattr_make_list(char *path, int attrnamespace,
|
|||
*list_size= extattr_list_file(path, attrnamespace, NULL, (size_t) 0);
|
||||
else
|
||||
*list_size= extattr_list_link(path, attrnamespace, NULL, (size_t) 0);
|
||||
if(*list_size == -1)
|
||||
if(*list_size == -1) {
|
||||
if(! aaip_extattr_path_supp(path, 0)) {
|
||||
*list_size = 0;
|
||||
return(2);
|
||||
}
|
||||
if(errno == EPERM && attrnamespace == EXTATTR_NAMESPACE_SYSTEM) {
|
||||
*list_size = 0;
|
||||
return(3);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
if(*list_size == 0)
|
||||
return(2);
|
||||
*list= calloc(*list_size, 1);
|
||||
|
@ -279,6 +321,54 @@ static int aaip_extattr_make_namelist(char *path, char *attrnamespace,
|
|||
return(1);
|
||||
}
|
||||
|
||||
|
||||
static int get_single_attr(char *path, char *name, size_t *value_length,
|
||||
char **value_bytes, int flag)
|
||||
{
|
||||
char *namept;
|
||||
int attrnamespace;
|
||||
ssize_t value_ret;
|
||||
|
||||
*value_bytes= NULL;
|
||||
*value_length= 0;
|
||||
if(strncmp(name, "user.", 5) == 0) {
|
||||
attrnamespace= EXTATTR_NAMESPACE_USER;
|
||||
namept= name + 5;
|
||||
} else {
|
||||
if(!(flag & 8))
|
||||
return(0);
|
||||
attrnamespace= EXTATTR_NAMESPACE_SYSTEM;
|
||||
namept= name + 7;
|
||||
}
|
||||
/* Predict length of value */
|
||||
if(flag & 32) /* follow link */
|
||||
value_ret= extattr_get_file(path, attrnamespace, namept, NULL, (size_t) 0);
|
||||
else
|
||||
value_ret= extattr_get_link(path, attrnamespace, namept, NULL, (size_t) 0);
|
||||
if(value_ret == -1)
|
||||
return(0);
|
||||
|
||||
*value_bytes= calloc(value_ret + 1, 1);
|
||||
if(*value_bytes == NULL)
|
||||
return(-1);
|
||||
|
||||
/* Obtain value */
|
||||
if(flag & 32) /* follow link */
|
||||
value_ret= extattr_get_file(path, attrnamespace, namept,
|
||||
*value_bytes, (size_t) value_ret);
|
||||
else
|
||||
value_ret= extattr_get_link(path, attrnamespace, namept,
|
||||
*value_bytes, (size_t) value_ret);
|
||||
if(value_ret == -1) {
|
||||
free(*value_bytes);
|
||||
*value_bytes= NULL;
|
||||
*value_length= 0;
|
||||
return(0);
|
||||
}
|
||||
*value_length= value_ret;
|
||||
return(1);
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_freebsd_extattR */
|
||||
|
||||
|
||||
|
@ -287,7 +377,7 @@ static int aaip_extattr_make_namelist(char *path, char *attrnamespace,
|
|||
@param path Path to the file
|
||||
@param num_attrs Will return the number of name-value pairs
|
||||
@param names Will return an array of pointers to 0-terminated names
|
||||
@param value_lengths Will return an arry with the lenghts of values
|
||||
@param value_lengths Will return an array with the lengths of values
|
||||
@param values Will return an array of pointers to 8-bit values
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= obtain ACL (access and eventually default)
|
||||
|
@ -299,7 +389,8 @@ static int aaip_extattr_make_namelist(char *path, char *attrnamespace,
|
|||
bit4= do not return trivial ACL that matches st_mode
|
||||
bit5= in case of symbolic link: inquire link target
|
||||
bit15= free memory of names, value_lengths, values
|
||||
@return >0 ok
|
||||
@return 1 ok
|
||||
2 ok, no permission to inspect non-user namespaces
|
||||
<=0 error
|
||||
-1= out of memory
|
||||
-2= program error with prediction of result size
|
||||
|
@ -309,7 +400,7 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
|||
size_t **value_lengths, char ***values, int flag)
|
||||
{
|
||||
int ret;
|
||||
ssize_t i, num_names= 0, acl_names= 0;
|
||||
ssize_t i, num_names= 0;
|
||||
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
unsigned char *a_acl= NULL;
|
||||
|
@ -317,11 +408,12 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
|||
size_t a_acl_len= 0;
|
||||
#endif
|
||||
#ifdef Libisofs_with_freebsd_extattR
|
||||
char *list= NULL, *user_list= NULL, *sys_list= NULL, *namept;
|
||||
ssize_t value_ret, retry= 0, list_size= 0, user_list_size= 0;
|
||||
char *list= NULL, *user_list= NULL, *sys_list= NULL;
|
||||
ssize_t value_ret, list_size= 0, user_list_size= 0;
|
||||
ssize_t sys_list_size= 0;
|
||||
int attrnamespace;
|
||||
int acl_names= 0;
|
||||
#endif
|
||||
int no_perm_for_system= 0;
|
||||
|
||||
if(flag & (1 << 15)) { /* Free memory */
|
||||
{ret= 1; goto ex;}
|
||||
|
@ -357,6 +449,8 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
|||
&sys_list, &sys_list_size, flag & 32);
|
||||
if(ret <= 0)
|
||||
{ret= -1; goto ex;}
|
||||
if(ret == 3)
|
||||
no_perm_for_system= 1;
|
||||
}
|
||||
|
||||
/* Check for NUL in names, convert into a linuxish list of namespace.name */
|
||||
|
@ -375,7 +469,11 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
|||
#ifdef Libisofs_with_aaip_acL
|
||||
if(flag & 1) {
|
||||
num_names++;
|
||||
|
||||
#ifdef Libisofs_with_freebsd_extattR
|
||||
acl_names= 1;
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -407,45 +505,10 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
|||
}
|
||||
|
||||
for(i= 0; (size_t) i < *num_attrs; i++) {
|
||||
if(strncmp((*names)[i], "user.", 5) == 0) {
|
||||
attrnamespace= EXTATTR_NAMESPACE_USER;
|
||||
namept= (*names)[i] + 5;
|
||||
} else {
|
||||
if(!(flag & 8))
|
||||
continue;
|
||||
attrnamespace= EXTATTR_NAMESPACE_SYSTEM;
|
||||
namept= (*names)[i] + 7;
|
||||
}
|
||||
/* Predict length of value */
|
||||
if(flag & 32) /* follow link */
|
||||
value_ret= extattr_get_file(path, attrnamespace, namept,
|
||||
NULL, (size_t) 0);
|
||||
else
|
||||
value_ret= extattr_get_link(path, attrnamespace, namept,
|
||||
NULL, (size_t) 0);
|
||||
if(value_ret == -1)
|
||||
continue;
|
||||
|
||||
(*values)[i]= calloc(value_ret + 1, 1);
|
||||
if((*values)[i] == NULL)
|
||||
value_ret= get_single_attr(path, (*names)[i], *value_lengths + i,
|
||||
*values + i, flag & (8 | 32));
|
||||
if(value_ret <= 0)
|
||||
{ret= -1; goto ex;}
|
||||
|
||||
/* Obtain value */
|
||||
if(flag & 32) /* follow link */
|
||||
value_ret= extattr_get_file(path, attrnamespace, namept,
|
||||
(*values)[i], (size_t) value_ret);
|
||||
else
|
||||
value_ret= extattr_get_link(path, attrnamespace, namept,
|
||||
(*values)[i], (size_t) value_ret);
|
||||
if(value_ret == -1) { /* there could be a race condition */
|
||||
|
||||
if(retry++ > 5)
|
||||
{ret= -1; goto ex;}
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
(*value_lengths)[i]= value_ret;
|
||||
retry= 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -456,8 +519,11 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
|||
if(flag & 1) { /* Obtain ACL */
|
||||
/* access-ACL */
|
||||
aaip_get_acl_text(path, &a_acl_text, flag & (16 | 32));
|
||||
if(a_acl_text == NULL)
|
||||
{ret= 1; goto ex;} /* empty ACL / only st_mode info was found in ACL */
|
||||
if(a_acl_text == NULL) {
|
||||
/* empty ACL / only st_mode info was found in ACL */
|
||||
ret= 1 + no_perm_for_system;
|
||||
goto ex;
|
||||
}
|
||||
ret= aaip_encode_acl(a_acl_text, (mode_t) 0, &a_acl_len, &a_acl, flag & 2);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
|
@ -476,7 +542,7 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
|||
|
||||
#endif /* Libisofs_with_aaip_acL */
|
||||
|
||||
ret= 1;
|
||||
ret= 1 + no_perm_for_system;
|
||||
ex:;
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
if(a_acl != NULL)
|
||||
|
@ -525,7 +591,7 @@ ex:;
|
|||
@param path Path to the file
|
||||
@param num_attrs Will return the number of name-value pairs
|
||||
@param names Will return an array of pointers to 0-terminated names
|
||||
@param value_lengths Will return an arry with the lenghts of values
|
||||
@param value_lengths Will return an array with the lengths of values
|
||||
@param values Will return an array of pointers to 8-bit values
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= obtain ACL (access and eventually default)
|
||||
|
@ -654,7 +720,7 @@ ex:;
|
|||
0 no suitable ACL manipulation adapter available
|
||||
-1 failure of system ACL service (see errno)
|
||||
-2 attempt to manipulate ACL of a symbolic link
|
||||
without bit5 resp. with no suitable link target
|
||||
without bit5 or with no suitable link target
|
||||
*/
|
||||
int aaip_set_acl_text(char *path, char *text, int flag)
|
||||
{
|
||||
|
@ -735,6 +801,15 @@ static int aaip_extattr_delete_names(char *path, int attrnamespace,
|
|||
#endif /* Libisofs_with_freebsd_extattR */
|
||||
|
||||
|
||||
static void register_errno(int *errnos, int i, int in_errno)
|
||||
{
|
||||
if(in_errno > 0)
|
||||
errnos[i]= in_errno;
|
||||
else
|
||||
errnos[i]= -1;
|
||||
}
|
||||
|
||||
|
||||
/* Bring the given attributes and/or ACLs into effect with the given file.
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= decode and set ACLs
|
||||
|
@ -746,6 +821,8 @@ static int aaip_extattr_delete_names(char *path, int attrnamespace,
|
|||
bit5= in case of symbolic link: manipulate link target
|
||||
bit6= tolerate inappropriate presence or absence of
|
||||
directory default ACL
|
||||
bit7= void setting a name value pair if it already
|
||||
exists and has the desired value.
|
||||
@return 1 success
|
||||
-1 error memory allocation
|
||||
-2 error with decoding of ACL
|
||||
|
@ -758,17 +835,23 @@ static int aaip_extattr_delete_names(char *path, int attrnamespace,
|
|||
ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other::
|
||||
*/
|
||||
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||
size_t *value_lengths, char **values, int flag)
|
||||
size_t *value_lengths, char **values,
|
||||
int *errnos, int flag)
|
||||
{
|
||||
int ret, has_default_acl= 0;
|
||||
int ret, has_default_acl= 0, end_ret= 1;
|
||||
size_t i, consumed, acl_text_fill, acl_idx= 0;
|
||||
char *acl_text= NULL;
|
||||
#ifdef Libisofs_with_freebsd_extattR
|
||||
char *user_list= NULL, *sys_list= NULL, *namept;
|
||||
ssize_t user_list_size= 0, sys_list_size= 0;
|
||||
char *user_list= NULL, *sys_list= NULL, *namept, *old_value;
|
||||
ssize_t user_list_size= 0, sys_list_size= 0, value_ret;
|
||||
int attrnamespace;
|
||||
size_t old_value_l;
|
||||
int skip;
|
||||
#endif
|
||||
|
||||
for(i= 0; i < num_attrs; i++)
|
||||
errnos[i]= 0;
|
||||
|
||||
#ifdef Libisofs_with_freebsd_extattR
|
||||
|
||||
if(flag & 2) { /* Delete all file attributes */
|
||||
|
@ -817,16 +900,35 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||
attrnamespace= EXTATTR_NAMESPACE_SYSTEM;
|
||||
namept= names[i] + 7;
|
||||
} else {
|
||||
{ret= -8; goto ex;}
|
||||
register_errno(errnos, i, (int) EFAULT);
|
||||
end_ret= -8;
|
||||
continue;
|
||||
}
|
||||
skip= 0;
|
||||
if(flag & 128) {
|
||||
value_ret= get_single_attr(path, names[i], &old_value_l,
|
||||
&old_value, flag & (8 | 32));
|
||||
if(value_ret > 0 && old_value_l == value_lengths[i]) {
|
||||
if(memcmp(old_value, values[i], value_lengths[i]) == 0)
|
||||
skip= 1;
|
||||
}
|
||||
if(old_value != NULL)
|
||||
free(old_value);
|
||||
}
|
||||
if(!skip) {
|
||||
if(flag & 32)
|
||||
ret= extattr_set_file(path, attrnamespace, namept,
|
||||
values[i], value_lengths[i]);
|
||||
else
|
||||
ret= extattr_set_link(path, attrnamespace, namept,
|
||||
values[i], value_lengths[i]);
|
||||
if(ret == -1) {
|
||||
register_errno(errnos, i, errno);
|
||||
if(end_ret != 1)
|
||||
end_ret= -4;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(flag & 32)
|
||||
ret= extattr_set_file(path, attrnamespace, namept,
|
||||
values[i], value_lengths[i]);
|
||||
else
|
||||
ret= extattr_set_link(path, attrnamespace, namept,
|
||||
values[i], value_lengths[i]);
|
||||
if(ret == -1)
|
||||
{ret= -4; goto ex;}
|
||||
|
||||
#else
|
||||
|
||||
|
@ -841,8 +943,12 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||
}
|
||||
|
||||
/* Decode ACLs */
|
||||
/* It is important that this happens after restoring xattr which might be
|
||||
representations of ACL, too. If isofs ACL are enabled, then they shall
|
||||
override the xattr ones.
|
||||
*/
|
||||
if(acl_idx == 0)
|
||||
{ret= 1; goto ex;}
|
||||
{ret= end_ret; goto ex;}
|
||||
i= acl_idx - 1;
|
||||
|
||||
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
||||
|
@ -864,6 +970,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
ret= aaip_set_acl_text(path, acl_text, flag & (32 | 64));
|
||||
if(ret == -1)
|
||||
register_errno(errnos, i, errno);
|
||||
if(ret <= 0)
|
||||
{ret= -3; goto ex;}
|
||||
#else
|
||||
|
@ -873,7 +981,7 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||
if(has_default_acl && !(flag & 64))
|
||||
{ret= -3; goto ex;}
|
||||
|
||||
ret= 1;
|
||||
ret= end_ret;
|
||||
ex:;
|
||||
if(acl_text != NULL)
|
||||
free(acl_text);
|
||||
|
|
|
@ -5,9 +5,14 @@
|
|||
Arbitrary Attribute Interchange Protocol , system adapter for getting and
|
||||
setting of ACLs and xattr.
|
||||
|
||||
To be included by aaip_0_2.c
|
||||
To be included by aaip_0_2.c for Linux
|
||||
|
||||
Copyright (c) 2009 - 2011 Thomas Schmitt, libburnia project, GPLv2+
|
||||
Copyright (c) 2009 - 2022 Thomas Schmitt
|
||||
|
||||
This file is part of the libisofs project; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
or later as published by the Free Software Foundation.
|
||||
See COPYING file for details.
|
||||
|
||||
*/
|
||||
|
||||
|
@ -30,8 +35,12 @@
|
|||
#endif
|
||||
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
#ifdef Libisofs_with_sys_xattR
|
||||
#include <sys/xattr.h>
|
||||
#else
|
||||
#include <attr/xattr.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* ------------------------------ Inquiry --------------------------------- */
|
||||
|
@ -68,6 +77,44 @@ int aaip_local_attr_support(int flag)
|
|||
}
|
||||
|
||||
|
||||
/* -------------------------- Error reporting ----------------------------- */
|
||||
|
||||
|
||||
/* Report an error with local ACL or xattr calls.
|
||||
@param flag bit0-7: mode 0=NO_GET_LOCAL , 1=NO_SET_LOCAL
|
||||
*/
|
||||
static
|
||||
void aaip_local_error(char *function_name, char *path, int err, int flag)
|
||||
{
|
||||
int mode, err_code;
|
||||
|
||||
mode= (flag & 255);
|
||||
if(mode == 1)
|
||||
err_code= ISO_AAIP_NO_SET_LOCAL_S;
|
||||
else
|
||||
err_code= ISO_AAIP_NO_GET_LOCAL_S;
|
||||
if(err > 0) {
|
||||
if(path[0])
|
||||
iso_msg_submit(-1, err_code, 0,
|
||||
"Function %s(\"%s\") failed with errno %d '%s'",
|
||||
function_name, path, err, strerror(err));
|
||||
else
|
||||
iso_msg_submit(-1, err_code, 0, "Function %s() failed with %d '%s'",
|
||||
function_name, err, strerror(err));
|
||||
} else {
|
||||
if(path[0])
|
||||
iso_msg_submit(-1, err_code, 0,
|
||||
"Function %s(\"%s\") failed without error code",
|
||||
function_name, path);
|
||||
else
|
||||
iso_msg_submit(-1, err_code, 0,
|
||||
"Function %s() failed without error code",
|
||||
function_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------ Getters --------------------------------- */
|
||||
|
||||
/* Obtain the ACL of the given file in long text form.
|
||||
|
@ -89,7 +136,7 @@ int aaip_local_attr_support(int flag)
|
|||
or filesystem does not support ACL
|
||||
-1 failure of system ACL service (see errno)
|
||||
-2 attempt to inquire ACL of a symbolic link without
|
||||
bit4 or bit5 resp. with no suitable link target
|
||||
bit4 or bit5 or with no suitable link target
|
||||
*/
|
||||
int aaip_get_acl_text(char *path, char **text, int flag)
|
||||
{
|
||||
|
@ -159,12 +206,50 @@ int aaip_get_acl_text(char *path, char **text, int flag)
|
|||
}
|
||||
|
||||
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
|
||||
static int get_single_attr(char *path, char *name, size_t *value_length,
|
||||
char **value_bytes, int flag)
|
||||
{
|
||||
ssize_t value_ret;
|
||||
|
||||
*value_bytes= NULL;
|
||||
*value_length= 0;
|
||||
if(flag & 32)
|
||||
value_ret= getxattr(path, name, NULL, 0);
|
||||
else
|
||||
value_ret= lgetxattr(path, name, NULL, 0);
|
||||
if(value_ret == -1) {
|
||||
aaip_local_error((flag & 32) ? "getxattr" : "lgetxattr", path, errno, 0);
|
||||
return(0);
|
||||
}
|
||||
*value_bytes= calloc(value_ret + 1, 1);
|
||||
if(*value_bytes == NULL)
|
||||
return(-1);
|
||||
if(flag & 32)
|
||||
value_ret= getxattr(path, name, *value_bytes, value_ret);
|
||||
else
|
||||
value_ret= lgetxattr(path, name, *value_bytes, value_ret);
|
||||
if(value_ret == -1) {
|
||||
aaip_local_error((flag & 32) ? "getxattr" : "lgetxattr", path, errno, 0);
|
||||
free(*value_bytes);
|
||||
*value_bytes= NULL;
|
||||
*value_length= 0;
|
||||
return(0);
|
||||
}
|
||||
*value_length= value_ret;
|
||||
return(1);
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_aaip_xattR */
|
||||
|
||||
|
||||
/* Obtain the Extended Attributes and/or the ACLs of the given file in a form
|
||||
that is ready for aaip_encode().
|
||||
@param path Path to the file
|
||||
@param num_attrs Will return the number of name-value pairs
|
||||
@param names Will return an array of pointers to 0-terminated names
|
||||
@param value_lengths Will return an arry with the lenghts of values
|
||||
@param value_lengths Will return an array with the lengths of values
|
||||
@param values Will return an array of pointers to 8-bit values
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= obtain ACL (access and eventually default)
|
||||
|
@ -176,7 +261,9 @@ int aaip_get_acl_text(char *path, char **text, int flag)
|
|||
bit4= do not return trivial ACL that matches st_mode
|
||||
bit5= in case of symbolic link: inquire link target
|
||||
bit15= free memory of names, value_lengths, values
|
||||
@return >0 ok
|
||||
@return 1 ok
|
||||
(reserved for FreeBSD: 2 ok, no permission to inspect
|
||||
non-user namespaces.)
|
||||
<=0 error
|
||||
-1= out of memory
|
||||
-2= program error with prediction of result size
|
||||
|
@ -186,16 +273,20 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
|||
size_t **value_lengths, char ***values, int flag)
|
||||
{
|
||||
int ret;
|
||||
ssize_t i, num_names= 0;
|
||||
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
unsigned char *acl= NULL;
|
||||
char *a_acl_text= NULL, *d_acl_text= NULL;
|
||||
size_t acl_len= 0;
|
||||
#define Libisofs_aaip_get_attr_activE yes
|
||||
#endif
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
char *list= NULL;
|
||||
ssize_t value_ret, retry= 0, list_size= 0;
|
||||
ssize_t value_ret, list_size= 0;
|
||||
#define Libisofs_aaip_get_attr_activE yes
|
||||
#endif
|
||||
#ifdef Libisofs_aaip_get_attr_activE
|
||||
ssize_t i, num_names= 0;
|
||||
#endif
|
||||
|
||||
if(flag & (1 << 15)) { /* Free memory */
|
||||
|
@ -207,6 +298,14 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
|||
*value_lengths= NULL;
|
||||
*values= NULL;
|
||||
|
||||
#ifndef Libisofs_aaip_get_attr_activE
|
||||
|
||||
ret = 1;
|
||||
ex:;
|
||||
return ret;
|
||||
|
||||
#else /* Libisofs_aaip_get_attr_activE */
|
||||
|
||||
/* Set up arrays */
|
||||
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
|
@ -217,10 +316,13 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
|||
else
|
||||
list_size= llistxattr(path, list, 0);
|
||||
if(list_size == -1) {
|
||||
if(errno == ENOSYS) /* Function not implemented */
|
||||
if(errno == ENOSYS) { /* Function not implemented */
|
||||
list_size= 0; /* Handle as if xattr was disabled at compile time */
|
||||
else
|
||||
} else {
|
||||
aaip_local_error((flag & 32) ? "listxattr" : "llistxattr", path, errno,
|
||||
0);
|
||||
{ret= -1; goto ex;}
|
||||
}
|
||||
}
|
||||
if(list_size > 0) {
|
||||
list= calloc(list_size, 1);
|
||||
|
@ -230,8 +332,11 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
|||
list_size= listxattr(path, list, list_size);
|
||||
else
|
||||
list_size= llistxattr(path, list, list_size);
|
||||
if(list_size == -1)
|
||||
if(list_size == -1) {
|
||||
aaip_local_error((flag & 32) ? "listxattr" : "llistxattr", path, errno,
|
||||
0);
|
||||
{ret= -1; goto ex;}
|
||||
}
|
||||
}
|
||||
for(i= 0; i < list_size; i+= strlen(list + i) + 1)
|
||||
num_names++;
|
||||
|
@ -276,27 +381,10 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
|||
if(!(flag & 8))
|
||||
if(strncmp((*names)[i], "user.", 5))
|
||||
continue;
|
||||
if(flag & 32)
|
||||
value_ret= getxattr(path, (*names)[i], NULL, 0);
|
||||
else
|
||||
value_ret= lgetxattr(path, (*names)[i], NULL, 0);
|
||||
if(value_ret == -1)
|
||||
continue;
|
||||
(*values)[i]= calloc(value_ret + 1, 1);
|
||||
if((*values)[i] == NULL)
|
||||
value_ret= get_single_attr(path, (*names)[i], *value_lengths + i,
|
||||
*values + i, flag & 32);
|
||||
if(value_ret <= 0)
|
||||
{ret= -1; goto ex;}
|
||||
if(flag & 32)
|
||||
value_ret= getxattr(path, (*names)[i], (*values)[i], value_ret);
|
||||
else
|
||||
value_ret= lgetxattr(path, (*names)[i], (*values)[i], value_ret);
|
||||
if(value_ret == -1) { /* there could be a race condition */
|
||||
if(retry++ > 5)
|
||||
{ret= -1; goto ex;}
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
(*value_lengths)[i]= value_ret;
|
||||
retry= 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -361,6 +449,9 @@ ex:;
|
|||
*num_attrs= 0;
|
||||
}
|
||||
return(ret);
|
||||
|
||||
#endif /* Libisofs_aaip_get_attr_activE */
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -377,7 +468,7 @@ ex:;
|
|||
0 ACL support not enabled at compile time
|
||||
-1 failure of system ACL service (see errno)
|
||||
-2 attempt to manipulate ACL of a symbolic link
|
||||
without bit5 resp. with no suitable link target
|
||||
without bit5 or with no suitable link target
|
||||
*/
|
||||
int aaip_set_acl_text(char *path, char *text, int flag)
|
||||
{
|
||||
|
@ -399,11 +490,14 @@ int aaip_set_acl_text(char *path, char *text, int flag)
|
|||
|
||||
acl= acl_from_text(text);
|
||||
if(acl == NULL) {
|
||||
aaip_local_error("acl_from_text", "", errno, 1);
|
||||
ret= -1; goto ex;
|
||||
}
|
||||
ret= acl_set_file(path, (flag & 1) ? ACL_TYPE_DEFAULT : ACL_TYPE_ACCESS, acl);
|
||||
if(ret == -1)
|
||||
if(ret == -1) {
|
||||
aaip_local_error("acl_set_file", path, errno, 1);
|
||||
goto ex;
|
||||
}
|
||||
ret= 1;
|
||||
ex:
|
||||
if(acl != NULL)
|
||||
|
@ -419,6 +513,15 @@ ex:
|
|||
}
|
||||
|
||||
|
||||
static void register_errno(int *errnos, int i)
|
||||
{
|
||||
if(errno > 0)
|
||||
errnos[i]= errno;
|
||||
else
|
||||
errnos[i]= -1;
|
||||
}
|
||||
|
||||
|
||||
/* Bring the given attributes and/or ACLs into effect with the given file.
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= decode and set ACLs
|
||||
|
@ -428,8 +531,10 @@ ex:
|
|||
I.e. those with a name which does not begin
|
||||
by "user."
|
||||
bit5= in case of symbolic link: manipulate link target
|
||||
bit6= tolerate inappropriate presence or absense of
|
||||
bit6= tolerate inappropriate presence or absence of
|
||||
directory default ACL
|
||||
bit7= avoid setting a name value pair if it already
|
||||
exists and has the desired value.
|
||||
@return 1 success
|
||||
-1 error memory allocation
|
||||
-2 error with decoding of ACL
|
||||
|
@ -442,14 +547,25 @@ ex:
|
|||
ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other::
|
||||
*/
|
||||
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||
size_t *value_lengths, char **values, int flag)
|
||||
size_t *value_lengths, char **values,
|
||||
int *errnos, int flag)
|
||||
{
|
||||
int ret, has_default_acl= 0;
|
||||
size_t i, consumed, acl_text_fill, acl_idx= 0, h_consumed;
|
||||
char *acl_text= NULL, *list= NULL;
|
||||
int ret, end_ret= 1;
|
||||
size_t i, consumed, acl_text_fill, acl_idx= 0;
|
||||
char *acl_text= NULL;
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
ssize_t list_size= 0;
|
||||
char *list= NULL, *old_value;
|
||||
ssize_t list_size= 0, value_ret;
|
||||
size_t old_value_l;
|
||||
int skip;
|
||||
#endif
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
size_t h_consumed;
|
||||
int has_default_acl= 0;
|
||||
#endif
|
||||
|
||||
for(i= 0; i < num_attrs; i++)
|
||||
errnos[i]= 0;
|
||||
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
|
||||
|
@ -467,8 +583,11 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||
list_size= listxattr(path, list, list_size);
|
||||
else
|
||||
list_size= llistxattr(path, list, list_size);
|
||||
if(list_size == -1)
|
||||
if(list_size == -1) {
|
||||
aaip_local_error((flag & 32) ? "listxattr" : "llistxattr", path, errno,
|
||||
1);
|
||||
{ret= -5; goto ex;}
|
||||
}
|
||||
for(i= 0; i < (size_t) list_size; i+= strlen(list + i) + 1) {
|
||||
if(!(flag & 8))
|
||||
if(strncmp(list + i, "user.", 5))
|
||||
|
@ -477,8 +596,11 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||
ret= removexattr(path, list + i);
|
||||
else
|
||||
ret= lremovexattr(path, list + i);
|
||||
if(ret == -1)
|
||||
if(ret == -1) {
|
||||
aaip_local_error((flag & 32) ? "removexattr" : "lremovexattr", path,
|
||||
errno, 1);
|
||||
{ret= -5; goto ex;}
|
||||
}
|
||||
}
|
||||
free(list); list= NULL;
|
||||
}
|
||||
|
@ -504,12 +626,30 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
|
||||
if(flag & 32)
|
||||
ret= setxattr(path, names[i], values[i], value_lengths[i], 0);
|
||||
else
|
||||
ret= lsetxattr(path, names[i], values[i], value_lengths[i], 0);
|
||||
if(ret == -1)
|
||||
{ret= -4; goto ex;}
|
||||
skip= 0;
|
||||
if(flag & 128) {
|
||||
value_ret= get_single_attr(path, names[i], &old_value_l,
|
||||
&old_value, flag & 32);
|
||||
if(value_ret > 0 && old_value_l == value_lengths[i]) {
|
||||
if(memcmp(old_value, values[i], value_lengths[i]) == 0)
|
||||
skip= 1;
|
||||
}
|
||||
if(old_value != NULL)
|
||||
free(old_value);
|
||||
}
|
||||
if(!skip) {
|
||||
if(flag & 32)
|
||||
ret= setxattr(path, names[i], values[i], value_lengths[i], 0);
|
||||
else
|
||||
ret= lsetxattr(path, names[i], values[i], value_lengths[i], 0);
|
||||
if(ret == -1) {
|
||||
aaip_local_error((flag & 32) ? "setxattr" : "lsetxattr", path, errno,
|
||||
1);
|
||||
register_errno(errnos, i);
|
||||
end_ret= -4;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
@ -519,9 +659,13 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||
|
||||
}
|
||||
|
||||
/* Decode ACLs */
|
||||
/* Decode ACLs */
|
||||
/* It is important that this happens after restoring xattr which might be
|
||||
representations of ACL, too. If isofs ACL are enabled, then they shall
|
||||
override the xattr ones.
|
||||
*/
|
||||
if(acl_idx == 0)
|
||||
{ret= 1; goto ex;}
|
||||
{ret= end_ret; goto ex;}
|
||||
i= acl_idx - 1;
|
||||
/* "access" ACL */
|
||||
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
||||
|
@ -539,15 +683,16 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||
goto ex;
|
||||
if(ret <= 0)
|
||||
{ret= -2; goto ex;}
|
||||
has_default_acl= (ret == 2);
|
||||
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
|
||||
has_default_acl= (ret == 2);
|
||||
|
||||
ret= aaip_set_acl_text(path, acl_text, flag & 32);
|
||||
if(ret == -1)
|
||||
register_errno(errnos, i);
|
||||
if(ret <= 0)
|
||||
{ret= -3; goto ex;}
|
||||
#else
|
||||
{ret= -7; goto ex;}
|
||||
#endif
|
||||
/* "default" ACL */
|
||||
if(has_default_acl) {
|
||||
free(acl_text);
|
||||
|
@ -570,6 +715,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||
if(ret <= 0)
|
||||
{ret= -2; goto ex;}
|
||||
ret= aaip_set_acl_text(path, acl_text, 1 | (flag & 32));
|
||||
if(ret == -1)
|
||||
register_errno(errnos, i);
|
||||
if(ret <= 0)
|
||||
{ret= -3; goto ex;}
|
||||
} else {
|
||||
|
@ -581,12 +728,23 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||
|
||||
}
|
||||
}
|
||||
ret= 1;
|
||||
ret= end_ret;
|
||||
|
||||
#else
|
||||
|
||||
ret= -7;
|
||||
|
||||
#endif /* !Libisofs_with_aaip_acL */
|
||||
|
||||
ex:;
|
||||
if(acl_text != NULL)
|
||||
free(acl_text);
|
||||
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
if(list != NULL)
|
||||
free(list);
|
||||
#endif
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,12 @@
|
|||
See libisofs/aaip_0_2.h
|
||||
http://libburnia-project.org/wiki/AAIP
|
||||
|
||||
Copyright (c) 2009 - 2011 Thomas Schmitt, libburnia project, GPLv2+
|
||||
Copyright (c) 2009 - 2019 Thomas Schmitt
|
||||
|
||||
This file is part of the libisofs project; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
or later as published by the Free Software Foundation.
|
||||
See COPYING file for details.
|
||||
|
||||
*/
|
||||
|
||||
|
@ -27,6 +32,7 @@
|
|||
|
||||
#include "libisofs.h"
|
||||
#include "util.h"
|
||||
#include "messages.h"
|
||||
|
||||
/*
|
||||
#define Aaip_encode_debuG 1
|
||||
|
@ -62,12 +68,12 @@
|
|||
#define Aaip_namespace_trusteD 0x05
|
||||
#define Aaip_namespace_securitY 0x06
|
||||
|
||||
static char Aaip_namespace_textS[][16]= {"", "", "system.", "user.", "isofs.",
|
||||
"trusted.", "security."};
|
||||
|
||||
/* maximum expansion: "security." */
|
||||
#define Aaip_max_name_expansioN 9
|
||||
|
||||
static char Aaip_namespace_textS[][Aaip_max_name_expansioN + 1]=
|
||||
{"", "", "system.", "user.", "isofs.", "trusted.", "security."};
|
||||
|
||||
/* --------------------------------- Encoder ---------------------------- */
|
||||
|
||||
|
||||
|
@ -88,26 +94,30 @@ static int aaip_encode_pair(char *name, size_t attr_length, char *attr,
|
|||
no longer needed
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= set CONTINUE bit of last AAIP field to 1
|
||||
@return >0 is the number of SUSP fields generated,
|
||||
0 means error
|
||||
@return >= 0 is the number of SUSP fields generated,
|
||||
< 0 means error
|
||||
*/
|
||||
size_t aaip_encode(size_t num_attrs, char **names,
|
||||
size_t *value_lengths, char **values,
|
||||
size_t *result_len, unsigned char **result, int flag)
|
||||
ssize_t aaip_encode(size_t num_attrs, char **names,
|
||||
size_t *value_lengths, char **values,
|
||||
size_t *result_len, unsigned char **result, int flag)
|
||||
{
|
||||
size_t mem_size= 0, comp_size, ret;
|
||||
size_t mem_size= 0, comp_size;
|
||||
ssize_t ret;
|
||||
unsigned int number_of_fields, i, num_recs;
|
||||
|
||||
/* Predict memory needs, number of SUSP fields and component records */
|
||||
*result = NULL;
|
||||
*result_len= 0;
|
||||
for(i= 0; i < num_attrs; i++) {
|
||||
ret= aaip_encode_pair(names[i], value_lengths[i], values[i],
|
||||
&num_recs, &comp_size, NULL, (size_t) 0, 1);
|
||||
if(ret <= 0)
|
||||
if(ret < 0)
|
||||
return(ret);
|
||||
mem_size+= comp_size;
|
||||
}
|
||||
number_of_fields= mem_size / 250 + !!(mem_size % 250);
|
||||
if(number_of_fields == 0)
|
||||
return(0);
|
||||
mem_size+= number_of_fields * 5;
|
||||
|
||||
#ifdef Aaip_encode_debuG
|
||||
|
@ -118,14 +128,18 @@ size_t aaip_encode(size_t num_attrs, char **names,
|
|||
#endif
|
||||
|
||||
if(*result == NULL)
|
||||
return 0;
|
||||
return ISO_OUT_OF_MEM;
|
||||
|
||||
/* Encode pairs into result */
|
||||
for(i= 0; i < num_attrs; i++) {
|
||||
ret= aaip_encode_pair(names[i], value_lengths[i], values[i],
|
||||
&num_recs, &comp_size, *result, *result_len, 0);
|
||||
if(ret <= 0)
|
||||
if(ret < 0) {
|
||||
free(*result);
|
||||
*result = NULL;
|
||||
*result_len = 0;
|
||||
return(ret);
|
||||
}
|
||||
(*result_len)+= comp_size;
|
||||
}
|
||||
|
||||
|
@ -267,6 +281,7 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
|||
bit2= this is a default ACL, prepend SWITCH_MARK
|
||||
bit3= check for completeness of list and eventually
|
||||
fill up with entries deduced from st_mode
|
||||
bit4= be verbose about failure causes
|
||||
@return >0 means ok
|
||||
<=0 means error
|
||||
-1= out of memory
|
||||
|
@ -282,7 +297,7 @@ int aaip_encode_acl(char *acl_text, mode_t st_mode,
|
|||
*result= NULL;
|
||||
*result_len= 0;
|
||||
bytes= aaip_encode_acl_text(acl_text, st_mode,
|
||||
(size_t) 0, NULL, 1 | (flag & (2 | 4 | 8)));
|
||||
(size_t) 0, NULL, 1 | (flag & (2 | 4 | 8 | 16)));
|
||||
if(bytes < -2)
|
||||
return(bytes);
|
||||
if(bytes < 0)
|
||||
|
@ -297,7 +312,7 @@ int aaip_encode_acl(char *acl_text, mode_t st_mode,
|
|||
(*result)[bytes]= 0;
|
||||
*result_len= bytes;
|
||||
bytes= aaip_encode_acl_text(acl_text, st_mode, *result_len, *result,
|
||||
(flag & (2 | 4 | 8)));
|
||||
(flag & (2 | 4 | 8 | 16)));
|
||||
if(bytes < -2)
|
||||
return(bytes);
|
||||
if(bytes < 0)
|
||||
|
@ -349,10 +364,11 @@ static int aaip_make_aaip_perms(int r, int w, int x)
|
|||
bit2= this is a default ACL, prepend SWITCH_MARK 1
|
||||
bit3= check for completeness of list and eventually
|
||||
fill up with entries deduced from st_mode
|
||||
bit4= be verbose about failure causes
|
||||
@return >=0 number of bytes produced resp. counted
|
||||
<0 means error
|
||||
-1: result size overflow
|
||||
-2: conversion errror with user name or group name
|
||||
-2: conversion error with user name or group name
|
||||
ISO_AAIP_ACL_MULT_OBJ: multiple entries of user::, group::, other::
|
||||
*/
|
||||
static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
||||
|
@ -375,7 +391,7 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
|||
/* set SWITCH_MARK to indicate a default ACL */;
|
||||
if(!(flag & 1)) {
|
||||
if((size_t) count >= result_size)
|
||||
{ret= -1; goto ex;}
|
||||
goto result_size_overflow;
|
||||
result[count]= (Aaip_SWITCH_MARK << 4) | Aaip_EXEC;
|
||||
}
|
||||
count++;
|
||||
|
@ -404,7 +420,11 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
|||
/* >>> Duplicate u:: entry. */;
|
||||
/* >>> ??? If it matches the previous one: ignore */
|
||||
|
||||
return((int) ISO_AAIP_ACL_MULT_OBJ);
|
||||
if(flag & 16)
|
||||
iso_msg_submit(-1, ISO_AAIP_ACL_MULT_OBJ, 0,
|
||||
"Duplicate u:: entry detected in ACL text");
|
||||
ret = ISO_AAIP_ACL_MULT_OBJ;
|
||||
goto ex;
|
||||
}
|
||||
has_u++;
|
||||
} else {
|
||||
|
@ -420,6 +440,9 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
|||
num= aaip_numeric_id(name, 0);
|
||||
if(num <= 0) {
|
||||
/* ACL_USER is not part of AAIP 2.0 */
|
||||
if(flag & 16)
|
||||
iso_msg_submit(-1, ISO_AAIP_BAD_ACL_TEXT, 0,
|
||||
"Unknown user name found in ACL text: '%s'", name);
|
||||
{ret= -2; goto ex;}
|
||||
}
|
||||
uid= huid= num;
|
||||
|
@ -449,7 +472,11 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
|||
/* >>> Duplicate g:: entry. */;
|
||||
/* >>> ??? If it matches the previous one: ignore */
|
||||
|
||||
return((int) ISO_AAIP_ACL_MULT_OBJ);
|
||||
if(flag & 16)
|
||||
iso_msg_submit(-1, ISO_AAIP_ACL_MULT_OBJ, 0,
|
||||
"Duplicate g:: entry detected in ACL text");
|
||||
ret = ISO_AAIP_ACL_MULT_OBJ;
|
||||
goto ex;
|
||||
}
|
||||
has_g++;
|
||||
} else {
|
||||
|
@ -465,6 +492,9 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
|||
num= aaip_numeric_id(name, 0);
|
||||
if(num <= 0) {
|
||||
/* ACL_GROUP is not part of AAIP 2.0 */
|
||||
if(flag & 16)
|
||||
iso_msg_submit(-1, ISO_AAIP_BAD_ACL_TEXT, 0,
|
||||
"Unknown group name found in ACL text: '%s'", name);
|
||||
{ret= -2; goto ex;}
|
||||
}
|
||||
gid= hgid= num;
|
||||
|
@ -493,7 +523,11 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
|||
/* >>> Duplicate o:: entry. */;
|
||||
/* >>> ??? If it matches the previous one: ignore */
|
||||
|
||||
return((int) ISO_AAIP_ACL_MULT_OBJ);
|
||||
if(flag & 16)
|
||||
iso_msg_submit(-1, ISO_AAIP_ACL_MULT_OBJ, 0,
|
||||
"Duplicate o:: entry detected in ACL text");
|
||||
ret = ISO_AAIP_ACL_MULT_OBJ;
|
||||
goto ex;
|
||||
}
|
||||
has_o++;
|
||||
} else if(strncmp(rpt, "mask:", 5) == 0) {
|
||||
|
@ -508,7 +542,7 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
|||
|
||||
if(!(flag & 1)) {
|
||||
if((size_t) count >= result_size)
|
||||
{ret= -1; goto ex;}
|
||||
goto result_size_overflow;
|
||||
result[count]= perms | ((!!qualifier) << 3) | (type << 4);
|
||||
}
|
||||
count++;
|
||||
|
@ -517,7 +551,7 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
|||
num_recs= (qualifier_len / 127) + !!(qualifier_len % 127);
|
||||
if(!(flag & 1)) {
|
||||
if((size_t) (count + 1) > result_size)
|
||||
{ret= -1; goto ex;}
|
||||
goto result_size_overflow;
|
||||
for(i= 0; i < num_recs; i++) {
|
||||
if(i < num_recs - 1)
|
||||
result[count++]= 255;
|
||||
|
@ -527,7 +561,7 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
|||
result[count - 1]= 127;
|
||||
}
|
||||
if((size_t) (count + (result[count - 1] & 127)) > result_size)
|
||||
{ret= -1; goto ex;}
|
||||
goto result_size_overflow;
|
||||
memcpy(result + count, name + i * 127, result[count - 1] & 127);
|
||||
count+= result[count - 1] & 127;
|
||||
}
|
||||
|
@ -542,7 +576,7 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
|||
count+= needed;
|
||||
else {
|
||||
if((size_t) (count + needed) > result_size)
|
||||
{ret= -1; goto ex;}
|
||||
goto result_size_overflow;
|
||||
}
|
||||
}
|
||||
if ((flag & 8) && needed > 0 && !(flag & 1)) {
|
||||
|
@ -571,6 +605,13 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
|||
ex:;
|
||||
LIBISO_FREE_MEM(name);
|
||||
return(ret);
|
||||
|
||||
result_size_overflow:;
|
||||
if(flag & 16)
|
||||
iso_msg_submit(-1, ISO_ASSERT_FAILURE, 0,
|
||||
"Program error: Text to ACL conversion result size overflow");
|
||||
ret= -1;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
|
||||
|
@ -582,13 +623,14 @@ int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text, mode_t st_mode,
|
|||
unsigned char *a_acl= NULL, *d_acl= NULL, *acl= NULL;
|
||||
|
||||
if(a_acl_text != NULL) {
|
||||
ret= aaip_encode_acl(a_acl_text, st_mode, &a_acl_len, &a_acl, flag & 11);
|
||||
ret= aaip_encode_acl(a_acl_text, st_mode, &a_acl_len, &a_acl,
|
||||
flag & (1 | 2 | 8 | 16));
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
}
|
||||
if(d_acl_text != NULL) {
|
||||
ret= aaip_encode_acl(d_acl_text, (mode_t) 0, &d_acl_len, &d_acl,
|
||||
(flag & 3) | 4);
|
||||
(flag & (1 | 2 | 16)) | 4);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
}
|
||||
|
@ -637,7 +679,7 @@ ex:;
|
|||
mission bits.
|
||||
|
||||
*/
|
||||
/* Analyze occurence of ACL tag types in long text form. If not disabled by
|
||||
/* Analyze occurrence of ACL tag types in long text form. If not disabled by
|
||||
parameter flag remove the entries of type "user::" , "group::" , "other::" ,
|
||||
or "other:" from an ACL in long text form if they match the bits in st_mode
|
||||
as described by man 2 stat and man 5 acl.
|
||||
|
@ -1803,8 +1845,8 @@ int aaip_decode_attrs(struct aaip_state **handle,
|
|||
if(aaip->list_mem_used >= memory_limit)
|
||||
return(3);
|
||||
aaip->list_mem_used+= new_mem;
|
||||
aaip->name_buf= calloc(sizeof(char *), Aaip_initial_name_leN);
|
||||
aaip->value_buf= calloc(sizeof(char *), Aaip_initial_value_leN);
|
||||
aaip->name_buf= calloc(1, Aaip_initial_name_leN);
|
||||
aaip->value_buf= calloc(1, Aaip_initial_value_leN);
|
||||
if(aaip->name_buf == NULL || aaip->value_buf == NULL)
|
||||
return(-1);
|
||||
aaip->name_buf_size= Aaip_initial_name_leN;
|
||||
|
@ -1918,7 +1960,7 @@ int aaip_decode_attrs(struct aaip_state **handle,
|
|||
@param handle The decoding context created by aaip_decode_attrs()
|
||||
@param num_attrs Will return the number of name-value pairs
|
||||
@param names Will return an array of pointers to 0-terminated names
|
||||
@param value_lengths Will return an arry with the lenghts of values
|
||||
@param value_lengths Will return an array with the lengths of values
|
||||
@param values Will return an array of pointers to 8-bit values
|
||||
@param flag Bitfield for control purposes
|
||||
bit15= free memory of names, value_lengths, values
|
||||
|
@ -2065,7 +2107,7 @@ int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
|
|||
unsigned char *rpt;
|
||||
char perm_text[4], *wpt, *name= NULL;
|
||||
int type, qualifier= 0, perm, ret, cnt, name_size= 1024;
|
||||
size_t w_size, name_fill= 0, i;
|
||||
size_t w_size= 0, name_fill= 0, i;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
struct passwd *pwd;
|
||||
|
@ -2177,10 +2219,41 @@ ex:;
|
|||
/* ----------------------- Adapter for operating systems ----------------- */
|
||||
|
||||
|
||||
#ifdef Libisofs_use_os_dummY
|
||||
|
||||
#include "aaip-os-dummy.c"
|
||||
|
||||
#else
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#include "aaip-os-freebsd.c"
|
||||
|
||||
#else
|
||||
#ifdef __FreeBSD_kernel__
|
||||
|
||||
#ifdef NIX
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
/* ts B51213: xattr system library calls are only stubs */
|
||||
#include "aaip-os-linux.c"
|
||||
#else
|
||||
/* ts B51213: extattr system library calls are not even present */
|
||||
#include "aaip-os-freebsd.c"
|
||||
#endif /* ! Libisofs_with_aaip_xattR */
|
||||
#else /* NIX */
|
||||
/* ts B51213: so we still end up at the dummy */
|
||||
#include "aaip-os-dummy.c"
|
||||
#endif /* ! NIX */
|
||||
|
||||
#else
|
||||
#ifdef __NetBSD__
|
||||
|
||||
#include "aaip-os-freebsd.c"
|
||||
|
||||
#else
|
||||
#ifdef __OpenBSD__
|
||||
|
||||
#include "aaip-os-freebsd.c"
|
||||
|
||||
#else
|
||||
#ifdef __linux
|
||||
|
||||
|
@ -2198,5 +2271,9 @@ ex:;
|
|||
#include "aaip-os-dummy.c"
|
||||
|
||||
#endif /* ! __linux */
|
||||
#endif /* ! __OpenBSD__ */
|
||||
#endif /* ! __NetBSD__ */
|
||||
#endif /* ! __FreeBSD_kernel__ */
|
||||
#endif /* ! __FreeBSD__ */
|
||||
#endif /* ! Libisofs_use_os_dummY */
|
||||
|
||||
|
|
|
@ -9,13 +9,21 @@
|
|||
|
||||
test/aaip_0_2.h - Public declarations
|
||||
|
||||
Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2+
|
||||
Copyright (c) 2009 - 2016 Thomas Schmitt
|
||||
|
||||
This file is part of the libisofs project; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
or later as published by the Free Software Foundation.
|
||||
See COPYING file for details.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef Aaip_h_is_includeD
|
||||
#define Aaip_h_is_includeD yes
|
||||
|
||||
/* For ssize_t */
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
/* --------------------------------- Encoder ---------------------------- */
|
||||
|
||||
|
@ -30,12 +38,12 @@
|
|||
no longer needed
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= set CONTINUE bit of last AAIP field to 1
|
||||
@return >0 is the number of SUSP fields generated,
|
||||
0 means error
|
||||
@return >= 0 is the number of SUSP fields generated,
|
||||
< 0 means error
|
||||
*/
|
||||
size_t aaip_encode(size_t num_attrs, char **names,
|
||||
size_t *value_lengths, char **values,
|
||||
size_t *result_len, unsigned char **result, int flag);
|
||||
ssize_t aaip_encode(size_t num_attrs, char **names,
|
||||
size_t *value_lengths, char **values,
|
||||
size_t *result_len, unsigned char **result, int flag);
|
||||
|
||||
|
||||
/* ------ ACL representation ------ */
|
||||
|
@ -90,7 +98,7 @@ int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text, mode_t st_mode,
|
|||
size_t *result_len, unsigned char **result, int flag);
|
||||
|
||||
|
||||
/* Analyze occurence of ACL tag types in long text form. If not disabled by
|
||||
/* Analyze occurrence of ACL tag types in long text form. If not disabled by
|
||||
parameter flag remove the entries of type "user::" , "group::" , "other::" ,
|
||||
or "other:" from an ACL in long text form if they match the bits in st_mode
|
||||
as described by man 2 stat and man 5 acl.
|
||||
|
@ -191,7 +199,7 @@ int aaip_get_acl_text(char *path, char **text, int flag);
|
|||
@param path Path to the file
|
||||
@param num_attrs Will return the number of name-value pairs
|
||||
@param names Will return an array of pointers to 0-terminated names
|
||||
@param value_lengths Will return an arry with the lenghts of values
|
||||
@param value_lengths Will return an array with the lengths of values
|
||||
@param values Will return an array of pointers to 8-bit values
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= obtain ACLs (access and eventually default) via
|
||||
|
@ -427,7 +435,7 @@ int aaip_decode_attrs(struct aaip_state **handle,
|
|||
@param handle The decoding context created by aaip_decode_attrs()
|
||||
@param num_attrs Will return the number of name-value pairs
|
||||
@param names Will return an array of pointers to 0-terminated names
|
||||
@param value_lengths Will return an arry with the lenghts of values
|
||||
@param value_lengths Will return an array with the lengths of values
|
||||
@param values Will return an array of pointers to 8-bit values
|
||||
@param flag Bitfield for control purposes
|
||||
bit15= free memory of names, value_lengths, values
|
||||
|
@ -504,7 +512,8 @@ int aaip_set_acl_text(char *path, char *text, int flag);
|
|||
ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other::
|
||||
*/
|
||||
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||
size_t *value_lengths, char **values, int flag);
|
||||
size_t *value_lengths, char **values,
|
||||
int *errnos, int flag);
|
||||
|
||||
#endif /* ! Aaip_h_is_includeD */
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* TODO #00010 : optimize ring buffer
|
||||
* - write/read at the end of buffer requires a second mutex_lock, even if
|
||||
* there's enought space/data at the beginning
|
||||
* there's enough space/data at the beginning
|
||||
* - pre-buffer for writes < BLOCK_SIZE
|
||||
*
|
||||
*/
|
||||
|
@ -145,7 +145,7 @@ void iso_ring_buffer_free(IsoRingBuffer *buf)
|
|||
* @param
|
||||
* Number of bytes to write
|
||||
* @return
|
||||
* 1 succes, 0 read finished, < 0 error
|
||||
* 1 success, 0 read finished, < 0 error
|
||||
*/
|
||||
int iso_ring_buffer_write(IsoRingBuffer *buf, uint8_t *data, size_t count)
|
||||
{
|
||||
|
@ -165,7 +165,7 @@ int iso_ring_buffer_write(IsoRingBuffer *buf, uint8_t *data, size_t count)
|
|||
/*
|
||||
* Note. There's only a writer, so we have no race conditions.
|
||||
* Thus, the while(buf->size == buf->cap) is used here
|
||||
* only to propertly detect the reader has been cancelled
|
||||
* only to properly detect the reader has been cancelled
|
||||
*/
|
||||
|
||||
if (buf->rend) {
|
||||
|
@ -196,7 +196,7 @@ int iso_ring_buffer_write(IsoRingBuffer *buf, uint8_t *data, size_t count)
|
|||
|
||||
/**
|
||||
* Read count bytes from the buffer into dest. It blocks until the desired
|
||||
* bytes has been read. If the writer finishes before outputting enought
|
||||
* bytes has been read. If the writer finishes before outputting enough
|
||||
* bytes, 0 (EOF) is returned, the number of bytes already read remains
|
||||
* unknown.
|
||||
*
|
||||
|
@ -219,7 +219,7 @@ int iso_ring_buffer_read(IsoRingBuffer *buf, uint8_t *dest, size_t count)
|
|||
/*
|
||||
* Note. There's only a reader, so we have no race conditions.
|
||||
* Thus, the while(buf->size == 0) is used here just to ensure
|
||||
* a reader detects the EOF propertly if the writer has been
|
||||
* a reader detects the EOF properly if the writer has been
|
||||
* canceled while the reader was waiting
|
||||
*/
|
||||
|
||||
|
|
|
@ -55,13 +55,13 @@ void iso_ring_buffer_free(IsoRingBuffer *buf);
|
|||
* @param
|
||||
* Number of bytes to write
|
||||
* @return
|
||||
* 1 succes, 0 read finished, < 0 error
|
||||
* 1 success, 0 read finished, < 0 error
|
||||
*/
|
||||
int iso_ring_buffer_write(IsoRingBuffer *buf, uint8_t *data, size_t count);
|
||||
|
||||
/**
|
||||
* Read count bytes from the buffer into dest. It blocks until the desired
|
||||
* bytes has been read. If the writer finishes before outputting enought
|
||||
* bytes has been read. If the writer finishes before outputting enough
|
||||
* bytes, 0 (EOF) is returned, the number of bytes already read remains
|
||||
* unknown.
|
||||
*
|
||||
|
@ -94,7 +94,7 @@ int iso_ring_buffer_get_buf_status(IsoRingBuffer *buf, size_t *size,
|
|||
|
||||
/**
|
||||
* Close the buffer (to be called by the writer).
|
||||
* You have to explicity close the buffer when you don't have more data to
|
||||
* You have to explicitly close the buffer when you don't have more data to
|
||||
* write, otherwise reader will be waiting forever.
|
||||
*
|
||||
* @param error
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 - 2011 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2015 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -21,6 +21,7 @@
|
|||
#include "image.h"
|
||||
#include "aaip_0_2.h"
|
||||
#include "util.h"
|
||||
#include "messages.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -72,8 +73,15 @@ int default_create_file(IsoNodeBuilder *builder, IsoImage *image,
|
|||
iso_file_source_ref(src);
|
||||
|
||||
name = iso_file_source_get_name(src);
|
||||
if (strlen(name) > LIBISOFS_NODE_NAME_MAX)
|
||||
name[LIBISOFS_NODE_NAME_MAX] = 0;
|
||||
if ((int) strlen(name) > image->truncate_length) {
|
||||
ret = iso_truncate_rr_name(image->truncate_mode,
|
||||
image->truncate_length, name, 0);
|
||||
if (ret < 0) {
|
||||
iso_stream_unref(stream);
|
||||
free(name);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ret = iso_node_new_file(name, stream, &node);
|
||||
if (ret < 0) {
|
||||
iso_stream_unref(stream);
|
||||
|
@ -96,13 +104,13 @@ int default_create_file(IsoNodeBuilder *builder, IsoImage *image,
|
|||
|
||||
static
|
||||
int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
IsoFileSource *src, IsoNode **node)
|
||||
IsoFileSource *src, char *in_name, IsoNode **node)
|
||||
{
|
||||
int ret;
|
||||
int ret, name_is_attached = 0;
|
||||
struct stat info;
|
||||
IsoNode *new;
|
||||
IsoFilesystem *fs;
|
||||
char *name;
|
||||
char *name = NULL;
|
||||
unsigned char *aa_string = NULL;
|
||||
char *a_text = NULL, *d_text = NULL;
|
||||
char *dest = NULL;
|
||||
|
@ -122,9 +130,21 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
|||
goto ex;
|
||||
}
|
||||
|
||||
name = iso_file_source_get_name(src);
|
||||
if (strlen(name) > LIBISOFS_NODE_NAME_MAX)
|
||||
name[LIBISOFS_NODE_NAME_MAX] = 0;
|
||||
if (in_name == NULL) {
|
||||
name = iso_file_source_get_name(src);
|
||||
} else {
|
||||
name = strdup(in_name);
|
||||
if (name == NULL) {
|
||||
ret = ISO_OUT_OF_MEM; goto ex;
|
||||
}
|
||||
}
|
||||
|
||||
if ((int) strlen(name) > image->truncate_length) {
|
||||
ret = iso_truncate_rr_name(image->truncate_mode,
|
||||
image->truncate_length, name, 0);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
fs = iso_file_source_get_filesystem(src);
|
||||
new = NULL;
|
||||
|
||||
|
@ -195,12 +215,14 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
|||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
free(name);
|
||||
default:
|
||||
ret = ISO_BAD_FSRC_FILETYPE;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
name_is_attached = 1;
|
||||
|
||||
/* fill fields */
|
||||
iso_node_set_perms_internal(new, info.st_mode, 1);
|
||||
|
@ -214,9 +236,9 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
|||
/* Eventually set S_IRWXG from ACL */
|
||||
if (image->builder_ignore_acl) {
|
||||
ret = iso_file_source_get_aa_string(src, &aa_string, 4);
|
||||
if (aa_string != NULL)
|
||||
if (ret >= 0 && aa_string != NULL)
|
||||
iso_aa_get_acl_text(aa_string, info.st_mode, &a_text, &d_text, 16);
|
||||
if (a_text != NULL) {
|
||||
if (ret >= 0 && a_text != NULL) {
|
||||
aaip_cleanout_st_mode(a_text, &(info.st_mode), 4 | 16);
|
||||
iso_node_set_perms_internal(new, info.st_mode, 1);
|
||||
}
|
||||
|
@ -230,8 +252,11 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
|||
/* Obtain ownership of eventual AAIP string */
|
||||
ret = iso_file_source_get_aa_string(src, &aa_string,
|
||||
1 | (image->builder_ignore_acl << 1) |
|
||||
(image->builder_ignore_ea << 2 ));
|
||||
if (ret == 1 && aa_string != NULL) {
|
||||
(image->builder_ignore_ea << 2) |
|
||||
(image->builder_take_all_ea << 3));
|
||||
if(ret == 2)
|
||||
image->blind_on_local_get_attrs = 1;
|
||||
if (ret > 0 && aa_string != NULL) {
|
||||
ret = iso_node_add_xinfo(new, aaip_xinfo_func, aa_string);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
|
@ -243,6 +268,8 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
|||
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
if (name != NULL && !name_is_attached)
|
||||
free(name);
|
||||
LIBISO_FREE_MEM(dest);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2014 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -33,7 +34,7 @@ struct Iso_Node_Builder
|
|||
* always be created, even if src is another kind of file.
|
||||
*
|
||||
* In that case, if the implementation can't do the conversion, it
|
||||
* should fail propertly.
|
||||
* should fail properly.
|
||||
*
|
||||
* Note that the src is never unref, so you need to free it.
|
||||
*
|
||||
|
@ -47,6 +48,7 @@ struct Iso_Node_Builder
|
|||
* Create a new IsoNode from a IsoFileSource. The type of the node to be
|
||||
* created is determined from the type of the file source. Name,
|
||||
* permissions and other attributes are taken from source file.
|
||||
* But name may be overridden by parameter name if it is not NULL.
|
||||
*
|
||||
* Note that the src is never unref, so you need to free it.
|
||||
*
|
||||
|
@ -54,7 +56,7 @@ struct Iso_Node_Builder
|
|||
* 1 on success, < 0 on error
|
||||
*/
|
||||
int (*create_node)(IsoNodeBuilder *builder, IsoImage *image,
|
||||
IsoFileSource *src, IsoNode **node);
|
||||
IsoFileSource *src, char *name, IsoNode **node);
|
||||
|
||||
/**
|
||||
* Free implementation specific data. Should never be called by user.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -21,6 +21,11 @@
|
|||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* O_BINARY is needed for Cygwin but undefined elsewhere */
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Private data for File IsoDataSource
|
||||
*/
|
||||
|
@ -65,7 +70,7 @@ int ds_open(IsoDataSource *src)
|
|||
return ISO_FILE_ALREADY_OPENED;
|
||||
}
|
||||
|
||||
fd = open(data->path, O_RDONLY);
|
||||
fd = open(data->path, O_RDONLY | O_BINARY);
|
||||
if (fd == -1) {
|
||||
return ISO_FILE_ERROR;
|
||||
}
|
||||
|
@ -140,7 +145,7 @@ void ds_free_data(IsoDataSource *src)
|
|||
|
||||
/**
|
||||
* Create a new IsoDataSource from a local file. This is suitable for
|
||||
* accessing regular .iso images, or to acces drives via its block device
|
||||
* accessing regular .iso images, or to access drives via its block device
|
||||
* and standard POSIX I/O calls.
|
||||
*
|
||||
* @param path
|
||||
|
|
1994
libisofs/ecma119.c
1994
libisofs/ecma119.c
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 - 2013 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2023 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -33,7 +33,7 @@
|
|||
#define MAX_ISO_FILE_SECTION_SIZE 0xffffffff
|
||||
|
||||
/*
|
||||
* When a file need to be splitted in several sections, the maximum size
|
||||
* When a file need to be split in several sections, the maximum size
|
||||
* of such sections, but the last one. Set to a multiple of BLOCK_SIZE.
|
||||
* Default to 4GB - 2048 = 0xFFFFF800
|
||||
*/
|
||||
|
@ -59,7 +59,7 @@
|
|||
#define ISO_DISC_LABEL_SIZE 129
|
||||
|
||||
|
||||
/* The maximum lenght of an specs violating ECMA-119 file identifier.
|
||||
/* The maximum length of an specs violating ECMA-119 file identifier.
|
||||
The theoretical limit is 254 - 34 - 28 (len of SUSP CE entry) = 192
|
||||
Currently the practical limit is 254 - 34 - 96 (non-CE RR entries) - 28 (CE)
|
||||
*/
|
||||
|
@ -87,6 +87,12 @@
|
|||
#define ISO_GPT_ENTRIES_MAX 248
|
||||
|
||||
|
||||
/* How many warnings to issue about writing Joliet names which cannot be
|
||||
properly represented in UCS-2 and thus had to be defaulted to '_'.
|
||||
*/
|
||||
#define ISO_JOLIET_UCS2_WARN_MAX 3
|
||||
|
||||
|
||||
/**
|
||||
* Holds the options for the image generation.
|
||||
*/
|
||||
|
@ -94,7 +100,7 @@ struct iso_write_opts {
|
|||
|
||||
int will_cancel;
|
||||
|
||||
int level; /**< ISO level to write at. (ECMA-119, 10) */
|
||||
int iso_level; /**< ISO level to write at. (ECMA-119, 10) */
|
||||
|
||||
/** Which extensions to support. */
|
||||
unsigned int rockridge :1;
|
||||
|
@ -105,7 +111,7 @@ struct iso_write_opts {
|
|||
|
||||
unsigned int aaip :1; /* whether to write eventual ACL and EAs */
|
||||
|
||||
/* allways write timestamps in GMT */
|
||||
/* always write timestamps in GMT */
|
||||
unsigned int always_gmt :1;
|
||||
|
||||
/*
|
||||
|
@ -177,7 +183,7 @@ struct iso_write_opts {
|
|||
|
||||
/**
|
||||
* Allow all characters to be part of Volume and Volset identifiers on
|
||||
* the Primary Volume Descriptor. This breaks ISO-9660 contraints, but
|
||||
* the Primary Volume Descriptor. This breaks ISO-9660 constraints, but
|
||||
* should work on modern systems.
|
||||
*/
|
||||
unsigned int relaxed_vol_atts :1;
|
||||
|
@ -192,6 +198,11 @@ struct iso_write_opts {
|
|||
*/
|
||||
unsigned int joliet_long_names :1;
|
||||
|
||||
/**
|
||||
* Use UTF-16BE rather than its subset UCS-2
|
||||
*/
|
||||
unsigned int joliet_utf16 :1;
|
||||
|
||||
/**
|
||||
* Write Rock Ridge info as of specification RRIP-1.10 rather than
|
||||
* RRIP-1.12: signature "RRIP_1991A" rather than "IEEE_1282",
|
||||
|
@ -212,7 +223,7 @@ struct iso_write_opts {
|
|||
/**
|
||||
* Write AAIP as extension according to SUSP 1.10 rather than SUSP 1.12.
|
||||
* I.e. without announcing it by an ER field and thus without the need
|
||||
* to preceed the RRIP fields by an ES and to preceed the AA field by ES.
|
||||
* to precede the RRIP fields by an ES and to precede the AA field by ES.
|
||||
* This saves bytes and might avoid problems with readers which dislike
|
||||
* ER fields other than the ones for RRIP.
|
||||
* On the other hand, SUSP 1.12 frowns on such unannounced extensions
|
||||
|
@ -276,7 +287,7 @@ struct iso_write_opts {
|
|||
/**
|
||||
* The following options set the default values for files and directory
|
||||
* permissions, gid and uid. All these take one of three values: 0, 1 or 2.
|
||||
* If 0, the corresponding attribute will be kept as setted in the IsoNode.
|
||||
* If 0, the corresponding attribute will be kept as set in the IsoNode.
|
||||
* Unless you have changed it, it corresponds to the value on disc, so it
|
||||
* is suitable for backup purposes. If set to 1, the corresponding attrib.
|
||||
* will be changed by a default suitable value. Finally, if you set it to
|
||||
|
@ -338,7 +349,7 @@ struct iso_write_opts {
|
|||
* or write to an .iso file for future burning or distribution.
|
||||
*
|
||||
* On the other side, an appendable image is not self contained, it refers
|
||||
* to serveral files that are stored outside the image. Its usage is for
|
||||
* to several files that are stored outside the image. Its usage is for
|
||||
* multisession discs, where you add data in a new session, while the
|
||||
* previous session data can still be accessed. In those cases, the old
|
||||
* data is not written again. Instead, the new image refers to it, and thus
|
||||
|
@ -370,7 +381,7 @@ struct iso_write_opts {
|
|||
/**
|
||||
* When not NULL, it should point to a buffer of at least 64KiB, where
|
||||
* libisofs will write the contents that should be written at the beginning
|
||||
* of a overwriteable media, to grow the image. The growing of an image is
|
||||
* of a overwritable media, to grow the image. The growing of an image is
|
||||
* a way, used by first time in growisofs by Andy Polyakov, to allow the
|
||||
* appending of new data to non-multisession media, such as DVD+RW, in the
|
||||
* same way you append a new session to a multisession disc, i.e., without
|
||||
|
@ -382,7 +393,7 @@ struct iso_write_opts {
|
|||
*
|
||||
* You should initialize the buffer either with 0s, or with the contents of
|
||||
* the first blocks of the image you're growing. In most cases, 0 is good
|
||||
* enought.
|
||||
* enough.
|
||||
*/
|
||||
uint8_t *overwrite;
|
||||
|
||||
|
@ -420,6 +431,7 @@ struct iso_write_opts {
|
|||
* See ecma119_image : System Area related information
|
||||
*/
|
||||
char *system_area_data;
|
||||
int system_area_size;
|
||||
int system_area_options;
|
||||
|
||||
/* User settable PVD time stamps */
|
||||
|
@ -456,17 +468,56 @@ struct iso_write_opts {
|
|||
to HFS+/FAT and IsoFileSrc areas and marked by an MBR partition entry.
|
||||
*/
|
||||
char *prep_partition;
|
||||
int prep_part_flag;
|
||||
|
||||
/* Eventual disk file path of an EFI system partition image which shall
|
||||
be prepended to HFS+/FAT and IsoFileSrc areas and marked by a GPT entry.
|
||||
*/
|
||||
char *efi_boot_partition;
|
||||
int efi_boot_part_flag;
|
||||
|
||||
/* Eventual disk file paths of prepared images which shall be appended
|
||||
after the ISO image and described by partiton table entries in a MBR
|
||||
/* Disk file paths of prepared images which shall be appended
|
||||
after the ISO image and described by partition table entries in a MBR.
|
||||
NULL means unused.
|
||||
*/
|
||||
char *appended_partitions[ISO_MAX_PARTITIONS];
|
||||
uint8_t appended_part_types[ISO_MAX_PARTITIONS];
|
||||
int appended_part_flags[ISO_MAX_PARTITIONS];
|
||||
uint8_t appended_part_type_guids[ISO_MAX_PARTITIONS][16];
|
||||
|
||||
/* Flags in case that appended partitions show up in GPT:
|
||||
bit0= appended_part_type_guids is valid
|
||||
*/
|
||||
uint8_t appended_part_gpt_flags[ISO_MAX_PARTITIONS];
|
||||
|
||||
/* If 1: With appended partitions: create protective MBR and mark by GPT
|
||||
*/
|
||||
int appended_as_gpt;
|
||||
|
||||
/* If 1: With appended partitions: mark by APM partition
|
||||
*/
|
||||
int appended_as_apm;
|
||||
|
||||
/* If 1: Obey struct el_torito_boot_image.isolinux_options bit2-7 and bit8.
|
||||
I.e. mention boot image as partition in GPT and/or APM.
|
||||
*/
|
||||
int part_like_isohybrid;
|
||||
|
||||
/* The type to use for the mountable ISO partition if there is any and if
|
||||
the type is not mandatorily determined for particular circumstances like
|
||||
compliant GPT, CHRP, or PReP.
|
||||
-1 = use the default value (e.g. 0xcd, 0x83, 0x17)
|
||||
0x00 to 0xff = value to use if possible
|
||||
*/
|
||||
int iso_mbr_part_type;
|
||||
|
||||
/* iso_write_opts_set_iso_type_guid
|
||||
*/
|
||||
uint8_t iso_gpt_type_guid[16];
|
||||
/* bit0= iso_gpt_type_guid is valid
|
||||
*/
|
||||
int iso_gpt_flag;
|
||||
|
||||
|
||||
/* Eventual name of the non-ISO aspect of the image. E.g. SUN ASCII label.
|
||||
*/
|
||||
|
@ -485,6 +536,24 @@ struct iso_write_opts {
|
|||
*/
|
||||
int apm_block_size;
|
||||
|
||||
/* User defined GUID for GPT header and base of reproducible partition
|
||||
GUIDs. (Not to be confused with volume "UUID", which is actually a
|
||||
timestamp.)
|
||||
See API call iso_write_opts_set_gpt_guid().
|
||||
*/
|
||||
uint8_t gpt_disk_guid[16];
|
||||
int gpt_disk_guid_mode;
|
||||
|
||||
/* Maximum number of CE entries per file */
|
||||
uint32_t max_ce_entries;
|
||||
/* Whether to try dropping AAIP data on too many CE:
|
||||
bit0-3 = Mode:
|
||||
0 = throw ISO_TOO_MANY_CE, without trying to drop anything
|
||||
1 = drop non-isofs fattr
|
||||
2 = drop ACL if dropping non-isofs fattr does not suffice
|
||||
*/
|
||||
int max_ce_drop_attr;
|
||||
|
||||
};
|
||||
|
||||
typedef struct ecma119_image Ecma119Image;
|
||||
|
@ -502,70 +571,19 @@ struct ecma119_image
|
|||
IsoImage *image;
|
||||
Ecma119Node *root;
|
||||
|
||||
int will_cancel :1;
|
||||
IsoWriteOpts *opts;
|
||||
|
||||
unsigned int iso_level :2;
|
||||
|
||||
/* extensions */
|
||||
unsigned int rockridge :1;
|
||||
unsigned int joliet :1;
|
||||
/** Whether El Torito data will be produced */
|
||||
unsigned int eltorito :1;
|
||||
unsigned int iso1999 :1;
|
||||
unsigned int hfsplus :1;
|
||||
unsigned int fat :1;
|
||||
|
||||
unsigned int hardlinks:1; /* see iso_write_opts_set_hardlinks() */
|
||||
|
||||
unsigned int aaip :1; /* see iso_write_opts_set_aaip() */
|
||||
|
||||
/* allways write timestamps in GMT */
|
||||
unsigned int always_gmt :1;
|
||||
|
||||
/* relaxed constraints */
|
||||
unsigned int allow_dir_id_ext :1;
|
||||
unsigned int omit_version_numbers :2;
|
||||
unsigned int allow_deep_paths :1;
|
||||
unsigned int allow_longer_paths :1;
|
||||
unsigned int max_37_char_filenames :1;
|
||||
unsigned int no_force_dots :2;
|
||||
unsigned int allow_lowercase :1;
|
||||
unsigned int allow_full_ascii :1;
|
||||
unsigned int allow_7bit_ascii :1;
|
||||
|
||||
unsigned int relaxed_vol_atts : 1;
|
||||
|
||||
/** Allow paths on Joliet tree to be larger than 240 bytes */
|
||||
unsigned int joliet_longer_paths :1;
|
||||
|
||||
/** Allow Joliet names up to 103 characters rather than 64 */
|
||||
unsigned int joliet_long_names :1;
|
||||
|
||||
/** Write old fashioned RRIP-1.10 rather than RRIP-1.12 */
|
||||
unsigned int rrip_version_1_10 :1;
|
||||
|
||||
/** Write field PX with file serial number even with RRIP-1.10 */
|
||||
unsigned int rrip_1_10_px_ino :1;
|
||||
|
||||
/* Write AAIP as extension according to SUSP 1.10 rather than SUSP 1.12. */
|
||||
unsigned int aaip_susp_1_10 :1;
|
||||
|
||||
/* Store in ECMA-119, Joliet, ISO 9660:1999 timestamp the mtime of source
|
||||
bit0= ECMA-119, bit1= Joliet, bit2= ISO 9660:1999.
|
||||
/* The ECMA-119 directory node where to store Rock Ridge relocated
|
||||
directories. (Path is in IsoWriteOpts.rr_reloc_dir)
|
||||
*/
|
||||
unsigned int dir_rec_mtime :3;
|
||||
|
||||
/* The ECMA-119 directory where to store Rock Ridge relocated directories.
|
||||
*/
|
||||
char *rr_reloc_dir; /* IsoNode name in root directory */
|
||||
int rr_reloc_flags;
|
||||
Ecma119Node *rr_reloc_node; /* Directory node in ecma119_image */
|
||||
|
||||
unsigned int md5_session_checksum :1;
|
||||
unsigned int md5_file_checksums :2;
|
||||
|
||||
/*
|
||||
* Mode replace. If one of these flags is set, the correspodent values are
|
||||
* replaced with values below.
|
||||
* replaced with values below. Both get computed from IsoWriteOpts.
|
||||
*/
|
||||
unsigned int replace_uid :1;
|
||||
unsigned int replace_gid :1;
|
||||
|
@ -573,36 +591,32 @@ struct ecma119_image
|
|||
unsigned int replace_dir_mode :1;
|
||||
unsigned int replace_timestamps :1;
|
||||
|
||||
/* Mode replacement values. */
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
mode_t file_mode;
|
||||
mode_t dir_mode;
|
||||
time_t timestamp;
|
||||
|
||||
unsigned int old_empty :1;
|
||||
unsigned int untranslated_name_len;
|
||||
|
||||
/**
|
||||
* if sort files or not. Sorting is based of the weight of each file
|
||||
*/
|
||||
int sort_files;
|
||||
|
||||
/* Effective charsets */
|
||||
char *input_charset;
|
||||
char *output_charset;
|
||||
|
||||
/* See iso_write_opts and iso_write_opts_set_hfsp_serial_number().
|
||||
* 00...00 means that it shall be generated by libisofs.
|
||||
*/
|
||||
uint8_t hfsp_serial_number[8];
|
||||
|
||||
unsigned int appendable : 1;
|
||||
uint32_t ms_block; /**< start block for a ms image */
|
||||
time_t now; /**< Time at which writing began. */
|
||||
|
||||
/** Total size of the output. This only includes the current volume. */
|
||||
/* Total size of the output. Counted in bytes.
|
||||
* Includes ISO filesystem and appended data.
|
||||
*/
|
||||
off_t total_size;
|
||||
|
||||
/** Size actually governed by the ISO filesystem part of the output */
|
||||
uint32_t vol_space_size;
|
||||
|
||||
/* 1= write the total size into the PVD of the ISO,
|
||||
* 0= write vol_space_size
|
||||
*/
|
||||
int pvd_size_is_total_size;
|
||||
|
||||
/* Bytes already written to image output */
|
||||
off_t bytes_written;
|
||||
/* just for progress notification */
|
||||
|
@ -642,6 +656,7 @@ struct ecma119_image
|
|||
uint32_t joliet_path_table_size;
|
||||
uint32_t joliet_l_path_table_pos;
|
||||
uint32_t joliet_m_path_table_pos;
|
||||
size_t joliet_ucs2_failures;
|
||||
|
||||
/*
|
||||
* HFS+ related information
|
||||
|
@ -684,6 +699,11 @@ struct ecma119_image
|
|||
int num_bootsrc;
|
||||
IsoFileSrc **bootsrc; /* location of the boot images in the new image */
|
||||
|
||||
int *boot_appended_idx; /* Appended partition which serve as boot images */
|
||||
|
||||
uint32_t *boot_intvl_start; /* In blocks of 2048 bytes */
|
||||
uint32_t *boot_intvl_size; /* In blocks of 512 bytes */
|
||||
|
||||
/*
|
||||
* System Area related information
|
||||
*/
|
||||
|
@ -746,6 +766,8 @@ struct ecma119_image
|
|||
/* tree of files sources */
|
||||
IsoRBTree *files;
|
||||
|
||||
struct iso_filesrc_list_item *ecma119_hidden_list;
|
||||
|
||||
unsigned int checksum_idx_counter;
|
||||
void *checksum_ctx;
|
||||
off_t checksum_counter;
|
||||
|
@ -763,14 +785,6 @@ struct ecma119_image
|
|||
Use only underneath ecma119_image_new()
|
||||
and if not NULL*/
|
||||
|
||||
/* ??? Is there a reason why we copy lots of items from IsoWriteOpts
|
||||
rather than taking ownership of the IsoWriteOpts object which
|
||||
is submitted with ecma119_image_new() ?
|
||||
*/
|
||||
|
||||
char scdbackup_tag_parm[100];
|
||||
char *scdbackup_tag_written;
|
||||
|
||||
/* Buffer for communication between burn_source and writer thread */
|
||||
IsoRingBuffer *buffer;
|
||||
|
||||
|
@ -779,20 +793,7 @@ struct ecma119_image
|
|||
int wthread_is_running;
|
||||
pthread_attr_t th_attr;
|
||||
|
||||
/* User settable PVD time stamps */
|
||||
time_t vol_creation_time;
|
||||
time_t vol_modification_time;
|
||||
time_t vol_expiration_time;
|
||||
time_t vol_effective_time;
|
||||
/* To eventually override vol_creation_time and vol_modification_time
|
||||
* by unconverted string with timezone 0
|
||||
*/
|
||||
char vol_uuid[17];
|
||||
|
||||
/* The number of unclaimed 2K blocks before
|
||||
start of partition 1 as of the MBR in system area. */
|
||||
uint32_t partition_offset;
|
||||
/* Partition table parameter: 1 to 63, 0= disabled/default */
|
||||
/* Effective partition table parameter: 1 to 63, 0= disabled/default */
|
||||
int partition_secs_per_head;
|
||||
/* 1 to 255, 0= disabled/default */
|
||||
int partition_heads_per_cyl;
|
||||
|
@ -813,12 +814,6 @@ struct ecma119_image
|
|||
uint32_t j_part_l_path_table_pos;
|
||||
uint32_t j_part_m_path_table_pos;
|
||||
|
||||
#ifdef Libisofs_with_libjtE
|
||||
struct libjte_env *libjte_handle;
|
||||
#endif /* Libisofs_with_libjtE */
|
||||
|
||||
uint32_t tail_blocks;
|
||||
|
||||
/* Memorized ELF parameters from MIPS Little Endian boot file */
|
||||
uint32_t mipsel_e_entry;
|
||||
uint32_t mipsel_p_offset;
|
||||
|
@ -830,14 +825,16 @@ struct ecma119_image
|
|||
*/
|
||||
IsoFileSrc *sparc_core_src;
|
||||
|
||||
char *appended_partitions[ISO_MAX_PARTITIONS];
|
||||
uint8_t appended_part_types[ISO_MAX_PARTITIONS];
|
||||
/* Trailing padding of ISO filesystem partition for cylinder alignment */
|
||||
/* Only in effect with Libisofs_part_align_writeR */
|
||||
uint32_t part_align_blocks;
|
||||
uint32_t alignment_end_block;
|
||||
|
||||
/* Counted in blocks of 2048 */
|
||||
uint32_t appended_part_prepad[ISO_MAX_PARTITIONS];
|
||||
uint32_t appended_part_start[ISO_MAX_PARTITIONS];
|
||||
uint32_t appended_part_size[ISO_MAX_PARTITIONS];
|
||||
|
||||
char ascii_disc_label[ISO_DISC_LABEL_SIZE];
|
||||
int have_appended_partitions;
|
||||
|
||||
/* See IsoImage and libisofs.h */
|
||||
IsoNode *hfsplus_blessed[ISO_HFSPLUS_BLESS_MAX];
|
||||
|
@ -846,17 +843,12 @@ struct ecma119_image
|
|||
Only change a block size if it is 0. Set only to 512 or 2048.
|
||||
If it stays 0 then it will become 512 or 2048 in time.
|
||||
*/
|
||||
/* Blocksize of Apple Partition Map
|
||||
May be defined to 512 or 2048 before writer thread starts.
|
||||
*/
|
||||
int apm_block_size;
|
||||
|
||||
/* Allocation block size of HFS+
|
||||
May be defined to 512 or 2048 before hfsplus_writer_create().
|
||||
*/
|
||||
int hfsp_block_size;
|
||||
int hfsp_cat_node_size; /* 2 * apm_block_size */
|
||||
int hfsp_iso_block_fac; /* 2048 / apm_block_size */
|
||||
int hfsp_cat_node_size; /* 2 * hfsp_block_size */
|
||||
int hfsp_iso_block_fac; /* 2048 / hfsp_block_size */
|
||||
|
||||
/* Apple Partition Map description. To be composed during IsoImageWriter
|
||||
method ->compute_data_blocks() by calling iso_register_apm_entry().
|
||||
|
@ -877,7 +869,12 @@ struct ecma119_image
|
|||
struct iso_mbr_partition_request *mbr_req[ISO_MBR_ENTRIES_MAX];
|
||||
int mbr_req_count;
|
||||
|
||||
char *prep_partition;
|
||||
/* Number of bytes which have to be added after the cylinder aligned end
|
||||
of the overall ISO partition because clinder size is not a multiple
|
||||
of 2048
|
||||
*/
|
||||
int post_iso_part_pad;
|
||||
|
||||
uint32_t prep_part_size;
|
||||
|
||||
/* GPT description. To be composed during IsoImageWriter
|
||||
|
@ -890,13 +887,22 @@ struct ecma119_image
|
|||
/* bit0= GPT partitions may overlap */
|
||||
int gpt_req_flags;
|
||||
|
||||
char *efi_boot_partition;
|
||||
/* Whether the eventual backup GPT is not part of the ISO filesystem */
|
||||
int gpt_backup_outside;
|
||||
|
||||
/* The base UUID for the generated GPT UUIDs */
|
||||
uint8_t gpt_uuid_base[16];
|
||||
/* The counter which distinguishes the GPT UUIDs */
|
||||
uint32_t gpt_uuid_counter;
|
||||
|
||||
uint32_t efi_boot_part_size;
|
||||
IsoFileSrc *efi_boot_part_filesrc; /* Just a pointer. Do not free. */
|
||||
|
||||
/* Messages from gpt_tail_writer_compute_data_blocks() to
|
||||
iso_write_system_area().
|
||||
*/
|
||||
uint8_t gpt_disk_guid[16];
|
||||
int gpt_disk_guid_set;
|
||||
/* Start of GPT entries in System Area, block size 512 */
|
||||
uint32_t gpt_part_start;
|
||||
/* The ISO block number after the backup GPT header , block size 2048 */
|
||||
|
@ -909,6 +915,7 @@ struct ecma119_image
|
|||
write_data() methods of the writers.
|
||||
*/
|
||||
uint8_t sys_area_as_written[16 * BLOCK_SIZE];
|
||||
int sys_area_already_written;
|
||||
|
||||
/* Size of the filesrc_writer area (data file content).
|
||||
This is available before any IsoImageWriter.compute_data_blocks()
|
||||
|
@ -917,6 +924,21 @@ struct ecma119_image
|
|||
uint32_t filesrc_start;
|
||||
uint32_t filesrc_blocks;
|
||||
|
||||
/* Number of CE entries in currently processed node */
|
||||
uint32_t curr_ce_entries;
|
||||
|
||||
/* Count of symbolic links and special files which could not be represented
|
||||
in Joliet.
|
||||
*/
|
||||
unsigned long joliet_symlinks;
|
||||
unsigned long joliet_specials;
|
||||
|
||||
/* Count of symbolic links and special files which could not be represented
|
||||
in ISO 9660:1999.
|
||||
*/
|
||||
unsigned long iso1999_symlinks;
|
||||
unsigned long iso1999_specials;
|
||||
|
||||
};
|
||||
|
||||
#define BP(a,b) [(b) - (a) + 1]
|
||||
|
@ -1054,4 +1076,31 @@ void ecma119_set_voldescr_times(IsoImageWriter *writer,
|
|||
int iso_write_partition_file(Ecma119Image *target, char *path,
|
||||
uint32_t prepad, uint32_t blocks, int flag);
|
||||
|
||||
void issue_ucs2_warning_summary(size_t failures);
|
||||
|
||||
/* Tells whether ivr is a reader from imported_iso in a multi-session
|
||||
add-on situation, and thus to be kept in place.
|
||||
*/
|
||||
int iso_interval_reader_keep(Ecma119Image *target,
|
||||
struct iso_interval_reader *ivr,
|
||||
int flag);
|
||||
|
||||
/* @return: ISO_SUCCESS = ok, ISO_SUCCESS + 1 = keep , < 0 = error */
|
||||
int iso_interval_reader_start_size(Ecma119Image *t, char *path,
|
||||
off_t *start_byte, off_t *byte_count,
|
||||
int flag);
|
||||
|
||||
/* Obtains start and end number of appended partition range and returns
|
||||
the number of valid entries in the list of appended partitions.
|
||||
*/
|
||||
int iso_count_appended_partitions(Ecma119Image *target,
|
||||
int *first_partition, int *last_partition);
|
||||
|
||||
/* Determines the range of valid partition numbers depending on partition
|
||||
table type.
|
||||
*/
|
||||
void iso_tell_max_part_range(IsoWriteOpts *opts,
|
||||
int *first_partition, int *last_partition,
|
||||
int flag);
|
||||
|
||||
#endif /*LIBISO_ECMA119_H_*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 - 2012 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2016 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -29,52 +29,57 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static
|
||||
int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name)
|
||||
/* @param flag bit0= Do not issue error messages
|
||||
*/
|
||||
int iso_get_ecma119_name(IsoWriteOpts *opts, char *input_charset, int imgid,
|
||||
char *node_name, enum IsoNodeType node_type,
|
||||
char **name, int flag)
|
||||
{
|
||||
int ret, relaxed, free_ascii_name= 0, force_dots = 0;
|
||||
int ret, relaxed, free_ascii_name = 0, force_dots = 0;
|
||||
char *ascii_name;
|
||||
char *isoname= NULL;
|
||||
char *isoname = NULL;
|
||||
|
||||
if (iso->name == NULL) {
|
||||
if (node_name == NULL) {
|
||||
/* it is not necessarily an error, it can be the root */
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
if (img->untranslated_name_len > 0) {
|
||||
ascii_name = iso->name;
|
||||
if (opts->untranslated_name_len > 0) {
|
||||
ascii_name = node_name;
|
||||
ret = 1;
|
||||
} else {
|
||||
ret = str2ascii(img->input_charset, iso->name, &ascii_name);
|
||||
ret = str2ascii(input_charset, node_name, &ascii_name);
|
||||
free_ascii_name = 1;
|
||||
}
|
||||
if (ret < 0) {
|
||||
iso_msg_submit(img->image->id, ret, 0,
|
||||
"Cannot convert name '%s' to ASCII", iso->name);
|
||||
if (!(flag & 512))
|
||||
iso_msg_submit(imgid, ret, 0,
|
||||
"Cannot convert name '%s' to ASCII", node_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (img->allow_full_ascii) {
|
||||
if (opts->allow_full_ascii) {
|
||||
relaxed = 2;
|
||||
} else {
|
||||
relaxed = (int)img->allow_lowercase;
|
||||
relaxed = (int)opts->allow_lowercase;
|
||||
}
|
||||
if (img->allow_7bit_ascii)
|
||||
if (opts->allow_7bit_ascii)
|
||||
relaxed |= 4;
|
||||
if (iso->type == LIBISO_DIR && !(img->allow_dir_id_ext)) {
|
||||
if (img->untranslated_name_len > 0) {
|
||||
if (strlen(ascii_name) > img->untranslated_name_len) {
|
||||
if (node_type == LIBISO_DIR && !(opts->allow_dir_id_ext)) {
|
||||
if (opts->untranslated_name_len > 0) {
|
||||
if (strlen(ascii_name) > opts->untranslated_name_len) {
|
||||
needs_transl:;
|
||||
iso_msg_submit(img->image->id, ISO_NAME_NEEDS_TRANSL, 0,
|
||||
if (!(flag & 512))
|
||||
iso_msg_submit(imgid, ISO_NAME_NEEDS_TRANSL, 0,
|
||||
"File name too long (%d > %d) for untranslated recording: '%s'",
|
||||
strlen(ascii_name), img->untranslated_name_len,
|
||||
ascii_name);
|
||||
strlen(ascii_name), opts->untranslated_name_len,
|
||||
ascii_name);
|
||||
return ISO_NAME_NEEDS_TRANSL;
|
||||
}
|
||||
isoname = strdup(ascii_name);
|
||||
} else if (img->max_37_char_filenames) {
|
||||
} else if (opts->max_37_char_filenames) {
|
||||
isoname = iso_r_dirid(ascii_name, 37, relaxed);
|
||||
} else if (img->iso_level == 1) {
|
||||
} else if (opts->iso_level == 1) {
|
||||
|
||||
#ifdef Libisofs_old_ecma119_nameS
|
||||
|
||||
|
@ -99,14 +104,15 @@ needs_transl:;
|
|||
}
|
||||
}
|
||||
} else {
|
||||
force_dots = !((img->no_force_dots & 1) || iso->type == LIBISO_DIR);
|
||||
if (img->untranslated_name_len > 0) {
|
||||
if (strlen(ascii_name) > img->untranslated_name_len)
|
||||
force_dots = !((opts->no_force_dots & 1) ||
|
||||
node_type == LIBISO_DIR);
|
||||
if (opts->untranslated_name_len > 0) {
|
||||
if (strlen(ascii_name) > opts->untranslated_name_len)
|
||||
goto needs_transl;
|
||||
isoname = strdup(ascii_name);
|
||||
} else if (img->max_37_char_filenames) {
|
||||
} else if (opts->max_37_char_filenames) {
|
||||
isoname = iso_r_fileid(ascii_name, 36, relaxed, force_dots);
|
||||
} else if (img->iso_level == 1) {
|
||||
} else if (opts->iso_level == 1) {
|
||||
|
||||
#ifdef Libisofs_old_ecma119_nameS
|
||||
|
||||
|
@ -151,11 +157,21 @@ needs_transl:;
|
|||
}
|
||||
}
|
||||
|
||||
static
|
||||
int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = iso_get_ecma119_name(img->opts, img->input_charset, img->image->id,
|
||||
iso->name, iso->type, name, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ecma119_is_dedicated_reloc_dir(Ecma119Image *img, Ecma119Node *node)
|
||||
{
|
||||
if (img->rr_reloc_node == node &&
|
||||
node != img->root && node != img->partition_root &&
|
||||
(img->rr_reloc_flags & 2))
|
||||
(img->opts->rr_reloc_flags & 2))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -185,23 +201,26 @@ static
|
|||
int create_dir(Ecma119Image *img, IsoDir *iso, Ecma119Node **node)
|
||||
{
|
||||
int ret;
|
||||
Ecma119Node **children;
|
||||
Ecma119Node **children = NULL;
|
||||
struct ecma119_dir_info *dir_info;
|
||||
|
||||
children = calloc(1, sizeof(void*) * iso->nchildren);
|
||||
if (children == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
if (iso->nchildren > 0) {
|
||||
children = calloc(1, sizeof(void*) * iso->nchildren);
|
||||
if (children == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
|
||||
dir_info = calloc(1, sizeof(struct ecma119_dir_info));
|
||||
if (dir_info == NULL) {
|
||||
free(children);
|
||||
if (children != NULL)
|
||||
free(children);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
|
||||
ret = create_ecma119_node(img, (IsoNode*)iso, node);
|
||||
if (ret < 0) {
|
||||
free(children);
|
||||
if (children != NULL)
|
||||
free(children);
|
||||
free(dir_info);
|
||||
return ret;
|
||||
}
|
||||
|
@ -220,13 +239,13 @@ int create_file_src(Ecma119Image *img, IsoFile *iso, IsoFileSrc **src)
|
|||
off_t size;
|
||||
|
||||
size = iso_stream_get_size(iso->stream);
|
||||
if (size > (off_t)MAX_ISO_FILE_SECTION_SIZE && img->iso_level != 3) {
|
||||
if (size > (off_t)MAX_ISO_FILE_SECTION_SIZE && img->opts->iso_level != 3) {
|
||||
char *ipath = iso_tree_get_node_path(ISO_NODE(iso));
|
||||
ret = iso_msg_submit(img->image->id, ISO_FILE_TOO_BIG, 0,
|
||||
"File \"%s\" can't be added to image because "
|
||||
"is greater than 4GB", ipath);
|
||||
iso_msg_submit(img->image->id, ISO_FILE_TOO_BIG, 0,
|
||||
"File \"%s\" cannot be added to image because "
|
||||
"its size is 4 GiB or larger", ipath);
|
||||
free(ipath);
|
||||
return ret;
|
||||
return ISO_FILE_TOO_BIG;
|
||||
}
|
||||
ret = iso_file_src_create(img, iso, src);
|
||||
if (ret < 0) {
|
||||
|
@ -337,7 +356,8 @@ void ecma119_node_free(Ecma119Node *node)
|
|||
for (i = 0; i < node->info.dir->nchildren; i++) {
|
||||
ecma119_node_free(node->info.dir->children[i]);
|
||||
}
|
||||
free(node->info.dir->children);
|
||||
if (node->info.dir->children != NULL)
|
||||
free(node->info.dir->children);
|
||||
free(node->info.dir);
|
||||
}
|
||||
free(node->iso_name);
|
||||
|
@ -345,6 +365,35 @@ void ecma119_node_free(Ecma119Node *node)
|
|||
free(node);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int add_to_hidden_list(Ecma119Image *image, IsoFileSrc *src)
|
||||
{
|
||||
int ret;
|
||||
struct iso_filesrc_list_item *item;
|
||||
|
||||
LIBISO_ALLOC_MEM(item, struct iso_filesrc_list_item, 1);
|
||||
item->src = src;
|
||||
item->next = image->ecma119_hidden_list;
|
||||
image->ecma119_hidden_list = item;
|
||||
ret = ISO_SUCCESS;
|
||||
ex:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int iso_filesrc_list_destroy(struct iso_filesrc_list_item **start_item)
|
||||
{
|
||||
struct iso_filesrc_list_item *item, *next;
|
||||
|
||||
for (item = *start_item; item != NULL; item = next) {
|
||||
next = item->next;
|
||||
LIBISO_FREE_MEM(item);
|
||||
}
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param flag
|
||||
* bit0= iso is in a hidden directory. Thus hide it.
|
||||
|
@ -361,10 +410,12 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree,
|
|||
int max_path;
|
||||
char *iso_name= NULL, *ipath = NULL;
|
||||
IsoFileSrc *src = NULL;
|
||||
IsoWriteOpts *opts;
|
||||
|
||||
if (image == NULL || iso == NULL || tree == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
opts = image->opts;
|
||||
*tree = NULL;
|
||||
|
||||
hidden = flag & 1;
|
||||
|
@ -385,16 +436,16 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree,
|
|||
goto ex;
|
||||
}
|
||||
max_path = pathlen + 1 + (iso_name ? strlen(iso_name) : 0);
|
||||
if (!image->rockridge) {
|
||||
if (!opts->rockridge) {
|
||||
if ((iso->type == LIBISO_DIR && depth > 8) &&
|
||||
!image->allow_deep_paths) {
|
||||
ipath = iso_tree_get_node_path(iso);
|
||||
!opts->allow_deep_paths) {
|
||||
ipath = iso_tree_get_node_path(iso);
|
||||
ret = iso_msg_submit(image->image->id, ISO_FILE_IMGPATH_WRONG,
|
||||
0, "File \"%s\" can't be added, "
|
||||
"because directory depth "
|
||||
"is greater than 8.", ipath);
|
||||
goto ex;
|
||||
} else if (max_path > 255 && !image->allow_longer_paths) {
|
||||
} else if (max_path > 255 && !opts->allow_longer_paths) {
|
||||
ipath = iso_tree_get_node_path(iso);
|
||||
ret = iso_msg_submit(image->image->id, ISO_FILE_IMGPATH_WRONG,
|
||||
0, "File \"%s\" can't be added, "
|
||||
|
@ -409,6 +460,9 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree,
|
|||
case LIBISO_FILE:
|
||||
if (hidden) {
|
||||
ret = create_file_src(image, (IsoFile *) iso, &src);
|
||||
if (ret <= 0)
|
||||
goto ex;
|
||||
ret = add_to_hidden_list(image, src);
|
||||
} else {
|
||||
ret = create_file(image, (IsoFile*)iso, &node);
|
||||
}
|
||||
|
@ -418,7 +472,7 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree,
|
|||
ret = 0; /* Hidden means non-existing */
|
||||
goto ex;
|
||||
}
|
||||
if (image->rockridge) {
|
||||
if (opts->rockridge) {
|
||||
ret = create_symlink(image, (IsoSymlink*)iso, &node);
|
||||
} else {
|
||||
/* symlinks are only supported when RR is enabled */
|
||||
|
@ -434,7 +488,7 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree,
|
|||
ret = 0; /* Hidden means non-existing */
|
||||
goto ex;
|
||||
}
|
||||
if (image->rockridge) {
|
||||
if (opts->rockridge) {
|
||||
ret = create_special(image, (IsoSpecial*)iso, &node);
|
||||
} else {
|
||||
/* special files are only supported when RR is enabled */
|
||||
|
@ -449,6 +503,9 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree,
|
|||
if (image->eltorito) {
|
||||
if (hidden) {
|
||||
ret = el_torito_catalog_file_src_create(image, &src);
|
||||
if (ret <= 0)
|
||||
goto ex;
|
||||
ret = add_to_hidden_list(image, src);
|
||||
} else {
|
||||
ret = create_boot_cat(image, (IsoBoot*)iso, &node);
|
||||
}
|
||||
|
@ -472,9 +529,9 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree,
|
|||
image->rr_reloc_node = node;
|
||||
} else if (depth == 2) {
|
||||
/* Directories in root may be used as relocation dir */
|
||||
if (image->rr_reloc_dir != NULL)
|
||||
if (image->rr_reloc_dir[0] != 0 &&
|
||||
strcmp(iso->name, image->rr_reloc_dir) == 0)
|
||||
if (opts->rr_reloc_dir != NULL)
|
||||
if (opts->rr_reloc_dir[0] != 0 &&
|
||||
strcmp(iso->name, opts->rr_reloc_dir) == 0)
|
||||
image->rr_reloc_node = node;
|
||||
}
|
||||
}
|
||||
|
@ -540,13 +597,15 @@ int cmp_node_name(const void *f1, const void *f2)
|
|||
|
||||
/**
|
||||
* Sorts a the children of each directory in the ECMA-119 tree represented
|
||||
* by \p root, acording to the order specified in ECMA-119, section 9.3.
|
||||
* by \p root, according to the order specified in ECMA-119, section 9.3.
|
||||
*/
|
||||
static
|
||||
void sort_tree(Ecma119Node *root)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (root->info.dir->children == NULL)
|
||||
return;
|
||||
qsort(root->info.dir->children, root->info.dir->nchildren, sizeof(void*),
|
||||
cmp_node_name);
|
||||
for (i = 0; i < root->info.dir->nchildren; i++) {
|
||||
|
@ -575,6 +634,9 @@ int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
|
|||
nchildren = dir->info.dir->nchildren;
|
||||
children = dir->info.dir->children;
|
||||
|
||||
if (nchildren <= 0)
|
||||
return ISO_SUCCESS; /* nothing to do */
|
||||
|
||||
/* a hash table will temporary hold the names, for fast searching */
|
||||
ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash,
|
||||
(compare_function_t)strcmp, &table);
|
||||
|
@ -592,6 +654,7 @@ int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
|
|||
for (i = 0; i < nchildren; ++i) {
|
||||
char *name, *ext;
|
||||
char full_name[40];
|
||||
const int full_max_len = 40 - 1;
|
||||
int max; /* computed max len for name, without extension */
|
||||
int j = i;
|
||||
int digits = 1; /* characters to change per name */
|
||||
|
@ -606,7 +669,7 @@ int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (img->untranslated_name_len) {
|
||||
if (img->opts->untranslated_name_len) {
|
||||
/* This should not happen because no two IsoNode names should be
|
||||
identical and only unaltered IsoNode names should be seen here.
|
||||
Thus the Ema119Node names should be unique.
|
||||
|
@ -619,7 +682,7 @@ int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
|
|||
}
|
||||
|
||||
/*
|
||||
* A max of 7 characters is good enought, it allows handling up to
|
||||
* A max of 7 characters is good enough, it allows handling up to
|
||||
* 9,999,999 files with same name. We can increment this to
|
||||
* max_name_len, but the int_pow() function must then be modified
|
||||
* to return a bigger integer.
|
||||
|
@ -630,12 +693,14 @@ int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
|
|||
int change = 0; /* number to be written */
|
||||
|
||||
/* copy name to buffer */
|
||||
strcpy(full_name, children[i]->iso_name);
|
||||
strncpy(full_name, children[i]->iso_name, full_max_len);
|
||||
full_name[full_max_len] = 0;
|
||||
|
||||
/* compute name and extension */
|
||||
dot = strrchr(full_name, '.');
|
||||
if (dot != NULL &&
|
||||
(children[i]->type != ECMA119_DIR || img->allow_dir_id_ext)) {
|
||||
(children[i]->type != ECMA119_DIR ||
|
||||
img->opts->allow_dir_id_ext)) {
|
||||
|
||||
/*
|
||||
* File (normally not dir) with extension
|
||||
|
@ -801,11 +866,11 @@ int mangle_tree(Ecma119Image *img, Ecma119Node *dir, int recurse)
|
|||
int max_file, max_dir;
|
||||
Ecma119Node *root;
|
||||
|
||||
if (img->untranslated_name_len > 0) {
|
||||
max_file = max_dir = img->untranslated_name_len;
|
||||
} else if (img->max_37_char_filenames) {
|
||||
if (img->opts->untranslated_name_len > 0) {
|
||||
max_file = max_dir = img->opts->untranslated_name_len;
|
||||
} else if (img->opts->max_37_char_filenames) {
|
||||
max_file = max_dir = 37;
|
||||
} else if (img->iso_level == 1) {
|
||||
} else if (img->opts->iso_level == 1) {
|
||||
max_file = 12; /* 8 + 3 + 1 */
|
||||
max_dir = 8;
|
||||
} else {
|
||||
|
@ -973,9 +1038,9 @@ int reorder_tree(Ecma119Image *img, Ecma119Node *dir,
|
|||
/* dir is now the relocated Ecma119Node */
|
||||
pathlen = 37 + 1; /* The dir name might get longer by mangling */
|
||||
level = 2;
|
||||
if (img->rr_reloc_dir != NULL) {
|
||||
if (img->opts->rr_reloc_dir != NULL) {
|
||||
pathlen += strlen(img->rr_reloc_node->iso_name) + 1;
|
||||
if(img->rr_reloc_dir[0] != 0)
|
||||
if(img->opts->rr_reloc_dir[0] != 0)
|
||||
level = 3;
|
||||
}
|
||||
}
|
||||
|
@ -1095,6 +1160,11 @@ int family_set_ino(Ecma119Image *img, Ecma119Node **nodes, size_t family_start,
|
|||
*/
|
||||
if (img_ino == prev_ino)
|
||||
img_ino = 0;
|
||||
|
||||
/* Accept only if it is within the 32 bit range. */
|
||||
if (((uint64_t) img_ino) > 0xffffffff)
|
||||
img_ino = 0;
|
||||
|
||||
}
|
||||
if (img_ino == 0) {
|
||||
img_ino = img_give_ino_number(img->image, 0);
|
||||
|
@ -1128,7 +1198,7 @@ int match_hardlinks(Ecma119Image *img, Ecma119Node *dir, int flag)
|
|||
goto ex;
|
||||
|
||||
/* Sort according to id tuples, IsoFileSrc identity, properties, xattr. */
|
||||
if (img->hardlinks)
|
||||
if (img->opts->hardlinks)
|
||||
qsort(nodes, node_count, sizeof(Ecma119Node *), ecma119_node_cmp_hard);
|
||||
else
|
||||
qsort(nodes, node_count, sizeof(Ecma119Node *),
|
||||
|
@ -1198,9 +1268,9 @@ int ecma119_tree_create(Ecma119Image *img)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (img->rockridge && !img->allow_deep_paths) {
|
||||
if (img->opts->rockridge && !img->opts->allow_deep_paths) {
|
||||
|
||||
/* Relocate deep directories, acording to RRIP, 4.1.5 */
|
||||
/* Relocate deep directories, according to RRIP, 4.1.5 */
|
||||
ret = reorder_tree(img, root, 1, 0);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* 2012 Thomas Schmitt
|
||||
* 2012 - 2014 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -64,9 +64,7 @@ struct ecma119_node
|
|||
|
||||
IsoNode *node; /*< reference to the iso node */
|
||||
|
||||
/* >>> ts A90501 : Shouldn't this be uint32_t
|
||||
as this is what PX will take ? */
|
||||
ino_t ino;
|
||||
uint32_t ino;
|
||||
|
||||
nlink_t nlink;
|
||||
|
||||
|
@ -81,6 +79,17 @@ struct ecma119_node
|
|||
} info;
|
||||
};
|
||||
|
||||
|
||||
/* For recording files which are hidden in ECMA-119 */
|
||||
struct iso_filesrc_list_item
|
||||
{
|
||||
IsoFileSrc *src;
|
||||
struct iso_filesrc_list_item *next;
|
||||
};
|
||||
|
||||
int iso_filesrc_list_destroy(struct iso_filesrc_list_item **start_item);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -103,5 +112,13 @@ Ecma119Node *ecma119_search_iso_node(Ecma119Image *img, IsoNode *node);
|
|||
*/
|
||||
int ecma119_is_dedicated_reloc_dir(Ecma119Image *img, Ecma119Node *node);
|
||||
|
||||
/**
|
||||
* Determines the ECMA-119 name from node name.
|
||||
* @param flag bit0= Do not issue error messages
|
||||
*/
|
||||
int iso_get_ecma119_name(IsoWriteOpts *opts, char *input_charset, int imgid,
|
||||
char *node_name, enum IsoNodeType node_type,
|
||||
char **name, int flag);
|
||||
|
||||
|
||||
#endif /*LIBISO_ECMA119_TREE_H_*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2010 - 2013 Thomas Schmitt
|
||||
* Copyright (c) 2010 - 2024 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -19,6 +19,7 @@
|
|||
#include "image.h"
|
||||
#include "messages.h"
|
||||
#include "writer.h"
|
||||
#include "ecma119.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -82,15 +83,16 @@ void el_torito_set_load_seg(ElToritoBootImage *bootimg, short segment)
|
|||
{
|
||||
if (bootimg->type != 0)
|
||||
return;
|
||||
bootimg->load_seg = segment;
|
||||
if (segment < 0)
|
||||
bootimg->load_seg = 0x1000 + segment;
|
||||
else
|
||||
bootimg->load_seg = segment;
|
||||
}
|
||||
|
||||
/* API */
|
||||
int el_torito_get_load_seg(ElToritoBootImage *bootimg)
|
||||
{
|
||||
if (bootimg->load_seg < 0)
|
||||
return 0xffff - bootimg->load_seg;
|
||||
return bootimg->load_seg;
|
||||
return (int) bootimg->load_seg;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -102,17 +104,33 @@ void el_torito_set_load_size(ElToritoBootImage *bootimg, short sectors)
|
|||
{
|
||||
if (bootimg->type != 0)
|
||||
return;
|
||||
bootimg->load_size = sectors;
|
||||
if (sectors < 0)
|
||||
bootimg->load_size = 0x10000 + sectors;
|
||||
else
|
||||
bootimg->load_size = sectors;
|
||||
}
|
||||
|
||||
/* API */
|
||||
int el_torito_get_load_size(ElToritoBootImage *bootimg)
|
||||
{
|
||||
if (bootimg->load_size < 0)
|
||||
return 0xffff - bootimg->load_size;
|
||||
return bootimg->load_size;
|
||||
return (int) bootimg->load_size;
|
||||
}
|
||||
|
||||
/* API */
|
||||
void el_torito_set_full_load(ElToritoBootImage *bootimg, int mode)
|
||||
{
|
||||
if (bootimg->type != 0)
|
||||
return;
|
||||
bootimg->load_size_full= !!mode;
|
||||
}
|
||||
|
||||
/* API */
|
||||
int el_torito_get_full_load(ElToritoBootImage *bootimg)
|
||||
{
|
||||
return bootimg->load_size_full;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Marks the specified boot image as not bootable
|
||||
*/
|
||||
|
@ -204,6 +222,8 @@ void el_torito_patch_isolinux_image(ElToritoBootImage *bootimg)
|
|||
int el_torito_set_isolinux_options(ElToritoBootImage *bootimg, int options, int flag)
|
||||
{
|
||||
bootimg->isolinux_options = (options & 0x03ff);
|
||||
bootimg->seems_boot_info_table = !!(options & 1);
|
||||
bootimg->seems_grub2_boot_info = !!(options & (1 << 9));
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -285,14 +305,14 @@ int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot)
|
|||
node->size = 0;
|
||||
node->content = NULL;
|
||||
|
||||
/* atributes from parent */
|
||||
/* attributes from parent */
|
||||
node->node.mode = S_IFREG | (parent->node.mode & 0444);
|
||||
node->node.uid = parent->node.uid;
|
||||
node->node.gid = parent->node.gid;
|
||||
node->node.hidden = parent->node.hidden;
|
||||
|
||||
/* current time */
|
||||
now = time(NULL);
|
||||
iso_nowtime(&now, 0);
|
||||
node->node.atime = now;
|
||||
node->node.ctime = now;
|
||||
node->node.mtime = now;
|
||||
|
@ -308,44 +328,104 @@ int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot)
|
|||
return ++parent->nchildren;
|
||||
}
|
||||
|
||||
/* Get start and size from "%d_start_%lus_size_%lud" */
|
||||
static
|
||||
void iso_parse_start_size(char *text, unsigned long *part_start,
|
||||
unsigned long *part_size)
|
||||
{
|
||||
char *cpt;
|
||||
unsigned long start, size;
|
||||
|
||||
cpt = strchr(text, '_');
|
||||
if (cpt == NULL)
|
||||
return;
|
||||
if (strncmp(cpt, "_start_", 7) != 0)
|
||||
return;
|
||||
sscanf(cpt + 7, "%lu", &start);
|
||||
cpt = strchr(cpt + 7, '_');
|
||||
if (cpt == NULL)
|
||||
return;
|
||||
if (*(cpt - 1) != 's')
|
||||
return;
|
||||
if (strncmp(cpt, "_size_", 6) != 0)
|
||||
return;
|
||||
sscanf(cpt + 6, "%lu", &size);
|
||||
for (cpt = cpt + 6; *cpt >= '0' && *cpt <= '9'; cpt++);
|
||||
if (*cpt != 'd')
|
||||
return;
|
||||
|
||||
*part_start = start;
|
||||
*part_size = size;
|
||||
}
|
||||
|
||||
static
|
||||
int create_image(IsoImage *image, const char *image_path,
|
||||
enum eltorito_boot_media_type type,
|
||||
struct el_torito_boot_image **bootimg)
|
||||
struct el_torito_boot_image **bootimg,
|
||||
IsoFile **bootnode)
|
||||
{
|
||||
int ret;
|
||||
struct el_torito_boot_image *boot;
|
||||
int boot_media_type = 0;
|
||||
int load_sectors = 0; /* number of sector to load */
|
||||
int part_idx = -1;
|
||||
unsigned long part_start = 0, part_size = 0;
|
||||
unsigned char partition_type = 0;
|
||||
off_t size;
|
||||
IsoNode *imgfile;
|
||||
IsoStream *stream;
|
||||
IsoNode *imgfile = NULL;
|
||||
IsoStream *stream = NULL;
|
||||
|
||||
ret = iso_tree_path_to_node(image, image_path, &imgfile);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
if (ret == 0) {
|
||||
iso_msg_submit(image->id, ISO_NODE_DOESNT_EXIST, 0,
|
||||
*bootnode = NULL;
|
||||
|
||||
if (strncmp(image_path, "--interval:appended_partition_", 30) == 0) {
|
||||
/* --interval:appended_partition_N... */
|
||||
if (type != ELTORITO_NO_EMUL) {
|
||||
|
||||
/* >>> ??? lift this ban by making a temporary IsoStream from
|
||||
partition source, determine size,
|
||||
and read ELTORITO_HARD_DISC_EMUL MBR ?
|
||||
*/
|
||||
|
||||
iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
|
||||
"Appended partition cannot serve as El Torito boot image with FD/HD emulation");
|
||||
return ISO_BOOT_IMAGE_NOT_VALID;
|
||||
}
|
||||
sscanf(image_path + 30, "%d", &part_idx);
|
||||
if (part_idx < 1 || part_idx > ISO_MAX_PARTITIONS) {
|
||||
iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
|
||||
"Appended partition index for El Torito boot image is out of range");
|
||||
return ISO_BOOT_IMAGE_NOT_VALID;
|
||||
}
|
||||
iso_parse_start_size((char *) (image_path + 30),
|
||||
&part_start, &part_size);
|
||||
part_idx--;
|
||||
size = 1;
|
||||
} else {
|
||||
ret = iso_tree_path_to_node(image, image_path, &imgfile);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
if (ret == 0) {
|
||||
iso_msg_submit(image->id, ISO_NODE_DOESNT_EXIST, 0,
|
||||
"El Torito boot image file missing in ISO image: '%s'",
|
||||
image_path);
|
||||
return ISO_NODE_DOESNT_EXIST;
|
||||
return ISO_NODE_DOESNT_EXIST;
|
||||
}
|
||||
|
||||
if (imgfile->type != LIBISO_FILE) {
|
||||
return ISO_BOOT_IMAGE_NOT_VALID;
|
||||
}
|
||||
*bootnode = (IsoFile *) imgfile;
|
||||
|
||||
stream = ((IsoFile*)imgfile)->stream;
|
||||
|
||||
/* we need to read the image at least two times */
|
||||
if (!iso_stream_is_repeatable(stream)) {
|
||||
return ISO_BOOT_IMAGE_NOT_VALID;
|
||||
}
|
||||
|
||||
size = iso_stream_get_size(stream);
|
||||
}
|
||||
|
||||
if (imgfile->type != LIBISO_FILE) {
|
||||
return ISO_BOOT_IMAGE_NOT_VALID;
|
||||
}
|
||||
|
||||
stream = ((IsoFile*)imgfile)->stream;
|
||||
|
||||
/* we need to read the image at least two times */
|
||||
if (!iso_stream_is_repeatable(stream)) {
|
||||
return ISO_BOOT_IMAGE_NOT_VALID;
|
||||
}
|
||||
|
||||
size = iso_stream_get_size(stream);
|
||||
if (size <= 0) {
|
||||
iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
|
||||
"Boot image file is empty");
|
||||
|
@ -434,20 +514,25 @@ int create_image(IsoImage *image, const char *image_path,
|
|||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
boot->image = (IsoFile*)imgfile;
|
||||
iso_node_ref(imgfile); /* get our ref */
|
||||
boot->appended_idx = part_idx;
|
||||
boot->appended_start = part_start;
|
||||
boot->appended_size = part_size;
|
||||
if (imgfile != NULL)
|
||||
iso_node_ref(imgfile); /* get our ref */
|
||||
boot->bootable = 1;
|
||||
boot->seems_boot_info_table = 0;
|
||||
boot->seems_grub2_boot_info = 0;
|
||||
boot->seems_isohybrid_capable = 0;
|
||||
boot->isolinux_options = 0;
|
||||
boot->type = boot_media_type;
|
||||
boot->partition_type = partition_type;
|
||||
boot->load_seg = 0;
|
||||
boot->load_size = load_sectors;
|
||||
boot->load_size_full = 0;
|
||||
boot->platform_id = 0; /* 80x86 */
|
||||
memset(boot->id_string, 0, sizeof(boot->id_string));
|
||||
memset(boot->selection_crit, 0, sizeof(boot->selection_crit));
|
||||
if (bootimg) {
|
||||
*bootimg = boot;
|
||||
}
|
||||
*bootimg = boot;
|
||||
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
@ -461,6 +546,7 @@ int iso_image_set_boot_image(IsoImage *image, const char *image_path,
|
|||
struct el_torito_boot_catalog *catalog;
|
||||
ElToritoBootImage *boot_image= NULL;
|
||||
IsoBoot *cat_node= NULL;
|
||||
IsoFile *boot_node;
|
||||
|
||||
if (image == NULL || image_path == NULL || catalog_path == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
|
@ -480,12 +566,10 @@ int iso_image_set_boot_image(IsoImage *image, const char *image_path,
|
|||
|
||||
/* get both the dir and the name */
|
||||
catname = strrchr(catdir, '/');
|
||||
if (catname == NULL) {
|
||||
free(catdir);
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
if (catname == NULL)
|
||||
catname = catdir;
|
||||
if (catname == catdir) {
|
||||
/* we are apending catalog to root node */
|
||||
/* we are appending catalog to root node */
|
||||
parent = image->root;
|
||||
} else {
|
||||
IsoNode *p;
|
||||
|
@ -504,7 +588,8 @@ int iso_image_set_boot_image(IsoImage *image, const char *image_path,
|
|||
}
|
||||
parent = (IsoDir*)p;
|
||||
}
|
||||
catname++;
|
||||
if (catname[0] == '/' || catname[0] == 0)
|
||||
catname++;
|
||||
ret = iso_tree_add_boot_node(parent, catname, &cat_node);
|
||||
free(catdir);
|
||||
if (ret < 0) {
|
||||
|
@ -513,7 +598,7 @@ int iso_image_set_boot_image(IsoImage *image, const char *image_path,
|
|||
}
|
||||
|
||||
/* create the boot image */
|
||||
ret = create_image(image, image_path, type, &boot_image);
|
||||
ret = create_image(image, image_path, type, &boot_image, &boot_node);
|
||||
if (ret < 0) {
|
||||
goto boot_image_cleanup;
|
||||
}
|
||||
|
@ -529,7 +614,10 @@ int iso_image_set_boot_image(IsoImage *image, const char *image_path,
|
|||
for (i = 1; i < Libisofs_max_boot_imageS; i++)
|
||||
catalog->bootimages[i] = NULL;
|
||||
catalog->node = cat_node;
|
||||
catalog->sort_weight = 1000; /* slightly high */
|
||||
catalog->sort_weight = 1000000000; /* very high */
|
||||
if (boot_node != NULL)
|
||||
if (!(boot_node->explicit_weight || boot_node->from_old_session))
|
||||
boot_node->sort_weight = 2;
|
||||
iso_node_ref((IsoNode*)cat_node);
|
||||
image->bootcat = catalog;
|
||||
|
||||
|
@ -545,7 +633,8 @@ boot_image_cleanup:;
|
|||
iso_node_unref((IsoNode*)cat_node);
|
||||
}
|
||||
if (boot_image) {
|
||||
iso_node_unref((IsoNode*)boot_image->image);
|
||||
if (boot_image->image != NULL)
|
||||
iso_node_unref((IsoNode*)boot_image->image);
|
||||
free(boot_image);
|
||||
}
|
||||
return ret;
|
||||
|
@ -621,13 +710,14 @@ int iso_image_get_bootcat(IsoImage *image, IsoBoot **catnode, uint32_t *lba,
|
|||
return 0;
|
||||
*catnode = bootcat;
|
||||
*lba = bootcat->lba;
|
||||
*size = bootcat->size;
|
||||
if (bootcat->size > 0 && bootcat->content != NULL) {
|
||||
*content = calloc(1, bootcat->size);
|
||||
if (*content == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
memcpy(*content, bootcat->content, bootcat->size);
|
||||
}
|
||||
if (*content != NULL)
|
||||
*size = bootcat->size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -700,14 +790,18 @@ int iso_image_add_boot_image(IsoImage *image, const char *image_path,
|
|||
int ret;
|
||||
struct el_torito_boot_catalog *catalog = image->bootcat;
|
||||
ElToritoBootImage *boot_img;
|
||||
IsoFile *boot_node;
|
||||
|
||||
if(catalog == NULL)
|
||||
return ISO_BOOT_NO_CATALOG;
|
||||
if (catalog->num_bootimages >= Libisofs_max_boot_imageS)
|
||||
return ISO_BOOT_IMAGE_OVERFLOW;
|
||||
ret = create_image(image, image_path, type, &boot_img);
|
||||
ret = create_image(image, image_path, type, &boot_img, &boot_node);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (boot_node != NULL)
|
||||
if (!(boot_node->explicit_weight || boot_node->from_old_session))
|
||||
boot_node->sort_weight = 2;
|
||||
catalog->bootimages[catalog->num_bootimages] = boot_img;
|
||||
catalog->num_bootimages++;
|
||||
if (boot != NULL)
|
||||
|
@ -751,6 +845,8 @@ void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat)
|
|||
continue;
|
||||
if ((IsoNode*)image->image != NULL)
|
||||
iso_node_unref((IsoNode*)image->image);
|
||||
if (image->image_path != NULL)
|
||||
free(image->image_path);
|
||||
free(image);
|
||||
}
|
||||
if ((IsoNode*)cat->node != NULL)
|
||||
|
@ -799,7 +895,8 @@ write_section_header(uint8_t *buf, Ecma119Image *t, int idx, int num_entries)
|
|||
(struct el_torito_section_header *) buf;
|
||||
|
||||
/* 0x90 = more section headers follow , 0x91 = final section */
|
||||
e->header_indicator[0] = 0x90 + (idx == t->catalog->num_bootimages - 1);
|
||||
e->header_indicator[0] =
|
||||
0x90 + (idx == t->catalog->num_bootimages - num_entries);
|
||||
e->platform_id[0] = t->catalog->bootimages[idx]->platform_id;
|
||||
e->num_entries[0] = num_entries & 0xff;
|
||||
e->num_entries[1] = (num_entries >> 8) & 0xff;;
|
||||
|
@ -808,17 +905,44 @@ write_section_header(uint8_t *buf, Ecma119Image *t, int idx, int num_entries)
|
|||
sizeof(e->id_string));
|
||||
}
|
||||
|
||||
static int
|
||||
write_section_load_size(struct el_torito_boot_image *img,
|
||||
struct el_torito_section_entry *se,
|
||||
uint16_t load_size, off_t full_byte_size, int flag)
|
||||
{
|
||||
uint16_t size;
|
||||
off_t blocks;
|
||||
|
||||
size= load_size;
|
||||
if(img->type == 0 && img->load_size_full) {
|
||||
blocks= ((full_byte_size + 2047) / 2048) * 4;
|
||||
if (blocks > 65535) {
|
||||
if (img->platform_id == 0xef)
|
||||
size= 0;
|
||||
else
|
||||
size= 65535;
|
||||
} else if(blocks <= 0) {
|
||||
size= 1;
|
||||
} else {
|
||||
size= blocks;
|
||||
}
|
||||
}
|
||||
iso_lsb(se->sec_count, size, 2);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write one section entry.
|
||||
* Usable for the Default Entry
|
||||
* and for Section Entries with Selection criteria type == 0
|
||||
*/
|
||||
static void
|
||||
write_section_entry(uint8_t *buf, Ecma119Image *t, int idx)
|
||||
static
|
||||
int write_section_entry(uint8_t *buf, Ecma119Image *t, int idx)
|
||||
{
|
||||
struct el_torito_boot_image *img;
|
||||
struct el_torito_section_entry *se =
|
||||
(struct el_torito_section_entry*)buf;
|
||||
int app_idx, mode = 0;
|
||||
|
||||
img = t->catalog->bootimages[idx];
|
||||
|
||||
|
@ -826,16 +950,75 @@ write_section_entry(uint8_t *buf, Ecma119Image *t, int idx)
|
|||
se->boot_media_type[0] = img->type;
|
||||
iso_lsb(se->load_seg, img->load_seg, 2);
|
||||
se->system_type[0] = img->partition_type;
|
||||
iso_lsb(se->sec_count, img->load_size, 2);
|
||||
iso_lsb(se->block, t->bootsrc[idx]->sections[0].block, 4);
|
||||
|
||||
if (t->boot_appended_idx[idx] >= 0)
|
||||
if (t->appended_part_size[t->boot_appended_idx[idx]] > 0)
|
||||
mode = 2; /* appended partition */
|
||||
if (mode == 0 && t->opts->appendable &&
|
||||
(t->boot_intvl_start[idx] > 0 || t->boot_intvl_size[idx] > 0) &&
|
||||
t->boot_intvl_start[idx] + (t->boot_intvl_size[idx] + 3) / 4 <=
|
||||
t->opts->ms_block)
|
||||
mode = 1; /* image interval */
|
||||
if (mode == 0 && t->boot_appended_idx[idx] >= 0) {
|
||||
iso_msg_submit(t->image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
|
||||
"Appended partition which shall serve as boot image does not exist");
|
||||
return ISO_BOOT_IMAGE_NOT_VALID;
|
||||
}
|
||||
|
||||
if (mode == 1) {
|
||||
if (t->boot_intvl_start[idx] + (t->boot_intvl_size[idx] + 3) / 4 >
|
||||
t->total_size / 2048 + t->opts->ms_block - t->eff_partition_offset
|
||||
) {
|
||||
iso_msg_submit(t->image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
|
||||
"Block interval which shall serve as boot image is outside result range");
|
||||
return ISO_BOOT_IMAGE_NOT_VALID;
|
||||
}
|
||||
|
||||
/* >>> check for non-automatic load size */;
|
||||
|
||||
if (t->boot_intvl_size[idx] > 65535) {
|
||||
if (img->platform_id == 0xef)
|
||||
iso_lsb(se->sec_count, 0, 2);
|
||||
else
|
||||
iso_lsb(se->sec_count, 65535, 2);
|
||||
} else {
|
||||
if (t->boot_intvl_size[idx] == 0) {
|
||||
iso_msg_submit(t->image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
|
||||
"Block interval which shall serve as boot image has zero size");
|
||||
return ISO_BOOT_IMAGE_NOT_VALID;
|
||||
}
|
||||
iso_lsb(se->sec_count, t->boot_intvl_size[idx], 2);
|
||||
}
|
||||
iso_lsb(se->block, t->boot_intvl_start[idx], 4);
|
||||
} else if (mode == 2) {
|
||||
app_idx = t->boot_appended_idx[idx];
|
||||
|
||||
/* >>> check for non-automatic load size */;
|
||||
|
||||
if (t->appended_part_size[app_idx] * 4 > 65535) {
|
||||
if (img->platform_id == 0xef)
|
||||
iso_lsb(se->sec_count, 0, 2);
|
||||
else
|
||||
iso_lsb(se->sec_count, 65535, 2);
|
||||
} else {
|
||||
iso_lsb(se->sec_count, t->appended_part_size[app_idx] * 4, 2);
|
||||
}
|
||||
iso_lsb(se->block, t->appended_part_start[app_idx], 4);
|
||||
} else {
|
||||
write_section_load_size(img, se, (uint16_t) img->load_size,
|
||||
(off_t) t->bootsrc[idx]->sections[0].size, 0);
|
||||
iso_lsb(se->block, t->bootsrc[idx]->sections[0].block, 4);
|
||||
}
|
||||
|
||||
se->selec_criteria[0] = img->selection_crit[0];
|
||||
memcpy(se->vendor_sc, img->selection_crit + 1, 19);
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
int catalog_open(IsoStream *stream)
|
||||
{
|
||||
int i, j, k, num_entries;
|
||||
int i, j, k, num_entries, ret;
|
||||
struct catalog_stream *data;
|
||||
uint8_t *wpt;
|
||||
struct el_torito_boot_catalog *cat;
|
||||
|
@ -859,7 +1042,9 @@ int catalog_open(IsoStream *stream)
|
|||
boots[0]->platform_id, boots[0]->id_string);
|
||||
|
||||
/* write default entry = first boot image */
|
||||
write_section_entry(data->buffer + 32, data->target, 0);
|
||||
ret = write_section_entry(data->buffer + 32, data->target, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* IMPORTANT: The maximum number of boot images must fit into BLOCK_SIZE */
|
||||
wpt = data->buffer + 64;
|
||||
|
@ -880,7 +1065,9 @@ int catalog_open(IsoStream *stream)
|
|||
write_section_header(wpt, data->target, i, num_entries);
|
||||
wpt += 32;
|
||||
for (j = 0; j < num_entries; j++) {
|
||||
write_section_entry(wpt, data->target, i);
|
||||
ret = write_section_entry(wpt, data->target, i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
wpt += 32;
|
||||
i++;
|
||||
}
|
||||
|
@ -942,7 +1129,8 @@ int catalog_is_repeatable(IsoStream *stream)
|
|||
/**
|
||||
* fs_id will be the id reserved for El-Torito
|
||||
* dev_id will be 0 for catalog, 1 for boot image (if needed)
|
||||
* we leave ino_id for future use when we support multiple boot images
|
||||
* ino_id 0 is supposed to be unique. At write time it will get assigned
|
||||
* an automatic file serial number in the ISO, if needed.
|
||||
*/
|
||||
static
|
||||
void catalog_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id,
|
||||
|
@ -1117,7 +1305,10 @@ int patch_boot_info_table(uint8_t *buf, Ecma119Image *t,
|
|||
return iso_msg_submit(t->image->id, ISO_ISOLINUX_CANT_PATCH, 0,
|
||||
"Isolinux image too small. We won't patch it.");
|
||||
}
|
||||
ret = make_boot_info_table(buf, t->ms_block + (uint32_t) 16,
|
||||
if (t->bootsrc[idx] == NULL)
|
||||
return iso_msg_submit(t->image->id, ISO_ISOLINUX_CANT_PATCH, 0,
|
||||
"Cannot apply ISOLINUX patching outside of ISO 9660 filesystem.");
|
||||
ret = make_boot_info_table(buf, t->opts->ms_block + (uint32_t) 16,
|
||||
t->bootsrc[idx]->sections[0].block,
|
||||
(uint32_t) imgsize);
|
||||
return ret;
|
||||
|
@ -1136,7 +1327,10 @@ int patch_grub2_boot_image(uint8_t *buf, Ecma119Image *t,
|
|||
|
||||
if (imgsize < pos + 8)
|
||||
return iso_msg_submit(t->image->id, ISO_ISOLINUX_CANT_PATCH, 0,
|
||||
"Isolinux image too small for GRUB2. Will not patch it.");
|
||||
"Boot image too small for GRUB2. Will not patch it.");
|
||||
if (t->bootsrc[idx] == NULL)
|
||||
return iso_msg_submit(t->image->id, ISO_ISOLINUX_CANT_PATCH, 0,
|
||||
"Cannot apply GRUB2 patching outside of ISO 9660 filesystem.");
|
||||
blk = ((uint64_t) t->bootsrc[idx]->sections[0].block) * 4 + offst;
|
||||
iso_lsb((buf + pos), blk & 0xffffffff, 4);
|
||||
iso_lsb((buf + pos + 4), blk >> 32, 4);
|
||||
|
@ -1159,12 +1353,16 @@ int iso_patch_eltoritos(Ecma119Image *t)
|
|||
for (idx = 0; idx < t->catalog->num_bootimages; idx++) {
|
||||
if (!(t->catalog->bootimages[idx]->isolinux_options & 0x201))
|
||||
continue;
|
||||
if (t->bootsrc[idx] == NULL)
|
||||
return iso_msg_submit(t->image->id, ISO_ISOLINUX_CANT_PATCH, 0,
|
||||
"Cannot apply boot image patching outside of ISO 9660 filesystem");
|
||||
|
||||
original = t->bootsrc[idx]->stream;
|
||||
size = (size_t) iso_stream_get_size(original);
|
||||
|
||||
/* >>> BOOT ts B00428 :
|
||||
check whether size is not too large for buffering */;
|
||||
|
||||
if (size > Libisofs_elto_max_patchablE)
|
||||
return ISO_PATCH_OVERSIZED_BOOT;
|
||||
if (iso_stream_get_input_stream(original, 0) != NULL)
|
||||
return ISO_PATCH_FILTERED_BOOT;
|
||||
buf = calloc(1, size);
|
||||
if (buf == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
|
@ -1177,6 +1375,9 @@ int iso_patch_eltoritos(Ecma119Image *t)
|
|||
ret = iso_stream_read(original, buf, size);
|
||||
iso_stream_close(original);
|
||||
if (ret != (int) size) {
|
||||
if (ret >= 0)
|
||||
iso_msg_submit(t->image->id, ISO_FILE_READ_ERROR, 0,
|
||||
"Cannot read all bytes from El Torito boot image for boot info table");
|
||||
return (ret < 0) ? ret : (int) ISO_FILE_READ_ERROR;
|
||||
}
|
||||
|
||||
|
@ -1263,8 +1464,8 @@ int eltorito_writer_create(Ecma119Image *target)
|
|||
{
|
||||
int ret, idx, outsource_efi = 0;
|
||||
IsoImageWriter *writer;
|
||||
IsoFile *bootimg;
|
||||
IsoFileSrc *src;
|
||||
IsoFile *bootimg = NULL;
|
||||
IsoFileSrc *src = NULL;
|
||||
|
||||
writer = calloc(1, sizeof(IsoImageWriter));
|
||||
if (writer == NULL) {
|
||||
|
@ -1293,10 +1494,22 @@ int eltorito_writer_create(Ecma119Image *target)
|
|||
}
|
||||
}
|
||||
|
||||
if (target->efi_boot_partition != NULL)
|
||||
if (strcmp(target->efi_boot_partition, "--efi-boot-image") == 0)
|
||||
if (target->opts->efi_boot_partition != NULL)
|
||||
if (strcmp(target->opts->efi_boot_partition, "--efi-boot-image") == 0)
|
||||
outsource_efi = 1;
|
||||
for (idx = 0; idx < target->catalog->num_bootimages; idx++) {
|
||||
target->bootsrc[idx] = NULL;
|
||||
if (target->catalog->bootimages[idx]->appended_idx >= 0) {
|
||||
/* Use an appended partition as boot image rather than IsoFile */
|
||||
target->boot_appended_idx[idx] =
|
||||
target->catalog->bootimages[idx]->appended_idx;
|
||||
target->boot_intvl_start[idx] =
|
||||
target->catalog->bootimages[idx]->appended_start;
|
||||
target->boot_intvl_size[idx] =
|
||||
target->catalog->bootimages[idx]->appended_size;
|
||||
continue;
|
||||
}
|
||||
|
||||
bootimg = target->catalog->bootimages[idx]->image;
|
||||
ret = iso_file_src_create(target, bootimg, &src);
|
||||
if (ret < 0) {
|
||||
|
@ -1328,8 +1541,8 @@ int eltorito_writer_create(Ecma119Image *target)
|
|||
|
||||
if (outsource_efi) {
|
||||
/* Disable EFI Boot partition and complain */
|
||||
free(target->efi_boot_partition);
|
||||
target->efi_boot_partition = NULL;
|
||||
free(target->opts->efi_boot_partition);
|
||||
target->opts->efi_boot_partition = NULL;
|
||||
iso_msg_submit(target->image->id, ISO_BOOT_NO_EFI_ELTO, 0,
|
||||
"No newly added El Torito EFI boot image found for exposure as GPT partition");
|
||||
return ISO_BOOT_NO_EFI_ELTO;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2010 Thomas Schmitt
|
||||
* Copyright (c) 2010 - 2024 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -53,12 +53,24 @@ struct el_torito_boot_catalog {
|
|||
struct el_torito_boot_image {
|
||||
IsoFile *image;
|
||||
|
||||
/* Path of image at the time of ISO image loading (NULL = hidden image) */
|
||||
char *image_path;
|
||||
|
||||
/* Overrides .image if >= 0 : array index of appended partition */
|
||||
int appended_idx;
|
||||
uint32_t appended_start; /* In blocks of 2048 bytes */
|
||||
uint32_t appended_size; /* In blocks of 512 bytes */
|
||||
|
||||
unsigned int bootable:1; /**< If the entry is bootable. */
|
||||
/**
|
||||
* Whether the boot image seems to contain a boot_info_table
|
||||
*/
|
||||
unsigned int seems_boot_info_table:1;
|
||||
unsigned int seems_grub2_boot_info:1;
|
||||
/**
|
||||
* Whether the boot image seems to be capable of isohybrid
|
||||
*/
|
||||
unsigned int seems_isohybrid_capable:1;
|
||||
/**
|
||||
* isolinux options
|
||||
* bit 0 -> whether to patch image
|
||||
|
@ -72,10 +84,18 @@ struct el_torito_boot_image {
|
|||
* bit8= Mention in isohybrid Apple partition map
|
||||
*/
|
||||
unsigned int isolinux_options;
|
||||
unsigned char type; /**< The type of image */
|
||||
|
||||
unsigned char type; /**< The type of image :
|
||||
0=no emulation , 1=fd 1.2 MB , 2=fd 1.4 MB
|
||||
3=fd 3.8 MB , 4=hdd (size in partition table)
|
||||
*/
|
||||
unsigned char partition_type; /**< type of partition for HD-emul images */
|
||||
short load_seg; /**< Load segment for the initial boot image. */
|
||||
short load_size; /**< Number of sectors to load. */
|
||||
uint32_t emul_hdd_size; /* 512-bytes LBA after highest partition end from
|
||||
HD-emul partition table
|
||||
*/
|
||||
uint16_t load_seg; /**< Load segment for the initial boot image. */
|
||||
uint16_t load_size; /**< Number of sectors to load. */
|
||||
int load_size_full; /* 1= override load_size by image size */
|
||||
|
||||
/* Byte 1 of Validation Entry or Section Header Entry:
|
||||
0= 80x86, 1= PowerPC, 2= Mac, 0xef= EFI */
|
||||
|
@ -164,4 +184,11 @@ int iso_patch_eltoritos(Ecma119Image *t);
|
|||
#define Libisofs_grub2_elto_patch_offsT 5
|
||||
|
||||
|
||||
/* Maximum size of a boot image which is marked by
|
||||
el_torito_set_isolinux_options() for patching (boot info table,
|
||||
GRUB2 boot info, maybe others).
|
||||
*/
|
||||
#define Libisofs_elto_max_patchablE (32 * 1024 * 1024)
|
||||
|
||||
|
||||
#endif /* LIBISO_ELTORITO_H */
|
||||
|
|
|
@ -88,8 +88,8 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
|
|||
}
|
||||
|
||||
/* fill key and other atts */
|
||||
fsrc->no_write = (file->from_old_session && img->appendable);
|
||||
if (file->from_old_session && img->appendable) {
|
||||
fsrc->no_write = (file->from_old_session && img->opts->appendable);
|
||||
if (file->from_old_session && img->opts->appendable) {
|
||||
/*
|
||||
* On multisession discs we keep file sections from old image.
|
||||
*/
|
||||
|
@ -127,7 +127,8 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
|
|||
/* insert the filesrc in the tree */
|
||||
ret = iso_rbtree_insert(img->files, fsrc, (void**)src);
|
||||
if (ret <= 0) {
|
||||
if (ret == 0 && (*src)->checksum_index > 0 && !img->will_cancel) {
|
||||
if (ret == 0 && (*src)->checksum_index > 0 &&
|
||||
!img->opts->will_cancel) {
|
||||
/* Duplicate file source was mapped to previously registered source
|
||||
*/
|
||||
cret = iso_file_set_isofscx(file, (*src)->checksum_index, 0);
|
||||
|
@ -140,8 +141,8 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
|
|||
}
|
||||
iso_stream_ref(fsrc->stream);
|
||||
|
||||
if ((img->md5_file_checksums & 1) &&
|
||||
file->from_old_session && img->appendable) {
|
||||
if ((img->opts->md5_file_checksums & 1) &&
|
||||
file->from_old_session && img->opts->appendable) {
|
||||
ret = iso_node_get_xinfo((IsoNode *) file, checksum_md5_xinfo_func,
|
||||
&xipt);
|
||||
if (ret <= 0)
|
||||
|
@ -152,13 +153,14 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
|
|||
no_md5 = 1;
|
||||
}
|
||||
|
||||
if ((img->md5_file_checksums & 1) && !(no_md5 || img->will_cancel)) {
|
||||
if ((img->opts->md5_file_checksums & 1) &&
|
||||
!(no_md5 || img->opts->will_cancel)) {
|
||||
img->checksum_idx_counter++;
|
||||
if (img->checksum_idx_counter < 0x7fffffff) {
|
||||
fsrc->checksum_index = img->checksum_idx_counter;
|
||||
} else {
|
||||
fsrc->checksum_index= 0;
|
||||
img->checksum_idx_counter= 0x7fffffff; /* keep from rolling over */
|
||||
img->checksum_idx_counter= 0x7ffffffe; /* keep from rolling over */
|
||||
}
|
||||
cret = iso_file_set_isofscx(file, (*src)->checksum_index, 0);
|
||||
if (cret < 0)
|
||||
|
@ -227,12 +229,23 @@ int shall_be_written(void *arg)
|
|||
return f->no_write ? 0 : 1;
|
||||
}
|
||||
|
||||
static
|
||||
int shall_be_written_if_not_taken(void *arg)
|
||||
{
|
||||
IsoFileSrc *f = (IsoFileSrc *)arg;
|
||||
return f->no_write || f->taken ? 0 : 1;
|
||||
}
|
||||
|
||||
int filesrc_writer_pre_compute(IsoImageWriter *writer)
|
||||
{
|
||||
size_t i, size, is_external;
|
||||
Ecma119Image *t;
|
||||
IsoFileSrc **filelist;
|
||||
int (*inc_item)(void *);
|
||||
size_t omitted_count;
|
||||
IsoFileSrc **iso_ecma119_to_filesrc_array(Ecma119Image *t,
|
||||
int (*include_item)(void *),
|
||||
size_t *size);
|
||||
|
||||
if (writer == NULL) {
|
||||
return ISO_ASSERT_FAILURE;
|
||||
|
@ -244,24 +257,33 @@ int filesrc_writer_pre_compute(IsoImageWriter *writer)
|
|||
/* Normally reserve a single zeroed block for all files which have
|
||||
no block address: symbolic links, device files, empty data files.
|
||||
*/
|
||||
if (! t->old_empty)
|
||||
if (! t->opts->old_empty)
|
||||
t->filesrc_blocks++;
|
||||
|
||||
/* on appendable images, ms files shouldn't be included */
|
||||
if (t->appendable) {
|
||||
if (t->opts->appendable) {
|
||||
inc_item = shall_be_written;
|
||||
} else {
|
||||
inc_item = NULL;
|
||||
}
|
||||
|
||||
/* store the filesrcs in a array */
|
||||
filelist = (IsoFileSrc**)iso_rbtree_to_array(t->files, inc_item, &size);
|
||||
filelist = (IsoFileSrc**) iso_ecma119_to_filesrc_array(t, inc_item, &size);
|
||||
omitted_count = iso_rbtree_count_array(t->files, (size_t) 0,
|
||||
shall_be_written_if_not_taken);
|
||||
if (omitted_count > 0) {
|
||||
iso_msg_submit(t->image->id, ISO_NOT_REPRODUCIBLE, 0,
|
||||
"Cannot arrange content of data files in surely reproducible way");
|
||||
LIBISO_FREE_MEM(filelist);
|
||||
filelist = (IsoFileSrc**)iso_rbtree_to_array(
|
||||
t->files, inc_item, &size);
|
||||
}
|
||||
if (filelist == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
|
||||
/* sort files by weight, if needed */
|
||||
if (t->sort_files) {
|
||||
if (t->opts->sort_files) {
|
||||
qsort(filelist, size, sizeof(void*), cmp_by_weight);
|
||||
}
|
||||
|
||||
|
@ -436,7 +458,7 @@ int iso_filesrc_write_data(Ecma119Image *t, IsoFileSrc *file,
|
|||
file_size = iso_file_src_get_size(file);
|
||||
nblocks = DIV_UP(file_size, BLOCK_SIZE);
|
||||
pre_md5_valid = 0;
|
||||
if (file->checksum_index > 0 && (t->md5_file_checksums & 2)) {
|
||||
if (file->checksum_index > 0 && (t->opts->md5_file_checksums & 2)) {
|
||||
/* Obtain an MD5 of content by a first read pass */
|
||||
pre_md5_valid = filesrc_make_md5(t, file, pre_md5, 0);
|
||||
}
|
||||
|
@ -494,11 +516,11 @@ int iso_filesrc_write_data(Ecma119Image *t, IsoFileSrc *file,
|
|||
/* >>> HFS: need to align to allocation block size */;
|
||||
|
||||
#ifdef Libisofs_with_libjtE
|
||||
if (t->libjte_handle != NULL) {
|
||||
res = libjte_begin_data_file(t->libjte_handle, name,
|
||||
if (t->opts->libjte_handle != NULL) {
|
||||
res = libjte_begin_data_file(t->opts->libjte_handle, name,
|
||||
BLOCK_SIZE, file_size);
|
||||
if (res <= 0) {
|
||||
res = iso_libjte_forward_msgs(t->libjte_handle, t->image->id,
|
||||
res = iso_libjte_forward_msgs(t->opts->libjte_handle, t->image->id,
|
||||
ISO_LIBJTE_FILE_FAILED, 0);
|
||||
if (res < 0) {
|
||||
filesrc_close(file);
|
||||
|
@ -593,7 +615,7 @@ int iso_filesrc_write_data(Ecma119Image *t, IsoFileSrc *file,
|
|||
res = iso_md5_end(&ctx, md5);
|
||||
if (res <= 0)
|
||||
file->checksum_index = 0;
|
||||
if ((t->md5_file_checksums & 2) && pre_md5_valid > 0 &&
|
||||
if ((t->opts->md5_file_checksums & 2) && pre_md5_valid > 0 &&
|
||||
!was_error) {
|
||||
if (! iso_md5_match(md5, pre_md5)) {
|
||||
/* Issue MISHAP event */
|
||||
|
@ -619,8 +641,8 @@ ex:;
|
|||
|
||||
#ifdef Libisofs_with_libjtE
|
||||
if (jte_begun) {
|
||||
res = libjte_end_data_file(t->libjte_handle);
|
||||
iso_libjte_forward_msgs(t->libjte_handle, t->image->id,
|
||||
res = libjte_end_data_file(t->opts->libjte_handle);
|
||||
iso_libjte_forward_msgs(t->opts->libjte_handle, t->image->id,
|
||||
ISO_LIBJTE_END_FAILED, 0);
|
||||
if (res <= 0 && ret >= 0)
|
||||
ret = ISO_LIBJTE_FILE_FAILED;
|
||||
|
@ -658,7 +680,7 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
|||
files which have no block address:
|
||||
symbolic links, device files, empty data files.
|
||||
*/
|
||||
if (! t->old_empty) {
|
||||
if (! t->opts->old_empty) {
|
||||
ret = iso_write(t, buffer, BLOCK_SIZE);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
|
|
|
@ -32,6 +32,10 @@ struct Iso_File_Src
|
|||
*/
|
||||
unsigned int no_write :1;
|
||||
|
||||
/* Is 1 if the object was already put into the filelist array.
|
||||
*/
|
||||
unsigned int taken :1;
|
||||
|
||||
unsigned int checksum_index :31;
|
||||
|
||||
/** File Sections of the file in the image */
|
||||
|
|
|
@ -655,14 +655,41 @@ IsoStreamIface extf_stream_class = {
|
|||
static
|
||||
int extf_cmp_ino(IsoStream *s1, IsoStream *s2)
|
||||
{
|
||||
int i;
|
||||
ExternalFilterStreamData *data1, *data2;
|
||||
IsoExternalFilterCommand *cmd1, *cmd2;
|
||||
|
||||
/* This function may rely on being called by iso_stream_cmp_ino()
|
||||
only with s1, s2 which both point to it as their .cmp_ino() function.
|
||||
It would be a programming error to let any other than extf_stream_class
|
||||
point to extf_cmp_ino(). This fallback endangers transitivity of
|
||||
iso_stream_cmp_ino().
|
||||
*/
|
||||
if (s1->class != &extf_stream_class || s2->class != &extf_stream_class)
|
||||
return iso_stream_cmp_ino(s1, s2, 1);
|
||||
|
||||
data1 = (ExternalFilterStreamData*) s1->data;
|
||||
data2 = (ExternalFilterStreamData*) s2->data;
|
||||
if (data1->cmd != data2->cmd)
|
||||
return (data1->cmd < data2->cmd ? -1 : 1);
|
||||
cmd1 = data1->cmd;
|
||||
cmd2 = data2->cmd;
|
||||
if (cmd1 != cmd2) {
|
||||
if (strcmp(cmd1->name, cmd2->name) != 0)
|
||||
return strcmp(cmd1->name, cmd2->name);
|
||||
if (strcmp(cmd1->path, cmd2->path) != 0)
|
||||
return strcmp(cmd1->path, cmd2->path);
|
||||
if (cmd1->argc != cmd2->argc)
|
||||
return cmd1->argc < cmd2->argc ? -1 : 1;
|
||||
for (i = 0; i < cmd1->argc; i++) {
|
||||
if (strcmp(cmd1->argv[i], cmd2->argv[i]) != 0)
|
||||
return strcmp(cmd1->argv[i], cmd2->argv[i]);
|
||||
}
|
||||
if (cmd1->behavior != cmd2->behavior)
|
||||
return cmd1->behavior < cmd2->behavior ? -1 : 1;
|
||||
if (strcmp(cmd1->suffix, cmd2->suffix) != 0)
|
||||
return strcmp(cmd1->suffix, cmd2->suffix);
|
||||
}
|
||||
|
||||
/* Both streams apply the same treatment to their input streams */
|
||||
return iso_stream_cmp_ino(data1->orig, data2->orig, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -573,6 +573,9 @@ int gzip_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag)
|
|||
static
|
||||
int gzip_cmp_ino(IsoStream *s1, IsoStream *s2);
|
||||
|
||||
static
|
||||
int gzip_uncompress_cmp_ino(IsoStream *s1, IsoStream *s2);
|
||||
|
||||
|
||||
IsoStreamIface gzip_stream_compress_class = {
|
||||
4,
|
||||
|
@ -603,17 +606,44 @@ IsoStreamIface gzip_stream_uncompress_class = {
|
|||
gzip_stream_free,
|
||||
gzip_update_size,
|
||||
gzip_get_input_stream,
|
||||
gzip_cmp_ino,
|
||||
gzip_uncompress_cmp_ino,
|
||||
gzip_clone_stream
|
||||
};
|
||||
|
||||
|
||||
|
||||
static
|
||||
int gzip_cmp_ino(IsoStream *s1, IsoStream *s2)
|
||||
{
|
||||
/* This function may rely on being called by iso_stream_cmp_ino()
|
||||
only with s1, s2 which both point to it as their .cmp_ino() function.
|
||||
It would be a programming error to let any other than
|
||||
gzip_stream_compress_class point to gzip_cmp_ino().
|
||||
This fallback endangers transitivity of iso_stream_cmp_ino().
|
||||
*/
|
||||
if (s1->class != s2->class || (s1->class != &gzip_stream_compress_class &&
|
||||
s2->class != &gzip_stream_compress_class))
|
||||
return iso_stream_cmp_ino(s1, s2, 1);
|
||||
|
||||
/* Both streams apply the same treatment to their input streams */
|
||||
return iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0),
|
||||
iso_stream_get_input_stream(s2, 0), 0);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int gzip_uncompress_cmp_ino(IsoStream *s1, IsoStream *s2)
|
||||
{
|
||||
/* This function may rely on being called by iso_stream_cmp_ino()
|
||||
only with s1, s2 which both point to it as their .cmp_ino() function.
|
||||
It would be a programming error to let any other than
|
||||
gzip_stream_uncompress_class point to gzip_uncompress_cmp_ino().
|
||||
*/
|
||||
if (s1->class != s2->class ||
|
||||
(s1->class != &gzip_stream_uncompress_class &&
|
||||
s2->class != &gzip_stream_uncompress_class))
|
||||
return iso_stream_cmp_ino(s1, s2, 1);
|
||||
|
||||
/* Both streams apply the same treatment to their input streams */
|
||||
return iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0),
|
||||
iso_stream_get_input_stream(s2, 0), 0);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -65,7 +65,7 @@ int get_next(struct find_iter_data *iter, IsoNode **n)
|
|||
iter->itersec = NULL;
|
||||
}
|
||||
if (ret != 0) {
|
||||
/* succes or error */
|
||||
/* success or error */
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
3906
libisofs/fs_image.c
3906
libisofs/fs_image.c
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 - 2011 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2017 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -30,6 +30,11 @@
|
|||
#include <libgen.h>
|
||||
#include <string.h>
|
||||
|
||||
/* O_BINARY is needed for Cygwin but undefined elsewhere */
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
static
|
||||
int iso_file_source_new_lfs(IsoFileSource *parent, const char *name,
|
||||
IsoFileSource **src);
|
||||
|
@ -45,7 +50,7 @@ typedef struct
|
|||
/** reference to the parent (if root it points to itself) */
|
||||
IsoFileSource *parent;
|
||||
char *name;
|
||||
unsigned int openned :2; /* 0: not openned, 1: file, 2:dir */
|
||||
unsigned int openned :2; /* 0: not opened, 1: file, 2:dir */
|
||||
union
|
||||
{
|
||||
int fd;
|
||||
|
@ -222,7 +227,7 @@ int lfs_open(IsoFileSource *src)
|
|||
data->info.dir = opendir(path);
|
||||
data->openned = data->info.dir ? 2 : 0;
|
||||
} else {
|
||||
data->info.fd = open(path, O_RDONLY);
|
||||
data->info.fd = open(path, O_RDONLY | O_BINARY);
|
||||
data->openned = data->info.fd != -1 ? 1 : 0;
|
||||
}
|
||||
free(path);
|
||||
|
@ -282,6 +287,9 @@ static
|
|||
int lfs_read(IsoFileSource *src, void *buf, size_t count)
|
||||
{
|
||||
_LocalFsFileSource *data;
|
||||
size_t to_read, done = 0;
|
||||
int ret;
|
||||
uint8_t *buf8;
|
||||
|
||||
if (src == NULL || buf == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
|
@ -293,28 +301,28 @@ int lfs_read(IsoFileSource *src, void *buf, size_t count)
|
|||
data = src->data;
|
||||
switch (data->openned) {
|
||||
case 1: /* not dir */
|
||||
{
|
||||
int ret;
|
||||
ret = read(data->info.fd, buf, count);
|
||||
buf8 = (uint8_t *) buf; /* for pointer arithmetic */
|
||||
for (to_read = count; to_read > 0; to_read = count - done) {
|
||||
if (to_read > 1024 * 1024)
|
||||
to_read = 1024 * 1024;
|
||||
ret = read(data->info.fd, buf8 + done, to_read);
|
||||
if (ret < 0) {
|
||||
/* error on read */
|
||||
switch (errno) {
|
||||
case EINTR:
|
||||
ret = ISO_INTERRUPTED;
|
||||
break;
|
||||
return ISO_INTERRUPTED;
|
||||
case EFAULT:
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
break;
|
||||
return ISO_OUT_OF_MEM;
|
||||
case EIO:
|
||||
ret = ISO_FILE_READ_ERROR;
|
||||
break;
|
||||
default:
|
||||
ret = ISO_FILE_ERROR;
|
||||
break;
|
||||
return ISO_FILE_READ_ERROR;
|
||||
}
|
||||
return ISO_FILE_ERROR;
|
||||
}
|
||||
return ret;
|
||||
if (ret == 0) /* EOF */
|
||||
break;
|
||||
done += ret;
|
||||
}
|
||||
return done;
|
||||
case 2: /* directory */
|
||||
return ISO_FILE_IS_DIR;
|
||||
default:
|
||||
|
@ -329,7 +337,7 @@ off_t lfs_lseek(IsoFileSource *src, off_t offset, int flag)
|
|||
int whence;
|
||||
|
||||
if (src == NULL) {
|
||||
return (off_t)ISO_NULL_POINTER;
|
||||
return (off_t)((int) ISO_NULL_POINTER);
|
||||
}
|
||||
switch (flag) {
|
||||
case 0:
|
||||
|
@ -339,7 +347,7 @@ off_t lfs_lseek(IsoFileSource *src, off_t offset, int flag)
|
|||
case 2:
|
||||
whence = SEEK_END; break;
|
||||
default:
|
||||
return (off_t)ISO_WRONG_ARG_VALUE;
|
||||
return (off_t)((int) ISO_WRONG_ARG_VALUE);
|
||||
}
|
||||
|
||||
data = src->data;
|
||||
|
@ -352,19 +360,19 @@ off_t lfs_lseek(IsoFileSource *src, off_t offset, int flag)
|
|||
/* error on read */
|
||||
switch (errno) {
|
||||
case ESPIPE:
|
||||
ret = (off_t)ISO_FILE_ERROR;
|
||||
ret = (off_t)((int) ISO_FILE_ERROR);
|
||||
break;
|
||||
default:
|
||||
ret = (off_t)ISO_ERROR;
|
||||
ret = (off_t)((int) ISO_ERROR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
case 2: /* directory */
|
||||
return (off_t)ISO_FILE_IS_DIR;
|
||||
return (off_t)((int) ISO_FILE_IS_DIR);
|
||||
default:
|
||||
return (off_t)ISO_FILE_NOT_OPENED;
|
||||
return (off_t)((int) ISO_FILE_NOT_OPENED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -475,7 +483,7 @@ void lfs_free(IsoFileSource *src)
|
|||
|
||||
data = src->data;
|
||||
|
||||
/* close the file if it is already openned */
|
||||
/* close the file if it is already opened */
|
||||
if (data->openned) {
|
||||
src->class->close(src);
|
||||
}
|
||||
|
@ -491,14 +499,15 @@ void lfs_free(IsoFileSource *src)
|
|||
static
|
||||
int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag)
|
||||
{
|
||||
int ret;
|
||||
size_t num_attrs = 0, *value_lengths = NULL, result_len, sret;
|
||||
int ret, no_non_user_perm= 0;
|
||||
size_t num_attrs = 0, *value_lengths = NULL, result_len;
|
||||
ssize_t sret;
|
||||
char *path = NULL, **names = NULL, **values = NULL;
|
||||
unsigned char *result = NULL;
|
||||
|
||||
*aa_string = NULL;
|
||||
|
||||
if ((flag & 3 ) == 3) {
|
||||
if ((flag & 6 ) == 6) { /* Neither ACL nor xattr shall be read */
|
||||
ret = 1;
|
||||
goto ex;
|
||||
}
|
||||
|
@ -512,7 +521,7 @@ int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag)
|
|||
}
|
||||
ret = aaip_get_attr_list(path, &num_attrs, &names,
|
||||
&value_lengths, &values,
|
||||
(!(flag & 2)) | 2 | (flag & 4) | 16);
|
||||
(!(flag & 2)) | 2 | (flag & 4) | (flag & 8) | 16);
|
||||
if (ret <= 0) {
|
||||
if (ret == -2)
|
||||
ret = ISO_AAIP_NO_GET_LOCAL;
|
||||
|
@ -520,23 +529,26 @@ int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag)
|
|||
ret = ISO_FILE_ERROR;
|
||||
goto ex;
|
||||
}
|
||||
if(ret == 2)
|
||||
no_non_user_perm= 1;
|
||||
|
||||
if (num_attrs == 0)
|
||||
result = NULL;
|
||||
else {
|
||||
sret = aaip_encode(num_attrs, names,
|
||||
value_lengths, values, &result_len, &result, 0);
|
||||
if (sret == 0) {
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
if (sret < 0) {
|
||||
ret = sret;
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
*aa_string = result;
|
||||
ret = 1;
|
||||
ret = 1 + no_non_user_perm;
|
||||
ex:;
|
||||
if (path != NULL)
|
||||
free(path);
|
||||
if (names != NULL || value_lengths != NULL || values != NULL)
|
||||
aaip_get_attr_list(path, &num_attrs, &names, &value_lengths, &values,
|
||||
aaip_get_attr_list(NULL, &num_attrs, &names, &value_lengths, &values,
|
||||
1 << 15); /* free memory */
|
||||
return ret;
|
||||
}
|
||||
|
@ -803,7 +815,7 @@ int iso_local_filesystem_new(IsoFilesystem **fs)
|
|||
}
|
||||
|
||||
/* fill struct */
|
||||
strncpy(lfs->type, "file", 4);
|
||||
memcpy(lfs->type, "file", 4);
|
||||
lfs->refcount = 1;
|
||||
lfs->version = 0;
|
||||
lfs->data = NULL; /* we don't need private data */
|
||||
|
@ -858,17 +870,19 @@ int iso_local_get_attrs(char *disk_path, size_t *num_attrs, char ***names,
|
|||
(flag & (1 | 4 | 8 | 32 | (1 << 15))) | 2 | 16);
|
||||
if (ret <= 0)
|
||||
return ISO_AAIP_NO_GET_LOCAL;
|
||||
return 1;
|
||||
return 1 + (ret == 2);
|
||||
}
|
||||
|
||||
|
||||
int iso_local_set_attrs(char *disk_path, size_t num_attrs, char **names,
|
||||
size_t *value_lengths, char **values, int flag)
|
||||
int iso_local_set_attrs_errno(char *disk_path, size_t num_attrs, char **names,
|
||||
size_t *value_lengths, char **values,
|
||||
int *errnos, int flag)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = aaip_set_attr_list(disk_path, num_attrs, names, value_lengths,
|
||||
values, (flag & (8 | 32 | 64)) | !(flag & 1));
|
||||
values, errnos,
|
||||
(flag & (8 | 32 | 64 | 128)) | !(flag & 1));
|
||||
if (ret <= 0) {
|
||||
if (ret == -1)
|
||||
return ISO_OUT_OF_MEM;
|
||||
|
@ -886,6 +900,25 @@ int iso_local_set_attrs(char *disk_path, size_t num_attrs, char **names,
|
|||
}
|
||||
|
||||
|
||||
int iso_local_set_attrs(char *disk_path, size_t num_attrs, char **names,
|
||||
size_t *value_lengths, char **values, int flag)
|
||||
{
|
||||
int ret;
|
||||
int *errnos = NULL;
|
||||
|
||||
if(num_attrs > 0) {
|
||||
errnos= calloc(num_attrs, sizeof(int));
|
||||
if(errnos == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
ret= iso_local_set_attrs_errno(disk_path, num_attrs, names, value_lengths,
|
||||
values, errnos, flag);
|
||||
if(errnos != NULL)
|
||||
free(errnos);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int iso_local_get_perms_wo_acl(char *disk_path, mode_t *st_mode, int flag)
|
||||
{
|
||||
struct stat stbuf;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2022 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -133,3 +134,104 @@ int iso_file_source_get_aa_string(IsoFileSource *src,
|
|||
return src->class->get_aa_string(src, aa_string, flag);
|
||||
}
|
||||
|
||||
|
||||
/* @flag bit0= Open and close src
|
||||
bit1= Try iso_file_source_lseek(, 0) (=SEEK_SET) with wanted_size
|
||||
@return <0 iso_file_source_lseek failed , >= 0 readable capacity
|
||||
*/
|
||||
off_t iso_file_source_lseek_capacity(IsoFileSource *src, off_t wanted_size,
|
||||
int flag)
|
||||
{
|
||||
int ret, opened = 0;
|
||||
off_t end, old, reset;
|
||||
struct stat info;
|
||||
|
||||
ret = iso_file_source_stat(src, &info);
|
||||
if (ret < 0) {
|
||||
end = -1;
|
||||
goto ex;
|
||||
}
|
||||
if (S_ISDIR(info.st_mode) || S_ISLNK(info.st_mode) ||
|
||||
S_ISFIFO(info.st_mode) || S_ISSOCK(info.st_mode)) {
|
||||
/* open(2) on fifo can block and have side effects.
|
||||
Active Unix sockets have not been tested but they make as few sense
|
||||
as directories or symbolic links.
|
||||
*/
|
||||
end = -1;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
if (flag & 1) {
|
||||
ret = iso_file_source_open(src);
|
||||
if (ret < 0) {
|
||||
end = -1;
|
||||
goto ex;
|
||||
}
|
||||
opened = 1;
|
||||
}
|
||||
old = iso_file_source_lseek(src, 0, 1);
|
||||
if (old < 0) {
|
||||
end = -1;
|
||||
goto ex;
|
||||
}
|
||||
if(flag & 2) {
|
||||
end = iso_file_source_lseek(src, wanted_size, 0);
|
||||
} else {
|
||||
end = iso_file_source_lseek(src, 0, 2);
|
||||
}
|
||||
if (end < 0) {
|
||||
end = -1;
|
||||
goto ex;
|
||||
}
|
||||
reset = iso_file_source_lseek(src, old, 0);
|
||||
if (reset != old) {
|
||||
end = -1;
|
||||
goto ex;
|
||||
}
|
||||
ex:;
|
||||
if (opened) {
|
||||
iso_file_source_close(src);
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
||||
|
||||
/* Determine whether src is random-access readable and return its capacity.
|
||||
@flag bit0= For iso_file_source_lseek_capacity(): Open and close src
|
||||
bit1= wanted_size is valid
|
||||
*/
|
||||
off_t iso_file_source_determine_capacity(IsoFileSource *src, off_t wanted_size,
|
||||
int flag)
|
||||
{
|
||||
int ret;
|
||||
off_t src_size, src_seek_size= -1;
|
||||
struct stat info;
|
||||
|
||||
ret = iso_file_source_stat(src, &info);
|
||||
if (ret < 0) {
|
||||
return (off_t) -1;
|
||||
}
|
||||
if (S_ISREG(info.st_mode)) {
|
||||
return info.st_size;
|
||||
}
|
||||
src_size = iso_file_source_lseek_capacity(src, wanted_size, (flag & 1));
|
||||
if (src_size > 0) {
|
||||
return src_size;
|
||||
}
|
||||
if (!(flag & 2)) {
|
||||
if (src_size == 0) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
src_seek_size= src_size;
|
||||
|
||||
src_size = iso_file_source_lseek_capacity(src, wanted_size,
|
||||
2 | (flag & 1));
|
||||
if (src_size >= 0) {
|
||||
return src_size;
|
||||
} else if (src_seek_size >= 0) {
|
||||
return src_seek_size;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 - 2011 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2022 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -28,15 +28,19 @@
|
|||
* Create a new IsoFilesystem to deal with local filesystem.
|
||||
*
|
||||
* @return
|
||||
* 1 sucess, < 0 error
|
||||
* 1 success, < 0 error
|
||||
*/
|
||||
int iso_local_filesystem_new(IsoFilesystem **fs);
|
||||
|
||||
|
||||
/* Rank two IsoFileSource of ifs_class by their eventual old image LBAs.
|
||||
Other IsoFileSource classes will be ranked only roughly.
|
||||
* @param cmp_ret will return the reply value -1, 0, or 1.
|
||||
* @return 1= *cmp_ret is a valid reply
|
||||
* 0= not both streams are of ifs_class,
|
||||
* *cmp_ret is only a rough estimation.
|
||||
*/
|
||||
int iso_ifs_sections_cmp(IsoFileSource *s1, IsoFileSource *s2, int flag);
|
||||
int iso_ifs_sections_cmp(IsoFileSource *s1, IsoFileSource *s2, int *cmp_ret,
|
||||
int flag);
|
||||
|
||||
|
||||
/* Create an independent copy of an ifs_class IsoFileSource.
|
||||
|
@ -45,4 +49,14 @@ int iso_ifs_source_clone(IsoFileSource *old_source, IsoFileSource **new_source,
|
|||
int flag);
|
||||
|
||||
|
||||
off_t iso_file_source_lseek_capacity(IsoFileSource *src, off_t wanted_size,
|
||||
int flag);
|
||||
|
||||
/* Determine whether src is random-access readable and return its capacity.
|
||||
*/
|
||||
off_t iso_file_source_determine_capacity(IsoFileSource *src, off_t wanted_size,
|
||||
int flag);
|
||||
|
||||
|
||||
|
||||
#endif /*LIBISO_FSOURCE_H_*/
|
||||
|
|
|
@ -91,7 +91,7 @@ int filesrc_block_and_size(Ecma119Image *t, IsoFileSrc *src,
|
|||
*total_size += src->sections[i].size;
|
||||
if (pos != src->sections[i].block) {
|
||||
iso_msg_submit(t->image->id, ISO_SECT_SCATTERED, 0,
|
||||
"File sections do not form consequtive array of blocks");
|
||||
"File sections do not form consecutive array of blocks");
|
||||
return ISO_SECT_SCATTERED;
|
||||
}
|
||||
/* If .size is not aligned to blocks then there is a byte gap.
|
||||
|
@ -115,8 +115,8 @@ uint8_t get_class (uint16_t v)
|
|||
return hfsplus_class_pages[high][low];
|
||||
}
|
||||
|
||||
static
|
||||
int set_hfsplus_name(Ecma119Image *t, char *name, HFSPlusNode *node)
|
||||
int iso_get_hfsplus_name(char *input_charset, int imgid, char *name,
|
||||
uint16_t **result, uint32_t *result_len, uint16_t **cmp_name)
|
||||
{
|
||||
int ret;
|
||||
uint16_t *ucs_name, *iptr, *optr;
|
||||
|
@ -128,19 +128,21 @@ int set_hfsplus_name(Ecma119Image *t, char *name, HFSPlusNode *node)
|
|||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
ret = str2ucs(t->input_charset, name, &ucs_name);
|
||||
ret = str2utf16be(input_charset, name, &ucs_name);
|
||||
if (ret < 0) {
|
||||
iso_msg_debug(t->image->id, "Can't convert %s", name);
|
||||
iso_msg_debug(imgid, "Cannot convert '%s'", name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
curlen = ucslen (ucs_name);
|
||||
node->name = calloc ((curlen * HFSPLUS_MAX_DECOMPOSE_LEN + 1),
|
||||
sizeof (node->name[0]));
|
||||
if (!node->name)
|
||||
return ISO_OUT_OF_MEM;
|
||||
*result = calloc ((curlen * HFSPLUS_MAX_DECOMPOSE_LEN + 1),
|
||||
sizeof (uint16_t));
|
||||
if (*result == NULL) {
|
||||
free(ucs_name);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
|
||||
for (iptr = ucs_name, optr = node->name; *iptr; iptr++)
|
||||
for (iptr = ucs_name, optr = *result; *iptr; iptr++)
|
||||
{
|
||||
const uint16_t *dptr;
|
||||
uint16_t val = iso_ntohs (*iptr);
|
||||
|
@ -189,7 +191,7 @@ int set_hfsplus_name(Ecma119Image *t, char *name, HFSPlusNode *node)
|
|||
if (!ucs_name[0])
|
||||
break;
|
||||
last_class = get_class (ucs_name[0]);
|
||||
for (optr = node->name + 1; *optr; optr++)
|
||||
for (optr = *result + 1; *optr; optr++)
|
||||
{
|
||||
uint8_t new_class = get_class (*optr);
|
||||
|
||||
|
@ -207,11 +209,15 @@ int set_hfsplus_name(Ecma119Image *t, char *name, HFSPlusNode *node)
|
|||
}
|
||||
while (done);
|
||||
|
||||
node->cmp_name = calloc ((ucslen (node->name) + 1), sizeof (node->cmp_name[0]));
|
||||
if (!node->cmp_name)
|
||||
return ISO_OUT_OF_MEM;
|
||||
*cmp_name = calloc ((ucslen (*result) + 1), sizeof (uint16_t));
|
||||
if (*cmp_name == NULL) {
|
||||
free(ucs_name);
|
||||
free(*result);
|
||||
*result = NULL;
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
|
||||
for (iptr = node->name, optr = node->cmp_name; *iptr; iptr++)
|
||||
for (iptr = *result, optr = *cmp_name; *iptr; iptr++)
|
||||
{
|
||||
*optr = iso_hfsplus_cichar(*iptr);
|
||||
if (*optr != 0)
|
||||
|
@ -221,10 +227,19 @@ int set_hfsplus_name(Ecma119Image *t, char *name, HFSPlusNode *node)
|
|||
|
||||
free (ucs_name);
|
||||
|
||||
node->strlen = ucslen (node->name);
|
||||
*result_len = ucslen (*result);
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
int set_hfsplus_name(Ecma119Image *t, char *name, HFSPlusNode *node)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = iso_get_hfsplus_name(t->input_charset, t->image->id, name,
|
||||
&(node->name), &(node->strlen), &(node->cmp_name));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* >>> ts B20617
|
||||
This should be HFSPlusNode rather than IsoNode in order to have access
|
||||
|
@ -390,7 +405,8 @@ int create_tree(Ecma119Image *t, IsoNode *iso, uint32_t parent_id)
|
|||
if (cret < 0)
|
||||
return cret;
|
||||
pos = pos->next;
|
||||
t->hfsp_leafs[cleaf].nchildren++;
|
||||
if (cret > 0)
|
||||
t->hfsp_leafs[cleaf].nchildren++;
|
||||
}
|
||||
}
|
||||
return ISO_SUCCESS;
|
||||
|
@ -429,7 +445,7 @@ int hfsplus_tail_writer_compute_data_blocks(IsoImageWriter *writer)
|
|||
}
|
||||
|
||||
t = writer->target;
|
||||
block_size = t->hfsp_block_size;
|
||||
block_size = t->opts->hfsp_block_size;
|
||||
block_fac = t->hfsp_iso_block_fac;
|
||||
|
||||
#ifdef Libisofs_ts_debuG
|
||||
|
@ -466,7 +482,8 @@ int hfsplus_tail_writer_compute_data_blocks(IsoImageWriter *writer)
|
|||
|
||||
t->hfsp_total_blocks = hfsp_curblock - t->hfsp_part_start;
|
||||
|
||||
return iso_quick_apm_entry(t, t->hfsp_part_start / block_fac,
|
||||
return iso_quick_apm_entry(t->apm_req, &(t->apm_req_count),
|
||||
t->hfsp_part_start / block_fac,
|
||||
t->hfsp_total_blocks / block_fac +
|
||||
!!(t->hfsp_total_blocks % block_fac),
|
||||
"HFSPLUS_Hybrid", "Apple_HFS");
|
||||
|
@ -477,17 +494,16 @@ static
|
|||
int hfsplus_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
{
|
||||
Ecma119Image *t;
|
||||
uint32_t i, link_blocks, hfsp_curblock;
|
||||
uint32_t block_fac, cat_node_size, block_size;
|
||||
uint32_t i, hfsp_curblock;
|
||||
uint32_t block_fac, block_size;
|
||||
|
||||
if (writer == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
|
||||
t = writer->target;
|
||||
block_size = t->hfsp_block_size;
|
||||
block_size = t->opts->hfsp_block_size;
|
||||
block_fac = t->hfsp_iso_block_fac;
|
||||
cat_node_size = t->hfsp_cat_node_size;
|
||||
|
||||
iso_msg_debug(t->image->id, "(b) curblock=%d, nodes =%d", t->curblock, t->hfsp_nnodes);
|
||||
t->hfsp_part_start = t->curblock * block_fac;
|
||||
|
@ -500,7 +516,7 @@ int hfsplus_writer_compute_data_blocks(IsoImageWriter *writer)
|
|||
t->hfsp_catalog_file_start = hfsp_curblock;
|
||||
|
||||
/*
|
||||
hfsp_curblock += (t->hfsp_nnodes * cat_node_size + block_size - 1) / block_size;
|
||||
hfsp_curblock += (t->hfsp_nnodes * t->hfsp_cat_node_size + block_size - 1) / block_size;
|
||||
*/
|
||||
hfsp_curblock += 2 * t->hfsp_nnodes;
|
||||
|
||||
|
@ -509,7 +525,6 @@ int hfsplus_writer_compute_data_blocks(IsoImageWriter *writer)
|
|||
|
||||
iso_msg_debug(t->image->id, "(d) hfsp_curblock=%d, nodes =%d", hfsp_curblock, t->hfsp_nnodes);
|
||||
|
||||
link_blocks = 0;
|
||||
for (i = 0; i < t->hfsp_nleafs; i++)
|
||||
if (t->hfsp_leafs[i].unix_type == UNIX_SYMLINK)
|
||||
{
|
||||
|
@ -528,11 +543,14 @@ int hfsplus_writer_compute_data_blocks(IsoImageWriter *writer)
|
|||
}
|
||||
|
||||
|
||||
static void set_time (uint32_t *tm, uint32_t t)
|
||||
static inline uint32_t mac_time_offset(uint32_t t)
|
||||
{
|
||||
iso_msb ((uint8_t *) tm, t + 2082844800, 4);
|
||||
uint32_t val;
|
||||
iso_msb ((uint8_t *) &val, t + 2082844800, sizeof(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
int nop_writer_write_vol_desc(IsoImageWriter *writer)
|
||||
{
|
||||
return ISO_SUCCESS;
|
||||
|
@ -584,7 +602,7 @@ write_sb (Ecma119Image *t)
|
|||
|
||||
iso_msg_debug(t->image->id, "Write HFS+ superblock");
|
||||
|
||||
block_size = t->hfsp_block_size;
|
||||
block_size = t->opts->hfsp_block_size;
|
||||
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
ret = iso_write(t, buffer, 1024);
|
||||
|
@ -600,9 +618,9 @@ write_sb (Ecma119Image *t)
|
|||
/* Cleanly unmounted, software locked. */
|
||||
iso_msb ((uint8_t *) &sb.attributes, (1 << 8) | (1 << 15), 4);
|
||||
iso_msb ((uint8_t *) &sb.last_mounted_version, 0x6c69736f, 4);
|
||||
set_time (&sb.ctime, t->now);
|
||||
set_time (&sb.utime, t->now);
|
||||
set_time (&sb.fsck_time, t->now);
|
||||
sb.ctime = mac_time_offset(t->now);
|
||||
sb.utime = mac_time_offset(t->now);
|
||||
sb.fsck_time = mac_time_offset(t->now);
|
||||
iso_msb ((uint8_t *) &sb.file_count, t->hfsp_nfiles, 4);
|
||||
iso_msb ((uint8_t *) &sb.folder_count, t->hfsp_ndirs - 1, 4);
|
||||
iso_msb ((uint8_t *) &sb.blksize, block_size, 4);
|
||||
|
@ -644,7 +662,7 @@ write_sb (Ecma119Image *t)
|
|||
|
||||
}
|
||||
|
||||
memcpy (&sb.num_serial, &t->hfsp_serial_number, 8);
|
||||
memcpy (&sb.num_serial, &t->opts->hfsp_serial_number, 8);
|
||||
ret = iso_write(t, &sb, sizeof (sb));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -667,7 +685,7 @@ int hfsplus_writer_write_data(IsoImageWriter *writer)
|
|||
}
|
||||
|
||||
t = writer->target;
|
||||
block_size = t->hfsp_block_size;
|
||||
block_size = t->opts->hfsp_block_size;
|
||||
block_fac = t->hfsp_iso_block_fac;
|
||||
cat_node_size = t->hfsp_cat_node_size;
|
||||
|
||||
|
@ -835,12 +853,11 @@ int hfsplus_writer_write_data(IsoImageWriter *writer)
|
|||
((uint8_t *) &common->type)[1] = t->hfsp_leafs[curnode].type;
|
||||
iso_msb ((uint8_t *) &common->valence, t->hfsp_leafs[curnode].nchildren, 4);
|
||||
iso_msb ((uint8_t *) &common->fileid, t->hfsp_leafs[curnode].cat_id, 4);
|
||||
set_time (&common->ctime, t->hfsp_leafs[curnode].node->ctime);
|
||||
set_time (&common->mtime, t->hfsp_leafs[curnode].node->mtime);
|
||||
common->ctime = mac_time_offset(t->hfsp_leafs[curnode].node->ctime);
|
||||
common->mtime = mac_time_offset(t->hfsp_leafs[curnode].node->mtime);
|
||||
/* FIXME: distinguish attr_mtime and mtime. */
|
||||
set_time (&common->attr_mtime, t->hfsp_leafs[curnode].node->mtime);
|
||||
set_time (&common->atime, t->hfsp_leafs[curnode].node->atime);
|
||||
|
||||
common->attr_mtime = mac_time_offset(t->hfsp_leafs[curnode].node->mtime);
|
||||
common->atime = mac_time_offset(t->hfsp_leafs[curnode].node->atime);
|
||||
iso_msb ((uint8_t *) &common->uid, px_get_uid (t, t->hfsp_leafs[curnode].node), 4);
|
||||
iso_msb ((uint8_t *) &common->gid, px_get_gid (t, t->hfsp_leafs[curnode].node), 4);
|
||||
iso_msb ((uint8_t *) &common->mode, px_get_mode (t, t->hfsp_leafs[curnode].node, (t->hfsp_leafs[curnode].type == HFSPLUS_DIR)), 2);
|
||||
|
@ -1035,7 +1052,7 @@ int hfsplus_tail_writer_write_data(IsoImageWriter *writer)
|
|||
}
|
||||
|
||||
t = writer->target;
|
||||
block_size = t->hfsp_block_size;
|
||||
block_size = t->opts->hfsp_block_size;
|
||||
|
||||
#ifdef Libisofs_ts_debuG
|
||||
iso_msg_debug(t->image->id, "hfsplus tail writer writes at = %.f",
|
||||
|
@ -1227,7 +1244,7 @@ int update_symlink(Ecma119Image *target, uint32_t changed_idx, char *new_name,
|
|||
char *orig_dest, *orig_start, *orig_end;
|
||||
char *hfsp_dest, *hfsp_start, *hfsp_end;
|
||||
int ret = 0;
|
||||
unsigned int comp_len, orig_len, hfsp_len, hfsp_comp_len;
|
||||
unsigned int comp_len, orig_len, hfsp_len;
|
||||
|
||||
if (target->hfsp_leafs[link_idx].node->type != LIBISO_SYMLINK)
|
||||
return ISO_SUCCESS;
|
||||
|
@ -1271,7 +1288,6 @@ int update_symlink(Ecma119Image *target, uint32_t changed_idx, char *new_name,
|
|||
hfsp_end = strchr(hfsp_start, '/');
|
||||
if (hfsp_end == NULL)
|
||||
hfsp_end = hfsp_start + strlen(hfsp_start);
|
||||
hfsp_comp_len = hfsp_end - hfsp_start;
|
||||
|
||||
if (comp_len == 0 || (comp_len == 1 && orig_start[0] == '.'))
|
||||
continue;
|
||||
|
@ -1563,10 +1579,18 @@ int mangle_leafs(Ecma119Image *target, int flag)
|
|||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
void iso_setup_hfsplus_block_size(Ecma119Image *target)
|
||||
{
|
||||
if (target->opts->hfsp_block_size == 0)
|
||||
target->opts->hfsp_block_size = HFSPLUS_DEFAULT_BLOCK_SIZE;
|
||||
target->hfsp_cat_node_size = 2 * target->opts->hfsp_block_size;
|
||||
target->hfsp_iso_block_fac = 2048 / target->opts->hfsp_block_size;
|
||||
}
|
||||
|
||||
int hfsplus_writer_create(Ecma119Image *target)
|
||||
{
|
||||
int ret;
|
||||
IsoImageWriter *writer;
|
||||
IsoImageWriter *writer = NULL;
|
||||
int max_levels;
|
||||
int level = 0;
|
||||
IsoNode *pos;
|
||||
|
@ -1576,16 +1600,14 @@ int hfsplus_writer_create(Ecma119Image *target)
|
|||
|
||||
writer = calloc(1, sizeof(IsoImageWriter));
|
||||
if (writer == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
make_hfsplus_decompose_pages();
|
||||
make_hfsplus_class_pages();
|
||||
|
||||
if (target->hfsp_block_size == 0)
|
||||
target->hfsp_block_size = HFSPLUS_DEFAULT_BLOCK_SIZE;
|
||||
target->hfsp_cat_node_size = 2 * target->hfsp_block_size;
|
||||
target->hfsp_iso_block_fac = 2048 / target->hfsp_block_size;
|
||||
iso_setup_hfsplus_block_size(target);
|
||||
cat_node_size = target->hfsp_cat_node_size;
|
||||
|
||||
writer->compute_data_blocks = hfsplus_writer_compute_data_blocks;
|
||||
|
@ -1600,10 +1622,8 @@ int hfsplus_writer_create(Ecma119Image *target)
|
|||
target->hfsp_ndirs = 0;
|
||||
target->hfsp_cat_id = 16;
|
||||
ret = hfsplus_count_tree(target, (IsoNode*)target->image->root);
|
||||
if (ret < 0) {
|
||||
free((char *) writer);
|
||||
return ret;
|
||||
}
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
|
||||
for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++)
|
||||
target->hfsp_bless_id[i] = 0;
|
||||
|
@ -1613,12 +1633,13 @@ int hfsplus_writer_create(Ecma119Image *target)
|
|||
|
||||
target->hfsp_leafs = calloc (target->hfsp_nleafs, sizeof (target->hfsp_leafs[0]));
|
||||
if (target->hfsp_leafs == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
goto ex;
|
||||
}
|
||||
ret = set_hfsplus_name (target, target->image->volume_id,
|
||||
&target->hfsp_leafs[target->hfsp_curleaf]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto ex;
|
||||
target->hfsp_leafs[target->hfsp_curleaf].node = (IsoNode *) target->image->root;
|
||||
target->hfsp_leafs[target->hfsp_curleaf].used_size = target->hfsp_leafs[target->hfsp_curleaf].strlen * 2 + 8 + 2 + sizeof (struct hfsplus_catfile_common);
|
||||
|
||||
|
@ -1649,10 +1670,13 @@ int hfsplus_writer_create(Ecma119Image *target)
|
|||
{
|
||||
int cret;
|
||||
cret = create_tree(target, pos, 2);
|
||||
if (cret < 0)
|
||||
return cret;
|
||||
if (cret < 0) {
|
||||
ret = cret;
|
||||
goto ex;
|
||||
}
|
||||
pos = pos->next;
|
||||
target->hfsp_leafs[0].nchildren++;
|
||||
if (cret > 0)
|
||||
target->hfsp_leafs[0].nchildren++;
|
||||
}
|
||||
|
||||
qsort(target->hfsp_leafs, target->hfsp_nleafs,
|
||||
|
@ -1660,13 +1684,14 @@ int hfsplus_writer_create(Ecma119Image *target)
|
|||
|
||||
ret = mangle_leafs(target, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto ex;
|
||||
|
||||
for (max_levels = 0; target->hfsp_nleafs >> max_levels; max_levels++);
|
||||
max_levels += 2;
|
||||
target->hfsp_levels = calloc (max_levels, sizeof (target->hfsp_levels[0]));
|
||||
if (target->hfsp_levels == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
target->hfsp_nnodes = 1;
|
||||
|
@ -1676,9 +1701,10 @@ int hfsplus_writer_create(Ecma119Image *target)
|
|||
unsigned bytes_rem = cat_node_size - sizeof (struct hfsplus_btnode) - 2;
|
||||
|
||||
target->hfsp_levels[level].nodes = calloc ((target->hfsp_nleafs + 1), sizeof (target->hfsp_levels[level].nodes[0]));
|
||||
if (!target->hfsp_levels[level].nodes)
|
||||
return ISO_OUT_OF_MEM;
|
||||
|
||||
if (!target->hfsp_levels[level].nodes) {
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
goto ex;
|
||||
}
|
||||
target->hfsp_levels[level].level_size = 0;
|
||||
for (i = 0; i < target->hfsp_nleafs; i++)
|
||||
{
|
||||
|
@ -1733,8 +1759,10 @@ int hfsplus_writer_create(Ecma119Image *target)
|
|||
level++;
|
||||
|
||||
target->hfsp_levels[level].nodes = calloc (((last_size + 1) / 2), sizeof (target->hfsp_levels[level].nodes[0]));
|
||||
if (!target->hfsp_levels[level].nodes)
|
||||
return ISO_OUT_OF_MEM;
|
||||
if (!target->hfsp_levels[level].nodes) {
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
target->hfsp_levels[level].level_size = 0;
|
||||
|
||||
|
@ -1769,16 +1797,21 @@ int hfsplus_writer_create(Ecma119Image *target)
|
|||
|
||||
if (target->hfsp_nnodes > (cat_node_size - 0x100) * 8)
|
||||
{
|
||||
return iso_msg_submit(target->image->id, ISO_MANGLE_TOO_MUCH_FILES, 0,
|
||||
"HFS+ map nodes aren't implemented");
|
||||
|
||||
return ISO_MANGLE_TOO_MUCH_FILES;
|
||||
iso_msg_submit(target->image->id, ISO_HFSPLUS_TOO_MANY_FILES, 0,
|
||||
"HFS+ map nodes aren't implemented");
|
||||
ret = ISO_HFSPLUS_TOO_MANY_FILES;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
/* add this writer to image */
|
||||
target->writers[target->nwriters++] = writer;
|
||||
writer = NULL;
|
||||
|
||||
return ISO_SUCCESS;
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
if (writer != NULL)
|
||||
free(writer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hfsplus_tail_writer_create(Ecma119Image *target)
|
||||
|
@ -1825,7 +1858,7 @@ struct iso_hfsplus_xinfo_data *iso_hfsplus_xinfo_new(int flag)
|
|||
}
|
||||
|
||||
/* The iso_node_xinfo_cloner function which gets associated to
|
||||
* iso_hfsplus_xinfo_func by iso_init() resp. iso_init_with_flag() via
|
||||
* iso_hfsplus_xinfo_func by iso_init() or iso_init_with_flag() via
|
||||
* iso_node_xinfo_make_clonable()
|
||||
*/
|
||||
int iso_hfsplus_xinfo_cloner(void *old_data, void **new_data, int flag)
|
||||
|
|
|
@ -194,4 +194,9 @@ void make_hfsplus_class_pages();
|
|||
|
||||
extern const uint16_t hfsplus_casefold[];
|
||||
|
||||
int iso_get_hfsplus_name(char *input_charset, int imgid, char *name,
|
||||
uint16_t **result, uint32_t *result_len, uint16_t **cmp_name);
|
||||
|
||||
void iso_setup_hfsplus_block_size(Ecma119Image *target);
|
||||
|
||||
#endif /* LIBISO_HFSPLUS_H */
|
||||
|
|
|
@ -422,6 +422,10 @@ static uint16_t class_page_data[] = {
|
|||
0x21, 0x230,
|
||||
0x22, 0x230,
|
||||
0x23, 0x230,
|
||||
0x00,
|
||||
|
||||
/* End of list */
|
||||
0x00
|
||||
};
|
||||
|
||||
uint16_t *hfsplus_class_pages[256];
|
||||
|
@ -434,7 +438,7 @@ void make_hfsplus_class_pages()
|
|||
uint16_t *rpt, *page_pt;
|
||||
int page_count = 0;
|
||||
|
||||
memset(class_pages, 0, 19 * 256);
|
||||
memset(class_pages, 0, 19 * 256 * sizeof(uint16_t));
|
||||
for (i = 0; i < 256; i++)
|
||||
hfsplus_class_pages[i] = NULL;
|
||||
|
||||
|
|
403
libisofs/image.c
403
libisofs/image.c
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 - 2013 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2024 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -17,11 +17,117 @@
|
|||
#include "node.h"
|
||||
#include "messages.h"
|
||||
#include "eltorito.h"
|
||||
#include "system_area.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
int iso_imported_sa_new(struct iso_imported_sys_area **boots, int flag)
|
||||
{
|
||||
struct iso_imported_sys_area *b;
|
||||
|
||||
*boots = NULL;
|
||||
b = calloc(1, sizeof(struct iso_imported_sys_area));
|
||||
if (b == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
|
||||
b->mbr_req = NULL;
|
||||
b->apm_req = NULL;
|
||||
|
||||
b->gpt_req = NULL;
|
||||
b->gpt_backup_comments = NULL;
|
||||
|
||||
b->mips_boot_file_paths = NULL;
|
||||
b->mips_vd_entries = NULL;
|
||||
|
||||
b->sparc_disc_label = NULL;
|
||||
b->sparc_core_node = NULL;
|
||||
b->sparc_core_node_path = NULL;
|
||||
b->sparc_entries = NULL;
|
||||
|
||||
b->hppa_cmdline = NULL;
|
||||
b->hppa_bootloader = NULL;
|
||||
b->hppa_kernel_32 = NULL;
|
||||
b->hppa_kernel_64 = NULL;
|
||||
b->hppa_ramdisk = NULL;
|
||||
|
||||
b->alpha_boot_image = NULL;
|
||||
|
||||
*boots = b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int iso_imported_sa_unref(struct iso_imported_sys_area **boots, int flag)
|
||||
{
|
||||
int i;
|
||||
struct iso_imported_sys_area *b;
|
||||
|
||||
b = *boots;
|
||||
if (b == NULL)
|
||||
return 2;
|
||||
if (b->refcount > 0)
|
||||
b->refcount--;
|
||||
if (b->refcount > 0)
|
||||
return 2;
|
||||
|
||||
if (b->mbr_req != NULL) {
|
||||
for (i = 0; i < b->mbr_req_count; i++) {
|
||||
if (b->mbr_req[i] != NULL)
|
||||
LIBISO_FREE_MEM(b->mbr_req[i]->image_path);
|
||||
LIBISO_FREE_MEM(b->mbr_req[i]);
|
||||
}
|
||||
LIBISO_FREE_MEM(b->mbr_req);
|
||||
}
|
||||
if (b->apm_req != NULL) {
|
||||
for (i = 0; i < b->apm_req_count; i++) {
|
||||
if (b->apm_req[i] != NULL)
|
||||
LIBISO_FREE_MEM(b->apm_req[i]->image_path);
|
||||
LIBISO_FREE_MEM(b->apm_req[i]);
|
||||
}
|
||||
LIBISO_FREE_MEM(b->apm_req);
|
||||
}
|
||||
if (b->gpt_req != NULL) {
|
||||
for (i = 0; i < b->gpt_req_count; i++) {
|
||||
if (b->gpt_req[i] != NULL)
|
||||
LIBISO_FREE_MEM(b->gpt_req[i]->image_path);
|
||||
LIBISO_FREE_MEM(b->gpt_req[i]);
|
||||
}
|
||||
LIBISO_FREE_MEM(b->gpt_req);
|
||||
}
|
||||
LIBISO_FREE_MEM(b->gpt_backup_comments);
|
||||
|
||||
if (b->mips_boot_file_paths != NULL) {
|
||||
for (i = 0; i < b->num_mips_boot_files; i++)
|
||||
LIBISO_FREE_MEM(b->mips_boot_file_paths[i]);
|
||||
LIBISO_FREE_MEM(b->mips_boot_file_paths);
|
||||
}
|
||||
if (b->mips_vd_entries != NULL) {
|
||||
for (i = 0; i < b->num_mips_boot_files; i++)
|
||||
LIBISO_FREE_MEM(b->mips_vd_entries[i]);
|
||||
LIBISO_FREE_MEM(b->mips_vd_entries);
|
||||
}
|
||||
LIBISO_FREE_MEM(b->mipsel_boot_file_path);
|
||||
|
||||
LIBISO_FREE_MEM(b->sparc_disc_label);
|
||||
if (b->sparc_core_node != NULL)
|
||||
iso_node_unref((IsoNode *) b->sparc_core_node);
|
||||
LIBISO_FREE_MEM(b->sparc_core_node_path);
|
||||
LIBISO_FREE_MEM(b->sparc_entries);
|
||||
|
||||
LIBISO_FREE_MEM(b->hppa_cmdline);
|
||||
LIBISO_FREE_MEM(b->hppa_bootloader);
|
||||
LIBISO_FREE_MEM(b->hppa_kernel_32);
|
||||
LIBISO_FREE_MEM(b->hppa_kernel_64);
|
||||
LIBISO_FREE_MEM(b->hppa_ramdisk);
|
||||
LIBISO_FREE_MEM(b->alpha_boot_image);
|
||||
LIBISO_FREE_MEM(b);
|
||||
*boots = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new image, empty.
|
||||
*
|
||||
|
@ -85,8 +191,18 @@ int iso_image_new(const char *name, IsoImage **image)
|
|||
for (i = 0; i < 15; i++)
|
||||
img->mips_boot_file_paths[i] = NULL;
|
||||
img->sparc_core_node = NULL;
|
||||
img->hppa_cmdline= NULL;
|
||||
img->hppa_bootloader = NULL;
|
||||
img->hppa_kernel_32 = NULL;
|
||||
img->hppa_kernel_64 = NULL;
|
||||
img->hppa_ramdisk = NULL;
|
||||
img->alpha_boot_image = NULL;
|
||||
img->import_src = NULL;
|
||||
img->builder_ignore_acl = 1;
|
||||
img->builder_ignore_ea = 1;
|
||||
img->truncate_mode = 1;
|
||||
img->truncate_length = LIBISOFS_NODE_NAME_MAX;
|
||||
img->truncate_buffer[0] = 0;
|
||||
img->inode_counter = 0;
|
||||
img->used_inodes = NULL;
|
||||
img->used_inodes_start = 0;
|
||||
|
@ -97,6 +213,13 @@ int iso_image_new(const char *name, IsoImage **image)
|
|||
img->generator_is_running = 0;
|
||||
for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++)
|
||||
img->hfsplus_blessed[i] = NULL;
|
||||
img->collision_warnings = 0;
|
||||
img->imported_sa_info = NULL;
|
||||
img->blind_on_local_get_attrs = 0;
|
||||
img->do_deeper_tree_inspection = 0;
|
||||
img->tree_loaded = 0;
|
||||
img->rr_loaded = 0;
|
||||
img->tree_compliance = NULL;
|
||||
|
||||
*image = img;
|
||||
return ISO_SUCCESS;
|
||||
|
@ -140,6 +263,11 @@ void iso_image_unref(IsoImage *image)
|
|||
iso_image_give_up_mips_boot(image, 0);
|
||||
if (image->sparc_core_node != NULL)
|
||||
iso_node_unref((IsoNode *) image->sparc_core_node);
|
||||
iso_image_set_hppa_palo(image, NULL, NULL, NULL, NULL, NULL, 1);
|
||||
if (image->alpha_boot_image != NULL)
|
||||
free(image->alpha_boot_image);
|
||||
if (image->import_src != NULL)
|
||||
iso_data_source_unref(image->import_src);
|
||||
free(image->volset_id);
|
||||
free(image->volume_id);
|
||||
free(image->publisher_id);
|
||||
|
@ -158,6 +286,9 @@ void iso_image_unref(IsoImage *image)
|
|||
if (image->system_area_data != NULL)
|
||||
free(image->system_area_data);
|
||||
iso_image_free_checksums(image, 0);
|
||||
iso_imported_sa_unref(&(image->imported_sa_info), 0);
|
||||
if (image->tree_compliance != NULL)
|
||||
iso_write_opts_free(image->tree_compliance);
|
||||
free(image);
|
||||
}
|
||||
}
|
||||
|
@ -350,13 +481,18 @@ int iso_image_set_pvd_times(IsoImage *image,
|
|||
if (creation_time == NULL || modification_time == NULL ||
|
||||
expiration_time == NULL || effective_time == NULL)
|
||||
return ISO_NULL_POINTER;
|
||||
image->creation_time = strdup(creation_time);
|
||||
image->modification_time = strdup(modification_time);
|
||||
image->expiration_time = strdup(expiration_time);
|
||||
image->effective_time = strdup(effective_time);
|
||||
image->creation_time = calloc(18, 1); /* Surely including a trailing 0 */
|
||||
image->modification_time = calloc(18, 1);
|
||||
image->expiration_time = calloc(18, 1);
|
||||
image->effective_time = calloc(18, 1);
|
||||
if (image->creation_time == NULL || image->modification_time == NULL ||
|
||||
image->expiration_time == NULL || image->effective_time == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
/* (If the string is too short, a non-zero timezone will not be stored) */
|
||||
strncpy(image->creation_time, creation_time, 17);
|
||||
strncpy(image->modification_time, modification_time, 17);
|
||||
strncpy(image->expiration_time, expiration_time, 17);
|
||||
strncpy(image->effective_time, effective_time, 17);
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -406,6 +542,7 @@ static
|
|||
int dir_update_size(IsoImage *image, IsoDir *dir)
|
||||
{
|
||||
IsoNode *pos;
|
||||
int ret;
|
||||
|
||||
#ifdef Libisofs_update_sizes_abortablE
|
||||
char *path= NULL;
|
||||
|
@ -416,7 +553,6 @@ int dir_update_size(IsoImage *image, IsoDir *dir)
|
|||
|
||||
pos = dir->children;
|
||||
while (pos) {
|
||||
int ret = 1;
|
||||
if (pos->type == LIBISO_FILE) {
|
||||
ret = iso_stream_update_size(ISO_FILE(pos)->stream);
|
||||
} else if (pos->type == LIBISO_DIR) {
|
||||
|
@ -428,6 +564,8 @@ int dir_update_size(IsoImage *image, IsoDir *dir)
|
|||
return ret; /* Message already issued by dir_update_size */
|
||||
#endif
|
||||
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_update_sizes_abortablE
|
||||
|
@ -465,7 +603,12 @@ int dir_update_size(IsoImage *image, IsoDir *dir)
|
|||
return cancel_ret; /* cancel due error threshold */
|
||||
}
|
||||
|
||||
#endif /* Libisofs_update_sizes_abortablE */
|
||||
#else
|
||||
|
||||
if (ret < 0)
|
||||
ret = 1; /* ignore error */
|
||||
|
||||
#endif /* ! Libisofs_update_sizes_abortablE */
|
||||
|
||||
pos = pos->next;
|
||||
}
|
||||
|
@ -486,6 +629,15 @@ void iso_image_set_ignore_aclea(IsoImage *image, int what)
|
|||
{
|
||||
image->builder_ignore_acl = (what & 1);
|
||||
image->builder_ignore_ea = !!(what & 2);
|
||||
image->builder_take_all_ea = !!(what & 8);
|
||||
}
|
||||
|
||||
|
||||
int iso_image_get_ignore_aclea(IsoImage *image)
|
||||
{
|
||||
return image->builder_ignore_acl |
|
||||
(image->builder_ignore_ea << 1) |
|
||||
(image->builder_take_all_ea << 3);
|
||||
}
|
||||
|
||||
|
||||
|
@ -562,7 +714,8 @@ ex:;
|
|||
|
||||
|
||||
/**
|
||||
* A global counter for inode numbers for the ISO image filesystem.
|
||||
* A global counter for Rock Ridge inode numbers in the ISO image filesystem.
|
||||
*
|
||||
* On image import it gets maxed by the eventual inode numbers from PX
|
||||
* entries. Up to the first 32 bit rollover it simply increments the counter.
|
||||
* After the first rollover it uses a look ahead bitmap which gets filled
|
||||
|
@ -572,13 +725,13 @@ ex:;
|
|||
* @param image The image where the number shall be used
|
||||
* @param flag bit0= reset count (Caution: image must get new inos then)
|
||||
* @return
|
||||
* Since ino_t 0 is used as default and considered self-unique,
|
||||
* Since 0 is used as default and considered self-unique,
|
||||
* the value 0 should only be returned in case of error.
|
||||
*/
|
||||
ino_t img_give_ino_number(IsoImage *image, int flag)
|
||||
uint32_t img_give_ino_number(IsoImage *image, int flag)
|
||||
{
|
||||
int ret;
|
||||
ino_t new_ino, ino_idx;
|
||||
uint64_t new_ino, ino_idx;
|
||||
static uint64_t limit = 0xffffffff;
|
||||
|
||||
if (flag & 1) {
|
||||
|
@ -588,10 +741,10 @@ ino_t img_give_ino_number(IsoImage *image, int flag)
|
|||
image->used_inodes = NULL;
|
||||
image->used_inodes_start = 0;
|
||||
}
|
||||
new_ino = image->inode_counter + 1;
|
||||
new_ino = ((uint64_t) image->inode_counter) + 1;
|
||||
if (image->used_inodes == NULL) {
|
||||
if (new_ino > 0 && new_ino <= limit) {
|
||||
image->inode_counter = new_ino;
|
||||
image->inode_counter = (uint32_t) new_ino;
|
||||
return image->inode_counter;
|
||||
}
|
||||
}
|
||||
|
@ -851,3 +1004,227 @@ int iso_image_get_sparc_core(IsoImage *img, IsoFile **sparc_core, int flag)
|
|||
}
|
||||
|
||||
|
||||
/* @param flag
|
||||
bit0= Let NULL parameters free the corresponding image properties.
|
||||
Else only the non-NULL parameters of this call have an effect.
|
||||
*/
|
||||
static int hppa_palo_set_path(IsoImage *img, char *path, char **target,
|
||||
char *what, int flag)
|
||||
{
|
||||
int ret, err;
|
||||
IsoNode *node;
|
||||
IsoFile *file;
|
||||
|
||||
if (path == NULL && !(flag & 1))
|
||||
return ISO_SUCCESS;
|
||||
if (iso_clone_mgtd_mem(path, target, 0) < 0)
|
||||
return ISO_OUT_OF_MEM;
|
||||
if (path == NULL)
|
||||
return ISO_SUCCESS;
|
||||
ret = iso_tree_path_to_node(img, path, &node);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret == 0) {
|
||||
iso_msg_submit(img->id, ISO_BOOT_FILE_MISSING, 0,
|
||||
"Cannot find in ISO image: %s file '%s'", what, path);
|
||||
return ISO_BOOT_FILE_MISSING;
|
||||
}
|
||||
if (iso_node_get_type(node) != LIBISO_FILE) {
|
||||
err = ISO_HPPA_PALO_NOTREG;
|
||||
if (strncmp(what, "DEC Alpha", 9) == 0)
|
||||
err = ISO_ALPHA_BOOT_NOTREG;
|
||||
iso_msg_submit(img->id, err, 0,
|
||||
"%s file is not a data file: '%s'", what, path);
|
||||
return err;
|
||||
}
|
||||
file = (IsoFile *) node;
|
||||
if (!(file->explicit_weight || file->from_old_session))
|
||||
file->sort_weight = 2;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
/* @param flag
|
||||
Bitfield for control purposes
|
||||
bit0= Let NULL parameters free the corresponding image properties.
|
||||
Else only the non-NULL parameters of this call have an effect.
|
||||
*/
|
||||
int iso_image_set_hppa_palo(IsoImage *img, char *cmdline, char *bootloader,
|
||||
char *kernel_32, char *kernel_64, char *ramdisk,
|
||||
int flag)
|
||||
{
|
||||
int ret;
|
||||
static char *what = "HP-PA PALO";
|
||||
|
||||
if (cmdline != NULL || (flag & 1))
|
||||
if (iso_clone_mgtd_mem(cmdline, &(img->hppa_cmdline), 0) < 0)
|
||||
return ISO_OUT_OF_MEM;
|
||||
ret = hppa_palo_set_path(img, bootloader, &(img->hppa_bootloader), what,
|
||||
flag & 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = hppa_palo_set_path(img, kernel_32, &(img->hppa_kernel_32), what,
|
||||
flag & 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = hppa_palo_set_path(img, kernel_64, &(img->hppa_kernel_64), what,
|
||||
flag & 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = hppa_palo_set_path(img, ramdisk, &(img->hppa_ramdisk), what,
|
||||
flag & 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_image_get_hppa_palo(IsoImage *img, char **cmdline, char **bootloader,
|
||||
char **kernel_32, char **kernel_64, char **ramdisk)
|
||||
{
|
||||
*cmdline = img->hppa_cmdline;
|
||||
*bootloader = img->hppa_bootloader;
|
||||
*kernel_32 = img->hppa_kernel_32;
|
||||
*kernel_64 = img->hppa_kernel_64;
|
||||
*ramdisk = img->hppa_ramdisk;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_image_set_alpha_boot(IsoImage *img, char *boot_loader_path, int flag)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = hppa_palo_set_path(img, boot_loader_path, &(img->alpha_boot_image),
|
||||
"DEC Alpha Bootloader", 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_image_get_alpha_boot(IsoImage *img, char **boot_loader_path)
|
||||
{
|
||||
*boot_loader_path = img->alpha_boot_image;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_image_set_truncate_mode(IsoImage *img, int mode, int length)
|
||||
{
|
||||
if (mode < 0 || mode > 1)
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
if (length < 64 || length > LIBISOFS_NODE_NAME_MAX)
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
img->truncate_mode = mode;
|
||||
img->truncate_length = length;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
/* API */
|
||||
int iso_image_get_truncate_mode(IsoImage *img, int *mode, int *length)
|
||||
{
|
||||
*mode = img->truncate_mode;
|
||||
*length = img->truncate_length;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
/* Warning: Not thread-safe */
|
||||
int iso_image_truncate_name(IsoImage *image, const char *name, char **namept,
|
||||
int flag)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (name == NULL)
|
||||
return ISO_NULL_POINTER;
|
||||
|
||||
if ((int) strlen(name) <= image->truncate_length) {
|
||||
*namept = (char *) name;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
*namept = image->truncate_buffer;
|
||||
if (name != image->truncate_buffer)
|
||||
strncpy(image->truncate_buffer, name, 4095);
|
||||
image->truncate_buffer[4095] = 0;
|
||||
ret = iso_truncate_rr_name(image->truncate_mode, image->truncate_length,
|
||||
image->truncate_buffer, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_image_was_blind_attrs(IsoImage *image, int flag)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (image == NULL)
|
||||
return ISO_NULL_POINTER;
|
||||
ret = image->blind_on_local_get_attrs;
|
||||
if (flag & 1)
|
||||
image->blind_on_local_get_attrs = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @param flag bit0= recursion is active
|
||||
*/
|
||||
static
|
||||
int iso_dir_zisofs_discard_bpt(IsoDir *dir, int flag)
|
||||
{
|
||||
int ret;
|
||||
IsoDirIter *iter = NULL;
|
||||
IsoNode *node;
|
||||
IsoDir *subdir;
|
||||
IsoFile *file;
|
||||
IsoStream *stream;
|
||||
|
||||
ret = iso_dir_get_children(dir, &iter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
while (iso_dir_iter_next(iter, &node) == 1) {
|
||||
if (iso_node_get_type(node) == LIBISO_DIR) {
|
||||
subdir = (IsoDir *) node;
|
||||
ret = iso_dir_zisofs_discard_bpt(subdir, flag | 1);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
continue;
|
||||
}
|
||||
if (iso_node_get_type(node) != LIBISO_FILE)
|
||||
continue;
|
||||
file = (IsoFile *) node;
|
||||
stream = iso_file_get_stream(file);
|
||||
if (stream == NULL)
|
||||
continue;
|
||||
ret = iso_stream_zisofs_discard_bpt(stream, 0);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
if (iter != NULL)
|
||||
iso_dir_iter_free(iter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_image_zisofs_discard_bpt(IsoImage *image, int flag)
|
||||
{
|
||||
int ret;
|
||||
IsoDir *dir;
|
||||
|
||||
if (image == NULL)
|
||||
return ISO_NULL_POINTER;
|
||||
dir = image->root;
|
||||
if (dir == NULL)
|
||||
return ISO_SUCCESS;
|
||||
ret = iso_dir_zisofs_discard_bpt(dir, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
232
libisofs/image.h
232
libisofs/image.h
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 - 2012 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2024 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -22,13 +22,16 @@
|
|||
*/
|
||||
#define ISO_USED_INODE_RANGE (1 << 18)
|
||||
|
||||
/* How many warnings to issue about name collisions during iso_image_import()
|
||||
*/
|
||||
#define ISO_IMPORT_COLL_WARN_MAX 10
|
||||
|
||||
/*
|
||||
* Image is a context for image manipulation.
|
||||
* Global objects such as the message_queues must belogn to that
|
||||
* context. Thus we will have, for example, a msg queue per image,
|
||||
* so images are completelly independent and can be managed together.
|
||||
* (Usefull, for example, in Multiple-Document-Interface GUI apps.
|
||||
* so images are completely independent and can be managed together.
|
||||
* (Useful, for example, in Multiple-Document-Interface GUI apps.
|
||||
* [The stuff we have in init belongs really to image!]
|
||||
*/
|
||||
|
||||
|
@ -61,6 +64,8 @@ struct Iso_Image
|
|||
/* Eventually loaded system area data, or NULL */
|
||||
char *system_area_data;
|
||||
/* Prescribed/detected options, see iso_write_opts_set_system_area() */
|
||||
/* >>> Needs to be coordinated with .imported_sa_info->system_area_options
|
||||
*/
|
||||
int system_area_options;
|
||||
|
||||
/*
|
||||
|
@ -75,6 +80,19 @@ struct Iso_Image
|
|||
*/
|
||||
IsoFile *sparc_core_node;
|
||||
|
||||
/*
|
||||
* Parameters for HP-PA PALO boot sector. cmdline is a string. The other
|
||||
* four are absolute paths to data files in the ISO image.
|
||||
*/
|
||||
char *hppa_cmdline;
|
||||
char *hppa_bootloader;
|
||||
char *hppa_kernel_32;
|
||||
char *hppa_kernel_64;
|
||||
char *hppa_ramdisk;
|
||||
|
||||
/* Absolute DEC Alpha boot image path in the ISO image */
|
||||
char *alpha_boot_image;
|
||||
|
||||
/* image identifier, for message origin identifier */
|
||||
int id;
|
||||
|
||||
|
@ -83,6 +101,11 @@ struct Iso_Image
|
|||
*/
|
||||
IsoFilesystem *fs;
|
||||
|
||||
/**
|
||||
* Block storage of imported ISO if demanded by IsoReadOpts.
|
||||
*/
|
||||
IsoDataSource *import_src;
|
||||
|
||||
/*
|
||||
* Default builder to use when adding files to the image tree.
|
||||
*/
|
||||
|
@ -122,6 +145,12 @@ struct Iso_Image
|
|||
*/
|
||||
unsigned int builder_ignore_ea : 1;
|
||||
|
||||
/**
|
||||
* If not builder_ignore_ea : import all xattr namespaces from local
|
||||
* filesystem, not only "user.
|
||||
*/
|
||||
unsigned int builder_take_all_ea : 1;
|
||||
|
||||
/**
|
||||
* Files to exclude. Wildcard support is included.
|
||||
*/
|
||||
|
@ -137,6 +166,20 @@ struct Iso_Image
|
|||
/* TODO
|
||||
enum iso_replace_mode (*confirm_replace)(IsoFileSource *src, IsoNode *node);
|
||||
*/
|
||||
|
||||
/**
|
||||
* What to do in case of name longer than truncate_length:
|
||||
* 0= throw FAILURE
|
||||
* 1= truncate to truncate_length with MD5 of whole name at end
|
||||
*/
|
||||
int truncate_mode;
|
||||
int truncate_length;
|
||||
|
||||
/**
|
||||
* This is a convenience buffer for name truncation during image
|
||||
* manipulation where libisofs is not thread-safe anyway.
|
||||
*/
|
||||
char truncate_buffer[4096];
|
||||
|
||||
/**
|
||||
* When this is not NULL, it is a pointer to a function that will
|
||||
|
@ -158,18 +201,20 @@ struct Iso_Image
|
|||
* Inode number management. inode_counter is taken over from
|
||||
* IsoImageFilesystem._ImageFsData after image import.
|
||||
* It is to be used with img_give_ino_number()
|
||||
*/
|
||||
ino_t inode_counter;
|
||||
* This is a Rock Ridge file serial number. Thus 32 bit.
|
||||
*/
|
||||
uint32_t inode_counter;
|
||||
/*
|
||||
* A bitmap of used inode numbers in an interval beginning at
|
||||
* used_inodes_start and holding ISO_USED_INODE_RANGE bits.
|
||||
* If a bit is set, then the corresponding inode number is occupied.
|
||||
* This interval is kept around inode_counter and eventually gets
|
||||
* advanced by ISO_USED_INODE_RANGE numbers in a tree traversal
|
||||
* done by img_collect_inos().
|
||||
* done by img_collect_inos(). The value will stay in the 32 bit range,
|
||||
* although used_inodes_start is 64 bit to better handle rollovers.
|
||||
*/
|
||||
uint8_t *used_inodes;
|
||||
ino_t used_inodes_start;
|
||||
uint64_t used_inodes_start;
|
||||
|
||||
/**
|
||||
* Array of MD5 checksums as announced by xattr "isofs.ca" of the
|
||||
|
@ -196,9 +241,35 @@ struct Iso_Image
|
|||
*/
|
||||
IsoNode *hfsplus_blessed[ISO_HFSPLUS_BLESS_MAX];
|
||||
|
||||
/* Counts the name collisions while iso_image_import() */
|
||||
size_t collision_warnings;
|
||||
|
||||
/* Contains the assessment of boot aspects of the loaded image */
|
||||
struct iso_imported_sys_area *imported_sa_info;
|
||||
|
||||
/* Whether some local filesystem xattr namespace could not be explored
|
||||
* during node building.
|
||||
*/
|
||||
int blind_on_local_get_attrs;
|
||||
|
||||
/* Deeper tree inspection when reading an IsoImage assesses traces of the
|
||||
used write options.
|
||||
*/
|
||||
int do_deeper_tree_inspection;
|
||||
int tree_loaded; /* 0=ISO 9660/ECMA-119 1=Joliet 2=ISO 9660:1999 */
|
||||
int rr_loaded; /* 0=plain ISO 9660/ECMA-119 1=Rock Ridge */
|
||||
IsoWriteOpts *tree_compliance;
|
||||
};
|
||||
|
||||
|
||||
/* Apply truncation mode to name, using image->truncate_buffer to perform
|
||||
truncation if needed.
|
||||
|
||||
Warning: Not thread-safe !
|
||||
*/
|
||||
int iso_image_truncate_name(IsoImage *image, const char *name, char **namept,
|
||||
int flag);
|
||||
|
||||
|
||||
/* Collect the bitmap of used inode numbers in the range of
|
||||
_ImageFsData.used_inodes_start + ISO_USED_INODE_RANGE
|
||||
|
@ -217,10 +288,10 @@ int img_collect_inos(IsoImage *image, IsoDir *dir, int flag);
|
|||
* @param image The image where the number shall be used
|
||||
* @param flag bit0= reset count (Caution: image must get new inos then)
|
||||
* @return
|
||||
* Since ino_t 0 is used as default and considered self-unique,
|
||||
* Since 0 is used as default and considered self-unique,
|
||||
* the value 0 should only be returned in case of error.
|
||||
*/
|
||||
ino_t img_give_ino_number(IsoImage *image, int flag);
|
||||
uint32_t img_give_ino_number(IsoImage *image, int flag);
|
||||
|
||||
/* @param flag bit0= overwrite any ino, else only ino == 0
|
||||
bit1= install inode with non-data, non-directory files
|
||||
|
@ -247,4 +318,147 @@ int iso_image_set_pvd_times(IsoImage *image,
|
|||
char *creation_time, char *modification_time,
|
||||
char *expiration_time, char *effective_time);
|
||||
|
||||
|
||||
/* Collects boot block information obtained from the system area of
|
||||
imported images
|
||||
*/
|
||||
struct iso_imported_sys_area {
|
||||
|
||||
int refcount;
|
||||
|
||||
/* Whether there was some System Area data at all */
|
||||
int is_not_zero;
|
||||
|
||||
/* Giving the error number if the assessment ended by an error */
|
||||
int overall_return;
|
||||
|
||||
/* Block address of loaded Primar Volume Descriptor */
|
||||
uint32_t pvd_block;
|
||||
|
||||
/* Size of the imported ISO image */
|
||||
uint32_t image_size;
|
||||
|
||||
/* see libisofs.h : iso_write_opts_set_system_area() */
|
||||
int system_area_options;
|
||||
|
||||
/* The perceived MBR partitions */
|
||||
struct iso_mbr_partition_request **mbr_req;
|
||||
int mbr_req_count;
|
||||
|
||||
/* see ecma119.h : struct ecma119_image , struct iso_write_opts */
|
||||
/* Effective partition table parameter: 1 to 63, 0= disabled/default */
|
||||
int partition_secs_per_head;
|
||||
/* 1 to 255, 0= disabled/default */
|
||||
int partition_heads_per_cyl;
|
||||
|
||||
/* see ecma119.h : struct iso_write_opts */
|
||||
uint32_t partition_offset;
|
||||
|
||||
/* 2048-byte start LBA and block count of PreP partition */
|
||||
uint32_t prep_part_start;
|
||||
uint32_t prep_part_size;
|
||||
|
||||
/* see ecma119.h : struct ecma119_image */
|
||||
struct iso_apm_partition_request **apm_req;
|
||||
int apm_req_count;
|
||||
int apm_req_flags;
|
||||
/* Number of found "GapNN", "ISO9660_data" partitions in APM */
|
||||
int apm_gap_count;
|
||||
|
||||
/* see ecma119.h : struct iso_write_opts */
|
||||
int apm_block_size;
|
||||
|
||||
/* >>> see ecma119.h : struct iso_write_opts */
|
||||
int hfsp_block_size;
|
||||
|
||||
/* see ecma119.h : struct ecma119_image */
|
||||
struct iso_gpt_partition_request **gpt_req;
|
||||
int gpt_req_count;
|
||||
int gpt_req_flags;
|
||||
|
||||
/* see ecma119.h : struct ecma119_image */
|
||||
uint8_t gpt_disk_guid[16];
|
||||
/* Start of GPT entries in System Area, block size 512 */
|
||||
uint64_t gpt_part_start;
|
||||
uint32_t gpt_max_entries;
|
||||
uint64_t gpt_first_lba;
|
||||
uint64_t gpt_last_lba;
|
||||
uint64_t gpt_backup_lba;
|
||||
char *gpt_backup_comments;
|
||||
uint32_t gpt_head_crc_found;
|
||||
uint32_t gpt_head_crc_should;
|
||||
uint32_t gpt_array_crc_found;
|
||||
uint32_t gpt_array_crc_should;
|
||||
|
||||
/* see image.h : struct Iso_Image */
|
||||
int num_mips_boot_files;
|
||||
char **mips_boot_file_paths; /* ISO 9660 Rock Ridge Paths */
|
||||
struct iso_mips_voldir_entry **mips_vd_entries;
|
||||
|
||||
/* see ecma119.h : struct ecma119_image */
|
||||
/* Memorized ELF parameters from MIPS Little Endian boot file */
|
||||
uint32_t mipsel_e_entry;
|
||||
uint32_t mipsel_p_offset;
|
||||
uint32_t mipsel_p_vaddr;
|
||||
uint32_t mipsel_p_filesz;
|
||||
uint32_t mipsel_seg_start;
|
||||
char *mipsel_boot_file_path;
|
||||
|
||||
/* see image.h : struct Iso_Image */
|
||||
char *sparc_disc_label;
|
||||
int sparc_secs_per_head;
|
||||
int sparc_heads_per_cyl;
|
||||
struct iso_sun_disk_label_entry *sparc_entries;
|
||||
int sparc_entry_count;
|
||||
|
||||
/* grub2-sparc-core : a node in the ISO image
|
||||
published at bytes 0x228 to 0x233
|
||||
*/
|
||||
uint64_t sparc_grub2_core_adr;
|
||||
uint32_t sparc_grub2_core_size;
|
||||
IsoFile *sparc_core_node;
|
||||
|
||||
/* Only for representing the imported ISO:
|
||||
Path of file which held the partition content.
|
||||
NULL = no such file
|
||||
*/
|
||||
char *sparc_core_node_path;
|
||||
|
||||
/* see image.h : struct Iso_Image */
|
||||
int hppa_hdrversion;
|
||||
char *hppa_cmdline;
|
||||
uint32_t hppa_kern32_adr;
|
||||
uint32_t hppa_kern32_len;
|
||||
uint32_t hppa_kern64_adr;
|
||||
uint32_t hppa_kern64_len;
|
||||
uint32_t hppa_ramdisk_adr;
|
||||
uint32_t hppa_ramdisk_len;
|
||||
uint32_t hppa_bootloader_adr;
|
||||
uint32_t hppa_bootloader_len;
|
||||
uint32_t hppa_ipl_entry;
|
||||
char *hppa_kernel_32;
|
||||
char *hppa_kernel_64;
|
||||
char *hppa_ramdisk;
|
||||
char *hppa_bootloader;
|
||||
|
||||
uint64_t alpha_boot_image_size;
|
||||
uint64_t alpha_boot_image_adr;
|
||||
char *alpha_boot_image;
|
||||
|
||||
/* Some block addresses of active and first session:
|
||||
PVD, L Pathtable, Opt L, M Pathtable, Opt M, root directory
|
||||
*/
|
||||
uint32_t meta_struct_blocks[12];
|
||||
int num_meta_struct_blocks;
|
||||
};
|
||||
|
||||
int iso_imported_sa_new(struct iso_imported_sys_area **sa_info, int flag);
|
||||
|
||||
int iso_imported_sa_unref(struct iso_imported_sys_area **sa_info, int flag);
|
||||
|
||||
void iso_image_assess_ecma119_name(IsoImage *image, struct stat *info,
|
||||
char *path, char *name);
|
||||
void iso_image_assess_joliet_name(IsoImage *image, struct stat *info,
|
||||
char *path, char *name);
|
||||
|
||||
#endif /*LIBISO_IMAGE_H_*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2011-2012 Thomas Schmitt
|
||||
* Copyright (c) 2011-2014 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -80,7 +80,8 @@ void iso1999_node_free(Iso1999Node *node)
|
|||
for (i = 0; i < node->info.dir->nchildren; i++) {
|
||||
iso1999_node_free(node->info.dir->children[i]);
|
||||
}
|
||||
free(node->info.dir->children);
|
||||
if (node->info.dir->children != NULL)
|
||||
free(node->info.dir->children);
|
||||
free(node->info.dir);
|
||||
}
|
||||
iso_node_unref(node->node);
|
||||
|
@ -111,11 +112,14 @@ int create_node(Ecma119Image *t, IsoNode *iso, Iso1999Node **node)
|
|||
free(n);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
n->info.dir->children = calloc(sizeof(void*), dir->nchildren);
|
||||
if (n->info.dir->children == NULL) {
|
||||
free(n->info.dir);
|
||||
free(n);
|
||||
return ISO_OUT_OF_MEM;
|
||||
n->info.dir->children = NULL;
|
||||
if (dir->nchildren > 0) {
|
||||
n->info.dir->children = calloc(sizeof(void*), dir->nchildren);
|
||||
if (n->info.dir->children == NULL) {
|
||||
free(n->info.dir);
|
||||
free(n);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
}
|
||||
n->type = ISO1999_DIR;
|
||||
} else if (iso->type == LIBISO_FILE) {
|
||||
|
@ -125,7 +129,7 @@ int create_node(Ecma119Image *t, IsoNode *iso, Iso1999Node **node)
|
|||
IsoFile *file = (IsoFile*) iso;
|
||||
|
||||
size = iso_stream_get_size(file->stream);
|
||||
if (size > (off_t)MAX_ISO_FILE_SECTION_SIZE && t->iso_level != 3) {
|
||||
if (size > (off_t)MAX_ISO_FILE_SECTION_SIZE && t->opts->iso_level != 3) {
|
||||
char *ipath = iso_tree_get_node_path(iso);
|
||||
ret = iso_msg_submit(t->image->id, ISO_FILE_TOO_BIG, 0,
|
||||
"File \"%s\" can't be added to image because is "
|
||||
|
@ -194,7 +198,7 @@ int create_tree(Ecma119Image *t, IsoNode *iso, Iso1999Node **tree, int pathlen)
|
|||
}
|
||||
|
||||
max_path = pathlen + 1 + (iso_name ? strlen(iso_name): 0);
|
||||
if (!t->allow_longer_paths && max_path > 255) {
|
||||
if (!t->opts->allow_longer_paths && max_path > 255) {
|
||||
char *ipath = iso_tree_get_node_path(iso);
|
||||
ret = iso_msg_submit(t->image->id, ISO_FILE_IMGPATH_WRONG, 0,
|
||||
"File \"%s\" can't be added to ISO 9660:1999 tree, "
|
||||
|
@ -247,14 +251,33 @@ int create_tree(Ecma119Image *t, IsoNode *iso, Iso1999Node **tree, int pathlen)
|
|||
}
|
||||
break;
|
||||
case LIBISO_SYMLINK:
|
||||
case LIBISO_SPECIAL:
|
||||
{
|
||||
t->iso1999_symlinks++;
|
||||
if (t->iso1999_symlinks == 1) {
|
||||
char *ipath = iso_tree_get_node_path(iso);
|
||||
ret = iso_msg_submit(t->image->id, ISO_FILE_IGNORED, 0,
|
||||
"Can't add %s to ISO 9660:1999 tree. This kind of files "
|
||||
"can only be added to a Rock Ridget tree. Skipping.",
|
||||
ipath);
|
||||
"Cannot add symbolic link %s to ISO 9660:1999 tree. Skipping.",
|
||||
ipath);
|
||||
free(ipath);
|
||||
} else {
|
||||
if (t->iso1999_symlinks == 2)
|
||||
iso_msg_submit(t->image->id, ISO_FILE_IGNORED, 0,
|
||||
"More symbolic links were omitted from ISO 9660:1999 tree.");
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
case LIBISO_SPECIAL:
|
||||
t->iso1999_specials++;
|
||||
if (t->iso1999_specials == 1) {
|
||||
char *ipath = iso_tree_get_node_path(iso);
|
||||
ret = iso_msg_submit(t->image->id, ISO_FILE_IGNORED, 0,
|
||||
"Cannot add special file %s to ISO 9660:1999 tree. Skipping.",
|
||||
ipath);
|
||||
free(ipath);
|
||||
} else {
|
||||
if (t->iso1999_specials == 2)
|
||||
iso_msg_submit(t->image->id, ISO_FILE_IGNORED, 0,
|
||||
"More special files were omitted from ISO 9660:1999 tree.");
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -279,7 +302,7 @@ cmp_node(const void *f1, const void *f2)
|
|||
/**
|
||||
* TODO #00027 Follow ISO 9660:1999 specs when sorting files
|
||||
* strcmp do not does exactly what ISO 9660:1999, 9.3, as characters
|
||||
* < 0x20 " " are allowed, so name len must be taken into accout
|
||||
* < 0x20 " " are allowed, so name len must be taken into account
|
||||
*/
|
||||
return strcmp(f->name, g->name);
|
||||
}
|
||||
|
@ -293,6 +316,8 @@ void sort_tree(Iso1999Node *root)
|
|||
{
|
||||
size_t i;
|
||||
|
||||
if (root->info.dir->children == NULL)
|
||||
return;
|
||||
qsort(root->info.dir->children, root->info.dir->nchildren,
|
||||
sizeof(void*), cmp_node);
|
||||
for (i = 0; i < root->info.dir->nchildren; i++) {
|
||||
|
@ -308,14 +333,18 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
|
|||
int ret;
|
||||
int i, nchildren;
|
||||
Iso1999Node **children;
|
||||
IsoHTable *table;
|
||||
IsoHTable *table = NULL;
|
||||
int need_sort = 0;
|
||||
char *full_name = NULL, *tmp = NULL;
|
||||
|
||||
nchildren = dir->info.dir->nchildren;
|
||||
if (nchildren <= 0) {
|
||||
ret = ISO_SUCCESS;
|
||||
goto ex;
|
||||
}
|
||||
children = dir->info.dir->children;
|
||||
LIBISO_ALLOC_MEM(full_name, char, 208);
|
||||
LIBISO_ALLOC_MEM(tmp, char, 208);
|
||||
nchildren = dir->info.dir->nchildren;
|
||||
children = dir->info.dir->children;
|
||||
|
||||
/* a hash table will temporary hold the names, for fast searching */
|
||||
ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash,
|
||||
|
@ -348,7 +377,7 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
|
|||
}
|
||||
|
||||
/*
|
||||
* A max of 7 characters is good enought, it allows handling up to
|
||||
* A max of 7 characters is good enough, it allows handling up to
|
||||
* 9,999,999 files with same name.
|
||||
*/
|
||||
while (digits < 8) {
|
||||
|
@ -722,13 +751,13 @@ void write_one_dir_record(Ecma119Image *t, Iso1999Node *node, int file_id,
|
|||
iso_bb(rec->block, block, 4);
|
||||
iso_bb(rec->length, len, 4);
|
||||
|
||||
/* was: iso_datetime_7(rec->recording_time, t->now, t->always_gmt);
|
||||
/* was: iso_datetime_7(rec->recording_time, t->now, t->opts->always_gmt);
|
||||
*/
|
||||
iso= node->node;
|
||||
iso_datetime_7(rec->recording_time,
|
||||
(t->dir_rec_mtime & 4) ? ( t->replace_timestamps ?
|
||||
t->timestamp : iso->mtime )
|
||||
: t->now, t->always_gmt);
|
||||
(t->opts->dir_rec_mtime & 4) ? ( t->replace_timestamps ?
|
||||
t->timestamp : iso->mtime )
|
||||
: t->now, t->opts->always_gmt);
|
||||
|
||||
rec->flags[0] = ((node->type == ISO1999_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0);
|
||||
iso_bb(rec->vol_seq_number, (uint32_t) 1, 2);
|
||||
|
@ -909,7 +938,7 @@ int write_path_table(Ecma119Image *t, Iso1999Node **pathlist, int l_type)
|
|||
int ret= ISO_SUCCESS;
|
||||
uint8_t *zeros = NULL;
|
||||
|
||||
/* 256 is just a convenient size large enought */
|
||||
/* 256 is just a convenient size large enough */
|
||||
LIBISO_ALLOC_MEM(buf, uint8_t, 256);
|
||||
|
||||
path_table_size = 0;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2007 Mario Danic
|
||||
* Copyright (c) 2011-2012 Thomas Schmitt
|
||||
* Copyright (c) 2011-2018 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -28,31 +28,69 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static
|
||||
int get_joliet_name(Ecma119Image *t, IsoNode *iso, uint16_t **name)
|
||||
/* @param flag bit0= Do not issue error messages
|
||||
*/
|
||||
int iso_get_joliet_name(IsoWriteOpts *opts, char *input_charset, int imgid,
|
||||
char *node_name, enum IsoNodeType node_type,
|
||||
size_t *joliet_ucs2_failures,
|
||||
uint16_t **name, int flag)
|
||||
{
|
||||
int ret;
|
||||
uint16_t *ucs_name;
|
||||
int ret = ISO_SUCCESS;
|
||||
uint16_t *ucs_name = NULL, *utf16_name = NULL;
|
||||
uint16_t *jname = NULL;
|
||||
|
||||
if (iso->name == NULL) {
|
||||
if (node_name == NULL) {
|
||||
/* it is not necessarily an error, it can be the root */
|
||||
*name = NULL;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
ret = str2ucs(t->input_charset, iso->name, &ucs_name);
|
||||
if (ret < 0) {
|
||||
iso_msg_debug(t->image->id, "Can't convert %s", iso->name);
|
||||
return ret;
|
||||
if (opts->joliet_utf16) {
|
||||
ret = str2utf16be(input_charset, node_name, &ucs_name);
|
||||
if (ret < 0) {
|
||||
if (!(flag & 512))
|
||||
iso_msg_debug(imgid, "Cannot convert to UTF-16 : \"%s\"",
|
||||
node_name);
|
||||
goto ex;
|
||||
}
|
||||
} else {
|
||||
ret = str2ucs(input_charset, node_name, &ucs_name);
|
||||
if (ret < 0) {
|
||||
if (!(flag & 512))
|
||||
iso_msg_debug(imgid, "Cannot convert to UCS-2 : \"%s\"",
|
||||
node_name);
|
||||
goto ex;
|
||||
}
|
||||
ret = str2utf16be(input_charset, node_name, &utf16_name);
|
||||
if (ret == ISO_SUCCESS) {
|
||||
if (ucscmp(ucs_name, utf16_name) != 0) {
|
||||
(*joliet_ucs2_failures)++;
|
||||
if (*joliet_ucs2_failures <= ISO_JOLIET_UCS2_WARN_MAX &&
|
||||
!(flag & 512)) {
|
||||
iso_msg_submit(imgid, ISO_NAME_NOT_UCS2, 0,
|
||||
"Filename not suitable for Joliet character set UCS-2 : \"%s\"",
|
||||
node_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (iso->type == LIBISO_DIR) {
|
||||
jname = iso_j_dir_id(ucs_name, t->joliet_long_names << 1);
|
||||
if (node_type == LIBISO_DIR) {
|
||||
jname = iso_j_dir_id(ucs_name, opts->joliet_long_names << 1);
|
||||
} else {
|
||||
jname = iso_j_file_id(ucs_name,
|
||||
(t->joliet_long_names << 1) | !!(t->no_force_dots & 2));
|
||||
(opts->joliet_long_names << 1) | !!(opts->no_force_dots & 2));
|
||||
}
|
||||
free(ucs_name);
|
||||
if (jname != NULL) {
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
if (ucs_name != NULL)
|
||||
free(ucs_name);
|
||||
if (utf16_name != NULL)
|
||||
free(utf16_name);
|
||||
if (ret != ISO_SUCCESS) {
|
||||
if (jname != NULL)
|
||||
free(jname);
|
||||
return ret;
|
||||
} else if (jname != NULL) {
|
||||
*name = jname;
|
||||
return ISO_SUCCESS;
|
||||
} else {
|
||||
|
@ -64,6 +102,19 @@ int get_joliet_name(Ecma119Image *t, IsoNode *iso, uint16_t **name)
|
|||
}
|
||||
}
|
||||
|
||||
static
|
||||
int get_joliet_name(Ecma119Image *t, IsoNode *iso, uint16_t **name)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = iso_get_joliet_name(t->opts, t->input_charset, t->image->id,
|
||||
iso->name, iso->type, &(t->joliet_ucs2_failures),
|
||||
name, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
void joliet_node_free(JolietNode *node)
|
||||
{
|
||||
|
@ -75,7 +126,8 @@ void joliet_node_free(JolietNode *node)
|
|||
for (i = 0; i < node->info.dir->nchildren; i++) {
|
||||
joliet_node_free(node->info.dir->children[i]);
|
||||
}
|
||||
free(node->info.dir->children);
|
||||
if (node->info.dir->children != NULL)
|
||||
free(node->info.dir->children);
|
||||
free(node->info.dir);
|
||||
}
|
||||
iso_node_unref(node->node);
|
||||
|
@ -106,11 +158,14 @@ int create_node(Ecma119Image *t, IsoNode *iso, JolietNode **node)
|
|||
free(joliet);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
joliet->info.dir->children = calloc(sizeof(void*), dir->nchildren);
|
||||
if (joliet->info.dir->children == NULL) {
|
||||
free(joliet->info.dir);
|
||||
free(joliet);
|
||||
return ISO_OUT_OF_MEM;
|
||||
joliet->info.dir->children = NULL;
|
||||
if (dir->nchildren > 0) {
|
||||
joliet->info.dir->children = calloc(sizeof(void*), dir->nchildren);
|
||||
if (joliet->info.dir->children == NULL) {
|
||||
free(joliet->info.dir);
|
||||
free(joliet);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
}
|
||||
joliet->type = JOLIET_DIR;
|
||||
} else if (iso->type == LIBISO_FILE) {
|
||||
|
@ -120,7 +175,8 @@ int create_node(Ecma119Image *t, IsoNode *iso, JolietNode **node)
|
|||
IsoFile *file = (IsoFile*) iso;
|
||||
|
||||
size = iso_stream_get_size(file->stream);
|
||||
if (size > (off_t)MAX_ISO_FILE_SECTION_SIZE && t->iso_level != 3) {
|
||||
if (size > (off_t)MAX_ISO_FILE_SECTION_SIZE &&
|
||||
t->opts->iso_level != 3) {
|
||||
char *ipath = iso_tree_get_node_path(iso);
|
||||
free(joliet);
|
||||
ret = iso_msg_submit(t->image->id, ISO_FILE_TOO_BIG, 0,
|
||||
|
@ -188,7 +244,7 @@ int create_tree(Ecma119Image *t, IsoNode *iso, JolietNode **tree, int pathlen)
|
|||
return ret;
|
||||
}
|
||||
max_path = pathlen + 1 + (jname ? ucslen(jname) * 2 : 0);
|
||||
if (!t->joliet_longer_paths && max_path > 240) {
|
||||
if (!t->opts->joliet_longer_paths && max_path > 240) {
|
||||
char *ipath = iso_tree_get_node_path(iso);
|
||||
/*
|
||||
* Wow!! Joliet is even more restrictive than plain ISO-9660,
|
||||
|
@ -245,14 +301,36 @@ int create_tree(Ecma119Image *t, IsoNode *iso, JolietNode **tree, int pathlen)
|
|||
}
|
||||
break;
|
||||
case LIBISO_SYMLINK:
|
||||
case LIBISO_SPECIAL:
|
||||
{
|
||||
t->joliet_symlinks++;
|
||||
if (t->joliet_symlinks == 1) {
|
||||
char *ipath = iso_tree_get_node_path(iso);
|
||||
/* This first ret might indicate the need to abort */
|
||||
ret = iso_msg_submit(t->image->id, ISO_FILE_IGNORED, 0,
|
||||
"Can't add %s to Joliet tree. %s can only be added to a "
|
||||
"Rock Ridge tree.", ipath, (iso->type == LIBISO_SYMLINK ?
|
||||
"Symlinks" : "Special files"));
|
||||
"Cannot add %s to Joliet tree. Symlinks can only be added to a "
|
||||
"Rock Ridge tree.", ipath);
|
||||
free(ipath);
|
||||
} else {
|
||||
if (t->joliet_symlinks == 2)
|
||||
iso_msg_submit(t->image->id, ISO_FILE_IGNORED, 0,
|
||||
"More symbolic links were omitted from Joliet tree.");
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
case LIBISO_SPECIAL:
|
||||
t->joliet_specials++;
|
||||
if (t->joliet_specials == 1) {
|
||||
char *ipath = iso_tree_get_node_path(iso);
|
||||
/* This first ret might indicate the need to abort */
|
||||
ret = iso_msg_submit(t->image->id, ISO_FILE_IGNORED, 0,
|
||||
"Cannot add %s to Joliet tree. "
|
||||
"Special files can only be added to a Rock Ridge tree.",
|
||||
ipath);
|
||||
free(ipath);
|
||||
} else {
|
||||
if (t->joliet_specials == 2)
|
||||
iso_msg_submit(t->image->id, ISO_FILE_IGNORED, 0,
|
||||
"More special files were omitted from Joliet tree.");
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -281,6 +359,8 @@ void sort_tree(JolietNode *root)
|
|||
{
|
||||
size_t i;
|
||||
|
||||
if (root->info.dir->children == NULL)
|
||||
return;
|
||||
qsort(root->info.dir->children, root->info.dir->nchildren,
|
||||
sizeof(void*), cmp_node);
|
||||
for (i = 0; i < root->info.dir->nchildren; i++) {
|
||||
|
@ -343,23 +423,41 @@ int joliet_create_mangled_name(uint16_t *dest, uint16_t *src, int digits,
|
|||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* From Joliet specs:
|
||||
* "ISO 9660 (Section 7.5.1) states that the sum of the following shall not
|
||||
* exceed 30:
|
||||
* - If there is a file name, the length of the file name.
|
||||
* - If there is a file name extension, the length of the file name extension.
|
||||
* On Joliet compliant media, however, the sum as calculated above shall not
|
||||
* exceed 128 [bytes], to allow for longer file identifiers."
|
||||
*
|
||||
* I.e. the dot does not count.
|
||||
*
|
||||
* (We have an option to lift the limit from 64*2 to 103*2, which is the
|
||||
* maximum to fit into an ISO 9660 directory record.)
|
||||
*/
|
||||
static
|
||||
int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
||||
{
|
||||
int ret;
|
||||
int i, nchildren, maxchar = 64;
|
||||
JolietNode **children;
|
||||
IsoHTable *table;
|
||||
IsoHTable *table = NULL;
|
||||
int need_sort = 0;
|
||||
uint16_t *full_name = NULL;
|
||||
uint16_t *tmp = NULL;
|
||||
|
||||
nchildren = dir->info.dir->nchildren;
|
||||
if (nchildren <= 0) {
|
||||
ret = ISO_SUCCESS;
|
||||
goto ex;
|
||||
}
|
||||
children = dir->info.dir->children;
|
||||
LIBISO_ALLOC_MEM(full_name, uint16_t, LIBISO_JOLIET_NAME_MAX);
|
||||
LIBISO_ALLOC_MEM(tmp, uint16_t, LIBISO_JOLIET_NAME_MAX);
|
||||
nchildren = dir->info.dir->nchildren;
|
||||
children = dir->info.dir->children;
|
||||
|
||||
if (t->joliet_long_names)
|
||||
if (t->opts->joliet_long_names)
|
||||
maxchar = 103;
|
||||
|
||||
/* a hash table will temporary hold the names, for fast searching */
|
||||
|
@ -393,7 +491,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
|||
}
|
||||
|
||||
/*
|
||||
* A max of 7 characters is good enought, it allows handling up to
|
||||
* A max of 7 characters is good enough, it allows handling up to
|
||||
* 9,999,999 files with same name.
|
||||
*/
|
||||
/* Important: joliet_create_mangled_name() relies on digits < 8 */
|
||||
|
@ -419,25 +517,26 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
|||
ext = dot + 1;
|
||||
|
||||
extlen = ucslen(ext);
|
||||
max = maxchar + 1 - extlen - 1 - digits;
|
||||
max = maxchar - extlen - digits;
|
||||
if (max <= 0) {
|
||||
/* this can happen if extension is too long */
|
||||
if (extlen + max > 3) {
|
||||
/*
|
||||
* This can happen if the extension is too long.
|
||||
* Reduce its length, to give name at least one
|
||||
* original character, if it has any.
|
||||
*/
|
||||
max = (dot > full_name);
|
||||
extlen = maxchar - max - digits;
|
||||
if (extlen < 3) {
|
||||
/*
|
||||
* reduce extension len, to give name an extra char
|
||||
* note that max is negative or 0
|
||||
*/
|
||||
extlen = extlen + max - 1;
|
||||
ext[extlen] = 0;
|
||||
max = maxchar + 2 - extlen - 1 - digits;
|
||||
} else {
|
||||
/*
|
||||
* error, we don't support extensions < 3
|
||||
* This can't happen with current limit of digits.
|
||||
* error, we do not reduce extensions to length < 3
|
||||
*
|
||||
* This cannot happen with current limit of digits
|
||||
* because maxchar is at least 64 and digits at most 7.
|
||||
*/
|
||||
ret = ISO_ERROR;
|
||||
goto mangle_cleanup;
|
||||
}
|
||||
ext[extlen] = 0;
|
||||
}
|
||||
/* ok, reduce name by digits */
|
||||
if (name + max < dot) {
|
||||
|
@ -446,10 +545,10 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
|||
} else {
|
||||
/* Directory, or file without extension */
|
||||
if (children[i]->type == JOLIET_DIR) {
|
||||
max = maxchar + 1 - digits;
|
||||
max = maxchar - digits;
|
||||
dot = NULL; /* dots have no meaning in dirs */
|
||||
} else {
|
||||
max = maxchar + 1 - digits;
|
||||
max = maxchar - digits;
|
||||
}
|
||||
name = full_name;
|
||||
if ((size_t) max < ucslen(name)) {
|
||||
|
@ -598,7 +697,7 @@ size_t calc_dirent_len(Ecma119Image *t, JolietNode *n)
|
|||
{
|
||||
/* note than name len is always even, so we always need the pad byte */
|
||||
int ret = n->name ? ucslen(n->name) * 2 + 34 : 34;
|
||||
if (n->type == JOLIET_FILE && !(t->omit_version_numbers & 3)) {
|
||||
if (n->type == JOLIET_FILE && !(t->opts->omit_version_numbers & 3)) {
|
||||
/* take into account version numbers */
|
||||
ret += 4;
|
||||
}
|
||||
|
@ -717,7 +816,7 @@ int joliet_writer_compute_data_blocks(IsoImageWriter *writer)
|
|||
t->curblock += DIV_UP(path_table_size, BLOCK_SIZE);
|
||||
t->joliet_path_table_size = path_table_size;
|
||||
|
||||
if (t->partition_offset > 0) {
|
||||
if (t->opts->partition_offset > 0) {
|
||||
/* Take into respect second directory tree */
|
||||
ndirs = t->joliet_ndirs;
|
||||
t->joliet_ndirs = 0;
|
||||
|
@ -766,7 +865,7 @@ void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id,
|
|||
|
||||
memcpy(rec->file_id, name, len_fi);
|
||||
|
||||
if (node->type == JOLIET_FILE && !(t->omit_version_numbers & 3)) {
|
||||
if (node->type == JOLIET_FILE && !(t->opts->omit_version_numbers & 3)) {
|
||||
len_dr += 4;
|
||||
rec->file_id[len_fi++] = 0;
|
||||
rec->file_id[len_fi++] = ';';
|
||||
|
@ -801,13 +900,13 @@ void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id,
|
|||
iso_bb(rec->block, block - t->eff_partition_offset, 4);
|
||||
iso_bb(rec->length, len, 4);
|
||||
|
||||
/* was: iso_datetime_7(rec->recording_time, t->now, t->always_gmt);
|
||||
/* was: iso_datetime_7(rec->recording_time, t->now, t->opts->always_gmt);
|
||||
*/
|
||||
iso= node->node;
|
||||
iso_datetime_7(rec->recording_time,
|
||||
(t->dir_rec_mtime & 2) ? ( t->replace_timestamps ?
|
||||
t->timestamp : iso->mtime )
|
||||
: t->now, t->always_gmt);
|
||||
(t->opts->dir_rec_mtime & 2) ? ( t->replace_timestamps ?
|
||||
t->timestamp : iso->mtime )
|
||||
: t->now, t->opts->always_gmt);
|
||||
|
||||
rec->flags[0] = ((node->type == JOLIET_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0);
|
||||
iso_bb(rec->vol_seq_number, (uint32_t) 1, 2);
|
||||
|
@ -828,18 +927,22 @@ void ucsncpy_pad(uint16_t *dest, const uint16_t *src, size_t max)
|
|||
csrc = (char*)src;
|
||||
|
||||
if (src != NULL) {
|
||||
len = MIN(ucslen(src) * 2, max);
|
||||
len = MIN(ucslen(src) * 2, max - (max % 2));
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
cdest[i] = csrc[i];
|
||||
if (len >= 2)
|
||||
iso_handle_split_utf16(dest + (len / 2 - 1));
|
||||
|
||||
for (i = len; i < max; i += 2) {
|
||||
for (i = len; i + 1 < max; i += 2) {
|
||||
cdest[i] = '\0';
|
||||
cdest[i + 1] = ' ';
|
||||
}
|
||||
if (max % 2)
|
||||
cdest[max - 1] = 0;
|
||||
}
|
||||
|
||||
int joliet_writer_write_vol_desc(IsoImageWriter *writer)
|
||||
|
@ -958,7 +1061,8 @@ int write_one_dir(Ecma119Image *t, JolietNode *dir)
|
|||
/* compute len of directory entry */
|
||||
fi_len = ucslen(child->name) * 2;
|
||||
len = fi_len + 34;
|
||||
if (child->type == JOLIET_FILE && !(t->omit_version_numbers & 3)) {
|
||||
if (child->type == JOLIET_FILE &&
|
||||
!(t->opts->omit_version_numbers & 3)) {
|
||||
len += 4;
|
||||
}
|
||||
|
||||
|
@ -1026,7 +1130,7 @@ int write_path_table(Ecma119Image *t, JolietNode **pathlist, int l_type)
|
|||
int ret= ISO_SUCCESS;
|
||||
uint8_t *zeros = NULL;
|
||||
|
||||
/* 256 is just a convenient size large enought */
|
||||
/* 256 is just a convenient size large enough */
|
||||
LIBISO_ALLOC_MEM(buf, uint8_t, 256);
|
||||
LIBISO_ALLOC_MEM(zeros, uint8_t, BLOCK_SIZE);
|
||||
path_table_size = 0;
|
||||
|
@ -1160,8 +1264,8 @@ int joliet_writer_write_data(IsoImageWriter *writer)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (t->partition_offset > 0) {
|
||||
t->eff_partition_offset = t->partition_offset;
|
||||
if (t->opts->partition_offset > 0) {
|
||||
t->eff_partition_offset = t->opts->partition_offset;
|
||||
ret = joliet_writer_write_dirs(writer);
|
||||
t->eff_partition_offset = 0;
|
||||
if (ret < 0)
|
||||
|
@ -1209,9 +1313,9 @@ int joliet_writer_create(Ecma119Image *target)
|
|||
/* add this writer to image */
|
||||
target->writers[target->nwriters++] = writer;
|
||||
|
||||
if(target->partition_offset > 0) {
|
||||
if(target->opts->partition_offset > 0) {
|
||||
/* Create second tree */
|
||||
target->eff_partition_offset = target->partition_offset;
|
||||
target->eff_partition_offset = target->opts->partition_offset;
|
||||
ret = joliet_tree_create(target);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
|
|
@ -63,5 +63,13 @@ int joliet_writer_create(Ecma119Image *target);
|
|||
*/
|
||||
int joliet_writer_write_vol_desc(IsoImageWriter *writer);
|
||||
|
||||
/**
|
||||
* Determine the Joliet name from node name.
|
||||
* @param flag bit0= Do not issue error messages
|
||||
*/
|
||||
int iso_get_joliet_name(IsoWriteOpts *opts, char *input_charset, int imgid,
|
||||
char *node_name, enum IsoNodeType node_type,
|
||||
size_t *joliet_ucs2_failures,
|
||||
uint16_t **name, int flag);
|
||||
|
||||
#endif /* LIBISO_JOLIET_H */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
/* libiso_msgs (generated from libdax_msgs : Fri Feb 22 19:42:52 CET 2008)
|
||||
Message handling facility of libisofs.
|
||||
Copyright (C) 2006 - 2008 Thomas Schmitt <scdbackup@gmx.net>,
|
||||
Copyright (C) 2006 - 2016 Thomas Schmitt <scdbackup@gmx.net>,
|
||||
provided under GPL version 2 or later
|
||||
*/
|
||||
|
||||
|
@ -33,14 +33,13 @@ static int libiso_msgs_item_new(struct libiso_msgs_item **item,
|
|||
int ret;
|
||||
struct libiso_msgs_item *o;
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
|
||||
(*item)= o=
|
||||
(struct libiso_msgs_item *) malloc(sizeof(struct libiso_msgs_item));
|
||||
if(o==NULL)
|
||||
return(-1);
|
||||
o->timestamp= 0.0;
|
||||
ret= gettimeofday(&tv,&tz);
|
||||
ret= gettimeofday(&tv, NULL);
|
||||
if(ret==0)
|
||||
o->timestamp= tv.tv_sec+0.000001*tv.tv_usec;
|
||||
o->process_id= getpid();
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
|
||||
/* libiso_msgs (generated from libdax_msgs : Fri Feb 22 19:42:52 CET 2008)
|
||||
Message handling facility of libisofs.
|
||||
Copyright (C) 2006-2008 Thomas Schmitt <scdbackup@gmx.net>,
|
||||
provided under GPL version 2 or later
|
||||
Copyright (C) 2006-2016 Thomas Schmitt <scdbackup@gmx.net>,
|
||||
|
||||
This file is part of the libisofs project; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
or later as published by the Free Software Foundation.
|
||||
See COPYING file for details.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
@ -221,7 +226,7 @@ struct libiso_msgs_item;
|
|||
*/
|
||||
#define LIBISO_MSGS_SEV_ABORT 0x71000000
|
||||
|
||||
/** A severity to exclude resp. discard any possible message.
|
||||
/** A severity to exclude or discard any possible message.
|
||||
Do not use this severity for submitting.
|
||||
*/
|
||||
#define LIBISO_MSGS_SEV_NEVER 0x7fffffff
|
||||
|
@ -266,8 +271,9 @@ int libiso_msgs_new(struct libiso_msgs **m, int flag);
|
|||
|
||||
/** Destroy a message handling facility and all its eventual messages.
|
||||
The submitted pointer gets set to NULL.
|
||||
Actually only the last destroy call of all offical references to the object
|
||||
will really dispose it. All others just decrement the reference counter.
|
||||
Actually only the last destroy call of all official references to the
|
||||
object will really dispose it. All others just decrement the reference
|
||||
counter.
|
||||
Call this function only with official reference pointers obtained by
|
||||
libiso_msgs_new() or libiso_msgs_refer(), and only once per such pointer.
|
||||
@param flag Bitfield for control purposes (unused yet, submit 0)
|
||||
|
@ -421,7 +427,7 @@ Range "elmom" : 0x00010000 to 0x0001ffff
|
|||
------------------------------------------------------------------------------
|
||||
Range "scdbackup" : 0x00020000 to 0x0002ffff
|
||||
|
||||
Acessing and defending drives:
|
||||
Accessing and defending drives:
|
||||
|
||||
0x00020001 (SORRY,LOW) = Cannot open busy device
|
||||
0x00020002 (SORRY,HIGH) = Encountered error when closing drive
|
||||
|
@ -510,7 +516,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
|
|||
0x00020148 (SORRY,HIGH) = Cannot write desired amount of data
|
||||
0x00020149 (SORRY,HIGH) = Unsuitable filetype for pseudo-drive
|
||||
0x0002014a (SORRY,HIGH) = Cannot read desired amount of data
|
||||
0x0002014b (SORRY,HIGH) = Drive is already registered resp. scanned
|
||||
0x0002014b (SORRY,HIGH) = Drive is already registered and scanned
|
||||
0x0002014c (FATAL,HIGH) = Emulated drive caught in SCSI function
|
||||
0x0002014d (SORRY,HIGH) = Asynchromous SCSI error
|
||||
0x0002014f (SORRY,HIGH) = Timeout with asynchromous SCSI command
|
||||
|
@ -553,11 +559,11 @@ Range "vreixo" : 0x00030000 to 0x0003ffff
|
|||
0x0003ffbc (FAILURE,HIGH) = Image already bootable
|
||||
0x0003ffbb (FAILURE,HIGH) = Trying to use an invalid file as boot image
|
||||
0x0003ff80 (FAILURE,HIGH) = Error on file operation
|
||||
0x0003ff7f (FAILURE,HIGH) = Trying to open an already openned file
|
||||
0x0003ff7f (FAILURE,HIGH) = Trying to open an already opened file
|
||||
0x0003ff7e (FAILURE,HIGH) = Access to file is not allowed
|
||||
0x0003ff7d (FAILURE,HIGH) = Incorrect path to file
|
||||
0x0003ff7c (FAILURE,HIGH) = The file does not exist in the filesystem
|
||||
0x0003ff7b (FAILURE,HIGH) = Trying to read or close a file not openned
|
||||
0x0003ff7b (FAILURE,HIGH) = Trying to read or close a file not opened
|
||||
0x0003ff7a (FAILURE,HIGH) = Directory used where no dir is expected
|
||||
0x0003ff79 (FAILURE,HIGH) = File read error
|
||||
0x0003ff78 (FAILURE,HIGH) = Not dir used where a dir is expected
|
||||
|
@ -608,7 +614,7 @@ X 0x00030203 (HINT,MEDIUM) = Unsupported El-Torito feature
|
|||
X 0x00030204 (SORRY,HIGH) = Invalid file to be an El-Torito image
|
||||
X 0x00030205 (WARNING,MEDIUM)= Cannot properly patch isolinux image
|
||||
X 0x00030206 (WARNING,MEDIUM)= Copying El-Torito from a previous image without
|
||||
X enought info about it
|
||||
X enough info about it
|
||||
X 0x00030301 (NOTE,MEDIUM) = Unsupported file type for Joliet tree
|
||||
|
||||
|
||||
|
|
2351
libisofs/libisofs.h
2351
libisofs/libisofs.h
File diff suppressed because it is too large
Load Diff
|
@ -5,6 +5,7 @@ aaip_xinfo_func;
|
|||
el_torito_get_bootable;
|
||||
el_torito_get_boot_media_type;
|
||||
el_torito_get_boot_platform_id;
|
||||
el_torito_get_full_load;
|
||||
el_torito_get_id_string;
|
||||
el_torito_get_isolinux_options;
|
||||
el_torito_get_load_seg;
|
||||
|
@ -13,12 +14,16 @@ el_torito_get_selection_crit;
|
|||
el_torito_patch_isolinux_image;
|
||||
el_torito_seems_boot_info_table;
|
||||
el_torito_set_boot_platform_id;
|
||||
el_torito_set_full_load;
|
||||
el_torito_set_id_string;
|
||||
el_torito_set_isolinux_options;
|
||||
el_torito_set_load_seg;
|
||||
el_torito_set_load_size;
|
||||
el_torito_set_no_bootable;
|
||||
el_torito_set_selection_crit;
|
||||
iso_assess_written_features;
|
||||
iso_conv_name_chars;
|
||||
iso_crc32_gpt;
|
||||
iso_data_source_new_from_file;
|
||||
iso_data_source_ref;
|
||||
iso_data_source_unref;
|
||||
|
@ -66,6 +71,7 @@ iso_filesystem_ref;
|
|||
iso_filesystem_unref;
|
||||
iso_finish;
|
||||
iso_fs_global_id;
|
||||
iso_generate_gpt_guid;
|
||||
iso_get_local_charset;
|
||||
iso_get_messenger;
|
||||
iso_gzip_get_refcounts;
|
||||
|
@ -73,8 +79,13 @@ iso_hfsplus_xinfo_func;
|
|||
iso_hfsplus_xinfo_new;
|
||||
iso_image_add_boot_image;
|
||||
iso_image_add_mips_boot_file;
|
||||
iso_image_add_new_dir;
|
||||
iso_image_add_new_file;
|
||||
iso_image_add_new_special;
|
||||
iso_image_add_new_symlink;
|
||||
iso_image_attach_data;
|
||||
iso_image_create_burn_source;
|
||||
iso_image_dir_get_node;
|
||||
iso_image_filesystem_new;
|
||||
iso_image_fs_get_abstract_file_id;
|
||||
iso_image_fs_get_application_id;
|
||||
|
@ -88,6 +99,7 @@ iso_image_fs_get_volume_id;
|
|||
iso_image_generator_is_running;
|
||||
iso_image_get_abstract_file_id;
|
||||
iso_image_get_all_boot_imgs;
|
||||
iso_image_get_alpha_boot;
|
||||
iso_image_get_app_use;
|
||||
iso_image_get_application_id;
|
||||
iso_image_get_attached_data;
|
||||
|
@ -96,6 +108,8 @@ iso_image_get_bootcat;
|
|||
iso_image_get_boot_image;
|
||||
iso_image_get_copyright_file_id;
|
||||
iso_image_get_data_preparer_id;
|
||||
iso_image_get_hppa_palo;
|
||||
iso_image_get_ignore_aclea;
|
||||
iso_image_get_mips_boot_files;
|
||||
iso_image_get_msg_id;
|
||||
iso_image_get_publisher_id;
|
||||
|
@ -105,6 +119,7 @@ iso_image_get_session_md5;
|
|||
iso_image_get_sparc_core;
|
||||
iso_image_get_system_area;
|
||||
iso_image_get_system_id;
|
||||
iso_image_get_truncate_mode;
|
||||
iso_image_get_volset_id;
|
||||
iso_image_get_volume_id;
|
||||
iso_image_give_up_mips_boot;
|
||||
|
@ -112,9 +127,13 @@ iso_image_hfsplus_bless;
|
|||
iso_image_hfsplus_get_blessed;
|
||||
iso_image_import;
|
||||
iso_image_new;
|
||||
iso_image_path_to_node;
|
||||
iso_image_ref;
|
||||
iso_image_remove_boot_image;
|
||||
iso_image_report_el_torito;
|
||||
iso_image_report_system_area;
|
||||
iso_image_set_abstract_file_id;
|
||||
iso_image_set_alpha_boot;
|
||||
iso_image_set_app_use;
|
||||
iso_image_set_application_id;
|
||||
iso_image_set_biblio_file_id;
|
||||
|
@ -123,16 +142,25 @@ iso_image_set_boot_catalog_weight;
|
|||
iso_image_set_boot_image;
|
||||
iso_image_set_copyright_file_id;
|
||||
iso_image_set_data_preparer_id;
|
||||
iso_image_set_hppa_palo;
|
||||
iso_image_set_ignore_aclea;
|
||||
iso_image_set_node_name;
|
||||
iso_image_set_publisher_id;
|
||||
iso_image_set_sparc_core;
|
||||
iso_image_set_system_id;
|
||||
iso_image_set_truncate_mode;
|
||||
iso_image_set_volset_id;
|
||||
iso_image_set_volume_id;
|
||||
iso_image_tree_clone;
|
||||
iso_image_unref;
|
||||
iso_image_update_sizes;
|
||||
iso_image_was_blind_attrs;
|
||||
iso_image_zisofs_discard_bpt;
|
||||
iso_init;
|
||||
iso_init_with_flag;
|
||||
iso_interval_reader_destroy;
|
||||
iso_interval_reader_new;
|
||||
iso_interval_reader_read;
|
||||
iso_lib_is_compatible;
|
||||
iso_lib_version;
|
||||
iso_local_attr_support;
|
||||
|
@ -141,6 +169,7 @@ iso_local_get_attrs;
|
|||
iso_local_get_perms_wo_acl;
|
||||
iso_local_set_acl_text;
|
||||
iso_local_set_attrs;
|
||||
iso_local_set_attrs_errno;
|
||||
iso_md5_clone;
|
||||
iso_md5_compute;
|
||||
iso_md5_end;
|
||||
|
@ -199,21 +228,29 @@ iso_node_unref;
|
|||
iso_node_xinfo_get_cloner;
|
||||
iso_node_xinfo_make_clonable;
|
||||
iso_node_zf_by_magic;
|
||||
iso_nowtime;
|
||||
iso_obtain_msgs;
|
||||
iso_read_image_feature_named;
|
||||
iso_read_image_features_destroy;
|
||||
iso_read_image_features_get_size;
|
||||
iso_read_image_features_has_eltorito;
|
||||
iso_read_image_features_has_iso1999;
|
||||
iso_read_image_features_has_joliet;
|
||||
iso_read_image_features_has_rockridge;
|
||||
iso_read_image_features_rr_loaded;
|
||||
iso_read_image_features_text;
|
||||
iso_read_image_features_tree_loaded;
|
||||
iso_read_opts_auto_input_charset;
|
||||
iso_read_opts_free;
|
||||
iso_read_opts_keep_import_src;
|
||||
iso_read_opts_load_system_area;
|
||||
iso_read_opts_new;
|
||||
iso_read_opts_set_default_gid;
|
||||
iso_read_opts_set_default_permissions;
|
||||
iso_read_opts_set_default_uid;
|
||||
iso_read_opts_set_ecma119_map;
|
||||
iso_read_opts_set_input_charset;
|
||||
iso_read_opts_set_joliet_map;
|
||||
iso_read_opts_set_new_inos;
|
||||
iso_read_opts_set_no_aaip;
|
||||
iso_read_opts_set_no_iso1999;
|
||||
|
@ -236,12 +273,14 @@ iso_stream_get_id;
|
|||
iso_stream_get_input_stream;
|
||||
iso_stream_get_size;
|
||||
iso_stream_get_source_path;
|
||||
iso_stream_get_zisofs_par;
|
||||
iso_stream_is_repeatable;
|
||||
iso_stream_open;
|
||||
iso_stream_read;
|
||||
iso_stream_ref;
|
||||
iso_stream_unref;
|
||||
iso_stream_update_size;
|
||||
iso_stream_zisofs_discard_bpt;
|
||||
iso_symlink_get_dest;
|
||||
iso_symlink_set_dest;
|
||||
iso_text_to_sev;
|
||||
|
@ -268,6 +307,7 @@ iso_tree_set_ignore_hidden;
|
|||
iso_tree_set_ignore_special;
|
||||
iso_tree_set_replace_mode;
|
||||
iso_tree_set_report_callback;
|
||||
iso_truncate_leaf_name;
|
||||
iso_util_decode_md5_tag;
|
||||
iso_write_opts_attach_jte;
|
||||
iso_write_opts_detach_jte;
|
||||
|
@ -284,6 +324,8 @@ iso_write_opts_set_allow_longer_paths;
|
|||
iso_write_opts_set_allow_lowercase;
|
||||
iso_write_opts_set_always_gmt;
|
||||
iso_write_opts_set_appendable;
|
||||
iso_write_opts_set_appended_as_apm;
|
||||
iso_write_opts_set_appended_as_gpt;
|
||||
iso_write_opts_set_default_dir_mode;
|
||||
iso_write_opts_set_default_file_mode;
|
||||
iso_write_opts_set_default_gid;
|
||||
|
@ -294,16 +336,21 @@ iso_write_opts_set_disc_label;
|
|||
iso_write_opts_set_efi_bootp;
|
||||
iso_write_opts_set_fat;
|
||||
iso_write_opts_set_fifo_size;
|
||||
iso_write_opts_set_gpt_guid;
|
||||
iso_write_opts_set_hardlinks;
|
||||
iso_write_opts_set_hfsp_block_size;
|
||||
iso_write_opts_set_hfsp_serial_number;
|
||||
iso_write_opts_set_hfsplus;
|
||||
iso_write_opts_set_iso1999;
|
||||
iso_write_opts_set_iso_level;
|
||||
iso_write_opts_set_iso_mbr_part_type;
|
||||
iso_write_opts_set_iso_type_guid;
|
||||
iso_write_opts_set_joliet;
|
||||
iso_write_opts_set_joliet_long_names;
|
||||
iso_write_opts_set_joliet_longer_paths;
|
||||
iso_write_opts_set_joliet_utf16;
|
||||
iso_write_opts_set_max_37_char_filenames;
|
||||
iso_write_opts_set_max_ce_entries;
|
||||
iso_write_opts_set_ms_block;
|
||||
iso_write_opts_set_no_force_dots;
|
||||
iso_write_opts_set_old_empty;
|
||||
|
@ -311,6 +358,8 @@ iso_write_opts_set_omit_version_numbers;
|
|||
iso_write_opts_set_output_charset;
|
||||
iso_write_opts_set_overwrite_buf;
|
||||
iso_write_opts_set_part_offset;
|
||||
iso_write_opts_set_part_like_isohybrid;
|
||||
iso_write_opts_set_part_type_guid;
|
||||
iso_write_opts_set_partition_img;
|
||||
iso_write_opts_set_prep_img;
|
||||
iso_write_opts_set_pvd_times;
|
||||
|
@ -328,6 +377,7 @@ iso_write_opts_set_system_area;
|
|||
iso_write_opts_set_tail_blocks;
|
||||
iso_write_opts_set_untranslated_name_len;
|
||||
iso_write_opts_set_will_cancel;
|
||||
iso_zisofs_ctrl_susp_z2;
|
||||
iso_zisofs_get_params;
|
||||
iso_zisofs_get_refcounts;
|
||||
iso_zisofs_set_params;
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
/*
|
||||
* Copyright (c) 2002 - 2008 H. Peter Anvin
|
||||
* Copyright (c) 2008 - 2022 Thomas Schmitt
|
||||
* with special credits to Matthew Garrett for isohybrid with GPT and APM
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* or later as published by the Free Software Foundation.
|
||||
* See COPYING file for details.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
|
@ -27,6 +37,8 @@
|
|||
#include "ecma119.h"
|
||||
#include "eltorito.h"
|
||||
#include "system_area.h"
|
||||
#include "image.h"
|
||||
#include "messages.h"
|
||||
|
||||
|
||||
/* This code stems from syslinux-3.72/utils/isohybrid, a perl script
|
||||
|
@ -50,7 +62,7 @@ license from above stem licenses, typically from LGPL.
|
|||
In case its generosity is needed, here is the 2-clause BSD license:
|
||||
|
||||
make_isohybrid_mbr.c is copyright 2002-2008 H. Peter Anvin
|
||||
and 2008-2012 Thomas Schmitt
|
||||
and 2008-2015 Thomas Schmitt
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
@ -146,7 +158,6 @@ int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag)
|
|||
|
||||
/* For generating a weak random number */
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
|
||||
if (bin_lba < 0 || bin_lba >= (1 << 29))
|
||||
return (0); /* 1 TB limit of signed 32 bit addressing of 512 byte blocks */
|
||||
|
@ -201,7 +212,7 @@ int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag)
|
|||
from. An environment variable ?
|
||||
125: Whatever, i use some 32-bit random value with no crypto strength.
|
||||
*/
|
||||
gettimeofday(&tv, &tz);
|
||||
gettimeofday(&tv, NULL);
|
||||
id = 0xffffffff & (tv.tv_sec ^ (tv.tv_usec * 2000));
|
||||
|
||||
/*
|
||||
|
@ -390,12 +401,15 @@ int lba512chs_to_buf(char **wpt, off_t lba, int head_count, int sector_count)
|
|||
|
||||
/* Find out whether GPT and APM are desired
|
||||
flag bit0 = register APM and GPT requests in Ecma119Image
|
||||
bit1 = do not asses and register APM
|
||||
bit2 = do not register overall GPT partition
|
||||
*/
|
||||
int assess_isohybrid_gpt_apm(Ecma119Image *t, int *gpt_count, int gpt_idx[128],
|
||||
int *apm_count, int flag)
|
||||
{
|
||||
int i, ilx_opts, j, ret, num_img;
|
||||
uint32_t block_count;
|
||||
uint64_t start_block;
|
||||
uint8_t gpt_name[72];
|
||||
static uint8_t zero_uuid[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uint8_t basic_data_uuid[16] = {
|
||||
|
@ -406,8 +420,8 @@ int assess_isohybrid_gpt_apm(Ecma119Image *t, int *gpt_count, int gpt_idx[128],
|
|||
0x00, 0x53, 0x46, 0x48, 0x00, 0x00, 0xaa, 0x11,
|
||||
0xaa, 0x11, 0x00, 0x30, 0x65, 0x43, 0xec, 0xac
|
||||
};
|
||||
uint8_t *uuid;
|
||||
static uint64_t gpt_flags = (((uint64_t) 1) << 60) | 1;
|
||||
uint8_t *uuid, *type_guid;
|
||||
uint64_t gpt_flags = (((uint64_t) 1) << 60) | 1;
|
||||
|
||||
*gpt_count = 0;
|
||||
*apm_count = 0;
|
||||
|
@ -418,11 +432,13 @@ int assess_isohybrid_gpt_apm(Ecma119Image *t, int *gpt_count, int gpt_idx[128],
|
|||
num_img = 0;
|
||||
for (i = 0; i < num_img; i++) {
|
||||
ilx_opts = t->catalog->bootimages[i]->isolinux_options;
|
||||
if (((ilx_opts >> 2) & 63) == 1 || ((ilx_opts >> 2) & 63) == 2) {
|
||||
if ((((ilx_opts >> 2) & 63) == 1 || ((ilx_opts >> 2) & 63) == 2) &&
|
||||
!(t->boot_appended_idx[i] >= 0 && t->opts->appended_as_gpt)) {
|
||||
if (*gpt_count < 128)
|
||||
gpt_idx[*gpt_count]= i;
|
||||
gpt_idx[*gpt_count] = i;
|
||||
(*gpt_count)++;
|
||||
if ((flag & 1) && t->bootsrc[i] != NULL) {
|
||||
if ((flag & 1) &&
|
||||
(t->bootsrc[i] != NULL || t->boot_appended_idx[i] >= 0)) {
|
||||
/* Register GPT entry */
|
||||
memset(gpt_name, 0, 72);
|
||||
sprintf((char *) gpt_name, "ISOHybrid%d", *gpt_count);
|
||||
|
@ -431,43 +447,77 @@ int assess_isohybrid_gpt_apm(Ecma119Image *t, int *gpt_count, int gpt_idx[128],
|
|||
uuid = hfs_uuid;
|
||||
else
|
||||
uuid = basic_data_uuid;
|
||||
block_count = 0;
|
||||
for (j = 0; j < t->bootsrc[i]->nsections; j++)
|
||||
block_count += t->bootsrc[i]->sections[j].size / 2048;
|
||||
if (t->boot_appended_idx[i] >= 0) {
|
||||
block_count = t->appended_part_size[
|
||||
t->boot_appended_idx[i]];
|
||||
start_block = ((uint64_t) t->appended_part_start[
|
||||
t->boot_appended_idx[i]]) * 4;
|
||||
} else {
|
||||
block_count = 0;
|
||||
for (j = 0; j < t->bootsrc[i]->nsections; j++)
|
||||
block_count += t->bootsrc[i]->sections[j].size / 2048;
|
||||
start_block = ((uint64_t) t->bootsrc[i]->sections[0].block)
|
||||
* 4;
|
||||
}
|
||||
ret = iso_quick_gpt_entry(
|
||||
t, t->bootsrc[i]->sections[0].block,
|
||||
block_count, uuid, zero_uuid, gpt_flags,
|
||||
(uint8_t *) gpt_name);
|
||||
t->gpt_req, &(t->gpt_req_count),
|
||||
start_block, ((uint64_t) block_count) * 4,
|
||||
uuid, zero_uuid, gpt_flags, (uint8_t *) gpt_name);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (ilx_opts & 256) {
|
||||
if ((ilx_opts & 256) && !(flag & 2)) {
|
||||
(*apm_count)++;
|
||||
if ((flag & 1) && t->bootsrc[i] != NULL) {
|
||||
if ((flag & 1) &&
|
||||
(t->bootsrc[i] != NULL || t->boot_appended_idx[i] >= 0)) {
|
||||
/* Register APM entry */
|
||||
block_count = 0;
|
||||
for (j = 0; j < t->bootsrc[i]->nsections; j++)
|
||||
block_count += t->bootsrc[i]->sections[j].size / 2048;
|
||||
ret = iso_quick_apm_entry(t, t->bootsrc[i]->sections[0].block,
|
||||
if (t->boot_appended_idx[i] >= 0) {
|
||||
block_count = t->appended_part_size[
|
||||
t->boot_appended_idx[i]];
|
||||
start_block = t->appended_part_start[
|
||||
t->boot_appended_idx[i]];
|
||||
} else {
|
||||
block_count = 0;
|
||||
for (j = 0; j < t->bootsrc[i]->nsections; j++)
|
||||
block_count += t->bootsrc[i]->sections[j].size / 2048;
|
||||
start_block = t->bootsrc[i]->sections[0].block;
|
||||
}
|
||||
ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count),
|
||||
(uint32_t) start_block,
|
||||
block_count, "EFI", "Apple_HFS");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* Prevent gap filling */
|
||||
t->apm_req_flags |= 2;
|
||||
t->apm_block_size = 2048;
|
||||
t->opts->apm_block_size = 2048;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((flag & 1) && *gpt_count > 0) {
|
||||
if (*gpt_count > 0 && !(flag & 4)) {
|
||||
(*gpt_count)++;
|
||||
if (*gpt_count < 128)
|
||||
gpt_idx[*gpt_count] = -1;
|
||||
}
|
||||
if ((flag & 1) && *gpt_count > 0 && !(flag & 4)) {
|
||||
/* Register overall GPT partition */
|
||||
memset(gpt_name, 0, 72);
|
||||
sprintf((char *) gpt_name, "ISOHybrid");
|
||||
iso_ascii_utf_16le(gpt_name);
|
||||
if (t->opts->iso_gpt_flag & 1)
|
||||
type_guid = t->opts->iso_gpt_type_guid;
|
||||
else
|
||||
type_guid = basic_data_uuid;
|
||||
if (t->system_area_options & (1 << 16))
|
||||
gpt_flags|= 4; /* Legacy BIOS bootable */
|
||||
if (t->opts->system_area_options & (1 << 17))
|
||||
gpt_flags &= ~(((uint64_t) 1) << 60); /* Not read-only */
|
||||
/* Let it be open ended. iso_write_gpt() will truncate it as needed. */
|
||||
block_count = 0xffffffff;
|
||||
ret = iso_quick_gpt_entry(t, (uint32_t) 0, block_count,
|
||||
basic_data_uuid, zero_uuid, gpt_flags,
|
||||
ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
|
||||
(uint64_t) t->opts->partition_offset * 4,
|
||||
((uint64_t) block_count) * 4,
|
||||
type_guid, zero_uuid, gpt_flags,
|
||||
(uint8_t *) gpt_name);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -522,19 +572,28 @@ static int insert_apm_head(uint8_t *buf, int apm_count)
|
|||
static int gpt_images_as_mbr_partitions(Ecma119Image *t, char *wpt,
|
||||
int gpt_idx[128], int *gpt_cursor)
|
||||
{
|
||||
int ilx_opts;
|
||||
int ilx_opts, skip = 0;
|
||||
off_t hd_blocks;
|
||||
static uint8_t dummy_chs[3] = {
|
||||
0xfe, 0xff, 0xff,
|
||||
};
|
||||
|
||||
if (gpt_idx[*gpt_cursor] < 0)
|
||||
skip = 1;
|
||||
else if (t->bootsrc[gpt_idx[*gpt_cursor]] == NULL)
|
||||
skip = 1;
|
||||
if (skip) {
|
||||
(*gpt_cursor)++;
|
||||
return 2;
|
||||
}
|
||||
|
||||
wpt[0] = 0;
|
||||
memcpy(wpt + 1, dummy_chs, 3);
|
||||
ilx_opts = t->catalog->bootimages[gpt_idx[*gpt_cursor]]->isolinux_options;
|
||||
if (((ilx_opts >> 2) & 63) == 2)
|
||||
wpt[4] = 0x00; /* HFS gets marked as "Empty" */
|
||||
else
|
||||
((unsigned char *) wpt)[4] = 0xef; /* "EFI (FAT-12/16/" */
|
||||
((unsigned char *) wpt)[4] = 0xef; /* "EFI (FAT-12/16)" */
|
||||
|
||||
memcpy(wpt + 5, dummy_chs, 3);
|
||||
|
||||
|
@ -553,27 +612,62 @@ static int gpt_images_as_mbr_partitions(Ecma119Image *t, char *wpt,
|
|||
}
|
||||
|
||||
|
||||
/* For generating a weak random number */
|
||||
static uint32_t iso_make_mbr_id(Ecma119Image *t, int flag)
|
||||
{
|
||||
uint32_t id;
|
||||
struct timeval tv;
|
||||
|
||||
if(t->opts->vol_uuid[0]) {
|
||||
id = iso_crc32_gpt((unsigned char *) t->opts->vol_uuid, 16, 0);
|
||||
} else if(t->opts->vol_modification_time > 0) {
|
||||
id = iso_crc32_gpt((unsigned char *) &(t->opts->vol_modification_time),
|
||||
sizeof(time_t), 0);
|
||||
} else {
|
||||
gettimeofday(&tv, NULL);
|
||||
id = 0xffffffff & (tv.tv_sec ^ (tv.tv_usec * 2000));
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @param flag bit0= make own random MBR Id from current time
|
||||
* or from overridden modification time
|
||||
* bit1= create protective MBR as of UEFI/GPT specs
|
||||
* bit2= write only partition table
|
||||
* do not insert APM mockup head
|
||||
* do not treat bytes before code as isohybrid MBR
|
||||
* do not create MBR id
|
||||
* bit3= replace fs_type 0x00 by 0x17 if appropriate
|
||||
*/
|
||||
int make_isolinux_mbr(int32_t *img_blocks, Ecma119Image *t,
|
||||
int make_isolinux_mbr(uint32_t *img_blocks, Ecma119Image *t,
|
||||
int part_offset, int part_number, int fs_type,
|
||||
uint8_t *buf, int flag)
|
||||
{
|
||||
uint32_t id, part, nominal_part_size;
|
||||
uint32_t id, part, nominal_part_size, mbr_part_start;
|
||||
off_t hd_img_blocks, hd_boot_lba;
|
||||
char *wpt;
|
||||
uint32_t boot_lba, mbr_id;
|
||||
int head_count, sector_count, ret;
|
||||
int gpt_count = 0, gpt_idx[128], apm_count = 0, gpt_cursor;
|
||||
/* For generating a weak random number */
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
char *wpt, *fs_type_wpt = NULL;
|
||||
uint32_t boot_lba;
|
||||
int head_count, sector_count, ret, part_is_in_img = 0;
|
||||
int gpt_count = 0, gpt_idx[128], apm_count = 0, gpt_cursor, i;
|
||||
|
||||
hd_img_blocks = ((off_t) *img_blocks) * (off_t) 4;
|
||||
if (t->bootsrc[0] == NULL)
|
||||
return iso_msg_submit(t->image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
|
||||
"Cannot refer by isohybrid MBR to data outside of ISO 9660 filesystem.");
|
||||
|
||||
for (i = 0; i < 128; i++)
|
||||
gpt_idx[i] = -1;
|
||||
|
||||
if (flag & 2) {
|
||||
part_number = 1;
|
||||
part_offset = 1;
|
||||
}
|
||||
|
||||
hd_img_blocks = ((off_t) *img_blocks) * (off_t) 4 -
|
||||
t->post_iso_part_pad / 512;
|
||||
|
||||
boot_lba = t->bootsrc[0]->sections[0].block;
|
||||
mbr_id = 0;
|
||||
head_count = t->partition_heads_per_cyl;
|
||||
sector_count = t->partition_secs_per_head;
|
||||
|
||||
|
@ -581,46 +675,52 @@ int make_isolinux_mbr(int32_t *img_blocks, Ecma119Image *t,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* The rest of APM has already been written by iso_write_apm().
|
||||
But the isohybrid APM head differs from the hfsplus_writer APM head.
|
||||
*/
|
||||
ret = insert_apm_head(buf, apm_count);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if(flag & 4) {
|
||||
wpt= (char *) buf + 446;
|
||||
} else {
|
||||
|
||||
/* Padding of image_size to a multiple of sector_count*head_count
|
||||
happens already at compute time and is implemented by
|
||||
an appropriate increase of Ecma119Image->tail_blocks.
|
||||
*/
|
||||
/* The rest of APM has already been written by iso_write_apm().
|
||||
But the isohybrid APM head differs from the hfsplus_writer APM head.
|
||||
*/
|
||||
ret = insert_apm_head(buf, apm_count);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
wpt = (char *) buf + 432;
|
||||
/* Padding of image_size to a multiple of sector_count*head_count
|
||||
happens already at compute time and is implemented by
|
||||
an appropriate increase of Ecma119Image->tail_blocks.
|
||||
*/
|
||||
|
||||
/* write qword boot_lba # Offset 432
|
||||
*/
|
||||
hd_boot_lba = ((off_t) boot_lba) * (off_t) 4;
|
||||
lsb_to_buf(&wpt, hd_boot_lba & 0xffffffff, 32, 0);
|
||||
lsb_to_buf(&wpt, hd_boot_lba >> 32, 32, 0);
|
||||
wpt = (char *) buf + 432;
|
||||
|
||||
/* write dword mbr_id # Offset 440
|
||||
(here some 32-bit random value with no crypto strength)
|
||||
*/
|
||||
if (flag & 1) {
|
||||
gettimeofday(&tv, &tz);
|
||||
id = 0xffffffff & (tv.tv_sec ^ (tv.tv_usec * 2000));
|
||||
lsb_to_buf(&wpt, id, 32, 0);
|
||||
/* write qword boot_lba # Offset 432
|
||||
*/
|
||||
hd_boot_lba = ((off_t) boot_lba) * (off_t) 4;
|
||||
lsb_to_buf(&wpt, hd_boot_lba & 0xffffffff, 32, 0);
|
||||
lsb_to_buf(&wpt, hd_boot_lba >> 32, 32, 0);
|
||||
|
||||
/* write dword mbr_id # Offset 440
|
||||
(here some 32-bit random value with no crypto strength)
|
||||
*/
|
||||
if (flag & 1) {
|
||||
id = iso_make_mbr_id(t, 0);
|
||||
lsb_to_buf(&wpt, id, 32, 0);
|
||||
} else {
|
||||
wpt+= 4;
|
||||
}
|
||||
|
||||
/* write word 0 # Offset 444
|
||||
*/
|
||||
lsb_to_buf(&wpt, 0, 16, 0);
|
||||
}
|
||||
|
||||
/* write word 0 # Offset 444
|
||||
*/
|
||||
lsb_to_buf(&wpt, 0, 16, 0);
|
||||
|
||||
/* # Offset 446
|
||||
*/
|
||||
gpt_cursor= 0;
|
||||
for (part = 1 ; part <= 4; part++) {
|
||||
if ((int) part != part_number) {
|
||||
/* if this_partition != partition_number: write 16 zero bytes
|
||||
(this is now overriden by the eventual desire to announce
|
||||
(this is now overridden by the eventual desire to announce
|
||||
EFI and HFS boot images.)
|
||||
*/
|
||||
memset(wpt, 0, 16);
|
||||
|
@ -631,18 +731,29 @@ int make_isolinux_mbr(int32_t *img_blocks, Ecma119Image *t,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Will this hit the part_number partition ? */
|
||||
mbr_part_start = iso_read_lsb((uint8_t *) (wpt + 8), 4);
|
||||
if (mbr_part_start > 0 &&
|
||||
mbr_part_start < hd_img_blocks + part_offset)
|
||||
part_is_in_img = 1;
|
||||
|
||||
wpt+= 16;
|
||||
continue;
|
||||
}
|
||||
/* write byte 0x80
|
||||
/* write byte 0x80 if bootable
|
||||
write LBA_to_CHS(partition_offset)
|
||||
write byte filesystem_type
|
||||
write LBA_to_CHS(image_size-1)
|
||||
write dword partition_offset
|
||||
write dword image_size
|
||||
*/
|
||||
lsb_to_buf(&wpt, 0x80, 8, 0);
|
||||
if (flag & 2)
|
||||
lsb_to_buf(&wpt, 0x00, 8, 0);
|
||||
else
|
||||
lsb_to_buf(&wpt, 0x80, 8, 0);
|
||||
lba512chs_to_buf(&wpt, part_offset, head_count, sector_count);
|
||||
fs_type_wpt = wpt;
|
||||
lsb_to_buf(&wpt, fs_type, 8, 0);
|
||||
lba512chs_to_buf(&wpt, hd_img_blocks - 1, head_count, sector_count);
|
||||
lsb_to_buf(&wpt, part_offset, 32, 0);
|
||||
|
@ -657,6 +768,17 @@ int make_isolinux_mbr(int32_t *img_blocks, Ecma119Image *t,
|
|||
*/
|
||||
lsb_to_buf(&wpt, 0xaa55, 16, 0);
|
||||
|
||||
/* Check whether automatically determined fs_type 0x00 can become 0x17 */
|
||||
if ((flag & 8) && fs_type_wpt != NULL && fs_type == 0x00 &&
|
||||
t->opts->iso_mbr_part_type != fs_type && !part_is_in_img) {
|
||||
if (t->opts->iso_mbr_part_type >= 0 &&
|
||||
t->opts->iso_mbr_part_type <= 255) {
|
||||
lsb_to_buf(&fs_type_wpt, t->opts->iso_mbr_part_type, 8, 0);
|
||||
} else {
|
||||
lsb_to_buf(&fs_type_wpt, 0x17, 8, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
|
|
@ -497,7 +497,7 @@ int checksum_copy_old_nodes(Ecma119Image *target, IsoNode *node, int flag)
|
|||
|
||||
if (node->type == LIBISO_FILE) {
|
||||
file = (IsoFile *) node;
|
||||
if (file->from_old_session && target->appendable) {
|
||||
if (file->from_old_session && target->opts->appendable) {
|
||||
/* Look for checksums at various places */
|
||||
|
||||
/* Try checksum directly stored with node */
|
||||
|
@ -527,7 +527,7 @@ int checksum_copy_old_nodes(Ecma119Image *target, IsoNode *node, int flag)
|
|||
if (md5_pt == NULL)
|
||||
return 0;
|
||||
|
||||
if (!target->will_cancel) {
|
||||
if (!target->opts->will_cancel) {
|
||||
ret = iso_node_lookup_attr(node, "isofs.cx", &value_length,
|
||||
&value, 0);
|
||||
if (ret == 1 && value_length == 4) {
|
||||
|
@ -540,13 +540,12 @@ int checksum_copy_old_nodes(Ecma119Image *target, IsoNode *node, int flag)
|
|||
if (value != NULL)
|
||||
free(value);
|
||||
|
||||
/* ts B30114 : It is unclear why these are removed here.
|
||||
At least with the opts->will_cancel runs,
|
||||
this is not appropriate.
|
||||
/* >>> ts B30114 : It is unclear why these are removed here.
|
||||
At least with the opts->will_cancel runs,
|
||||
this is not appropriate.
|
||||
*/
|
||||
iso_node_remove_xinfo(node, checksum_md5_xinfo_func);
|
||||
}
|
||||
iso_node_remove_xinfo(node, checksum_cx_xinfo_func);
|
||||
}
|
||||
} else if (node->type == LIBISO_DIR) {
|
||||
for (pos = ((IsoDir *) node)->children; pos != NULL; pos = pos->next) {
|
||||
|
@ -572,8 +571,8 @@ int checksum_writer_compute_data_blocks(IsoImageWriter *writer)
|
|||
t = writer->target;
|
||||
|
||||
t->checksum_array_pos = t->curblock;
|
||||
/* (t->curblock already contains t->ms_block) */
|
||||
t->checksum_range_start = t->ms_block;
|
||||
/* (t->curblock already contains t->opts->ms_block) */
|
||||
t->checksum_range_start = t->opts->ms_block;
|
||||
size = (t->checksum_idx_counter + 2) / 128;
|
||||
if (size * 128 < t->checksum_idx_counter + 2)
|
||||
size++;
|
||||
|
@ -713,7 +712,7 @@ int checksum_writer_create(Ecma119Image *target)
|
|||
/* add this writer to image */
|
||||
target->writers[target->nwriters++] = writer;
|
||||
/* Account for superblock checksum tag */
|
||||
if (target->md5_session_checksum) {
|
||||
if (target->opts->md5_session_checksum) {
|
||||
target->checksum_sb_tag_pos = target->curblock;
|
||||
target->curblock++;
|
||||
}
|
||||
|
@ -743,7 +742,7 @@ int iso_md5_write_scdbackup_tag(Ecma119Image *t, char *tag_block, int flag)
|
|||
(unsigned int) (pos % 1000000000));
|
||||
else
|
||||
sprintf(postext, "%u", (unsigned int) pos);
|
||||
sprintf(record, "%s %s ", t->scdbackup_tag_parm, postext);
|
||||
sprintf(record, "%s %s ", t->opts->scdbackup_tag_parm, postext);
|
||||
record_len = strlen(record);
|
||||
for (i = 0; i < 16; i++)
|
||||
sprintf(record + record_len + 2 * i,
|
||||
|
@ -765,8 +764,8 @@ int iso_md5_write_scdbackup_tag(Ecma119Image *t, char *tag_block, int flag)
|
|||
block_len+= 32;
|
||||
tag_block[block_len++]= '\n';
|
||||
|
||||
if (t->scdbackup_tag_written != NULL)
|
||||
strncpy(t->scdbackup_tag_written, tag_block + line_start,
|
||||
if (t->opts->scdbackup_tag_written != NULL)
|
||||
strncpy(t->opts->scdbackup_tag_written, tag_block + line_start,
|
||||
block_len - line_start);
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
|
@ -782,7 +781,7 @@ ex:;
|
|||
* 1= session tag (End checksumming.)
|
||||
* 2= superblock tag (System Area and Volume Descriptors)
|
||||
* 3= tree tag (ECMA-119 and Rock Ridge tree)
|
||||
* 4= relocated superblock tag (at LBA 0 of overwriteable media)
|
||||
* 4= relocated superblock tag (at LBA 0 of overwritable media)
|
||||
* Write to target->opts_overwrite rather than to iso_write().
|
||||
*/
|
||||
int iso_md5_write_tag(Ecma119Image *t, int flag)
|
||||
|
@ -828,7 +827,7 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
|
|||
} else if (mode == 3) {
|
||||
sprintf(tag_block + l, " next=%u", t->checksum_tag_pos);
|
||||
} else if (mode == 4) {
|
||||
sprintf(tag_block + l, " session_start=%u", t->ms_block);
|
||||
sprintf(tag_block + l, " session_start=%u", t->opts->ms_block);
|
||||
}
|
||||
strcat(tag_block + l, " md5=");
|
||||
l = strlen(tag_block);
|
||||
|
@ -849,8 +848,8 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
|
|||
}
|
||||
tag_block[l + 32] = '\n';
|
||||
|
||||
if (mode == 1 && t->scdbackup_tag_parm[0]) {
|
||||
if (t->ms_block > 0) {
|
||||
if (mode == 1 && t->opts->scdbackup_tag_parm[0]) {
|
||||
if (t->opts->ms_block > 0) {
|
||||
iso_msg_submit(t->image->id, ISO_SCDBACKUP_TAG_NOT_0, 0, NULL);
|
||||
} else {
|
||||
ret = iso_md5_write_scdbackup_tag(t, tag_block, 0);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 - 2011 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2023 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -38,6 +38,7 @@
|
|||
|
||||
#include "util.h"
|
||||
#include "node.h"
|
||||
#include "stream.h"
|
||||
|
||||
|
||||
/*
|
||||
|
@ -156,10 +157,10 @@ int iso_init_with_flag(int flag)
|
|||
#ifdef Libisofs_with_libjtE
|
||||
|
||||
/* Ugly compile time check for header version compatibility.
|
||||
If everthing matches, then it produces no C code. In case of mismatch,
|
||||
If everything matches, then it produces no C code. In case of mismatch,
|
||||
intentionally faulty C code will be inserted.
|
||||
*/
|
||||
/* The indendation is an advise of man gcc to help old compilers ignoring */
|
||||
/* The indentation is an advise of man gcc to help old compilers ignoring */
|
||||
#if iso_libjte_req_major > LIBJTE_VERSION_MAJOR
|
||||
#define Libisofs_libjte_dot_h_too_olD 1
|
||||
#endif
|
||||
|
@ -232,6 +233,7 @@ void iso_finish()
|
|||
{
|
||||
libiso_msgs_destroy(&libiso_msgr, 0);
|
||||
iso_node_xinfo_dispose_cloners(0);
|
||||
iso_stream_destroy_cmpranks(0);
|
||||
}
|
||||
|
||||
int iso_set_abort_severity(char *severity)
|
||||
|
@ -378,7 +380,7 @@ const char *iso_error_to_msg(int errcode)
|
|||
case ISO_DATA_SOURCE_MISHAP:
|
||||
case ISO_DATA_SOURCE_FAILURE:
|
||||
case ISO_DATA_SOURCE_FATAL:
|
||||
return "Read error occured with IsoDataSource";
|
||||
return "Read error occurred with IsoDataSource";
|
||||
case ISO_AAIP_IGNORED:
|
||||
return "AAIP info with ACL or xattr in ISO image will be ignored";
|
||||
case ISO_AAIP_BAD_ACL:
|
||||
|
@ -390,8 +392,10 @@ const char *iso_error_to_msg(int errcode)
|
|||
case ISO_AAIP_BAD_AASTRING:
|
||||
return "Error with decoding AAIP info for ACL or xattr";
|
||||
case ISO_AAIP_NO_GET_LOCAL:
|
||||
case ISO_AAIP_NO_GET_LOCAL_S:
|
||||
return "Error with reading ACL or xattr from local file";
|
||||
case ISO_AAIP_NO_SET_LOCAL:
|
||||
case ISO_AAIP_NO_SET_LOCAL_S:
|
||||
return "Error with attaching ACL or xattr to local file";
|
||||
case ISO_AAIP_NON_USER_NAME:
|
||||
return "Unallowed attempt to set an xattr with non-userspace name";
|
||||
|
@ -400,13 +404,13 @@ const char *iso_error_to_msg(int errcode)
|
|||
case ISO_ZLIB_NOT_ENABLED:
|
||||
return "Use of zlib was not enabled at compile time";
|
||||
case ISO_ZISOFS_TOO_LARGE:
|
||||
return "Cannot apply zisofs filter to file >= 4 GiB";
|
||||
return "File too large. Cannot apply zisofs filter.";
|
||||
case ISO_FILTER_WRONG_INPUT:
|
||||
return "Filter input differs from previous run";
|
||||
case ISO_ZLIB_COMPR_ERR:
|
||||
return "zlib compression/decompression error";
|
||||
case ISO_ZISOFS_WRONG_INPUT:
|
||||
return "Input stream is not in zisofs format";
|
||||
return "Input stream is not in a supported zisofs format";
|
||||
case ISO_ZISOFS_PARAM_LOCK:
|
||||
return "Cannot set global zisofs parameters while filters exist";
|
||||
case ISO_ZLIB_EARLY_EOF:
|
||||
|
@ -503,6 +507,72 @@ const char *iso_error_to_msg(int errcode)
|
|||
return "Too many chained symbolic links";
|
||||
case ISO_BAD_ISO_FILETYPE:
|
||||
return "Unrecognized file type in ISO image";
|
||||
case ISO_NAME_NOT_UCS2:
|
||||
return "Filename not suitable for character set UCS-2";
|
||||
case ISO_IMPORT_COLLISION:
|
||||
return "File name collision during ISO image import";
|
||||
case ISO_HPPA_PALO_INCOMPL:
|
||||
return "Incomplete HP-PA PALO boot parameters";
|
||||
case ISO_HPPA_PALO_OFLOW:
|
||||
return "HP-PA PALO boot address exceeds 2 GB";
|
||||
case ISO_HPPA_PALO_NOTREG:
|
||||
return "HP-PA PALO file is not a data file";
|
||||
case ISO_HPPA_PALO_CMDLEN:
|
||||
return "HP-PA PALO command line too long";
|
||||
case ISO_SYSAREA_PROBLEMS:
|
||||
return "Problems encountered during inspection of System Area";
|
||||
case ISO_INQ_SYSAREA_PROP:
|
||||
return "Unrecognized inquiry for system area property";
|
||||
case ISO_ALPHA_BOOT_NOTREG:
|
||||
return "DEC Alpha Boot Loader file is not a data file";
|
||||
case ISO_NO_KEPT_DATA_SRC:
|
||||
return "No data source of imported ISO image available";
|
||||
case ISO_MALFORMED_READ_INTVL:
|
||||
return "Malformed description string for interval reader";
|
||||
case ISO_INTVL_READ_PROBLEM:
|
||||
return "Unreadable file, premature EOF, or failure to seek for interval reader";
|
||||
case ISO_NOT_REPRODUCIBLE:
|
||||
return "Cannot arrange content of data files in surely reproducible way";
|
||||
case ISO_PATCH_FILTERED_BOOT:
|
||||
return "May not write boot info into filtered stream of boot image";
|
||||
case ISO_PATCH_OVERSIZED_BOOT:
|
||||
return "Boot image to large to buffer for writing boot info";
|
||||
case ISO_RR_NAME_TRUNCATED:
|
||||
return "File name had to be truncated and MD5 marked";
|
||||
case ISO_TRUNCATE_ISOFSNT:
|
||||
return "File name truncation length changed by loaded image info";
|
||||
case ISO_GENERAL_NOTE:
|
||||
return "A general note message was issued";
|
||||
case ISO_BAD_FSRC_FILETYPE:
|
||||
return "Unrecognized file type of IsoFileSrc object";
|
||||
case ISO_GPT_NO_VOL_UUID:
|
||||
return "Cannot derive GPT GUID from undefined pseudo-UUID volume timestamp";
|
||||
case ISO_BAD_GPT_GUID_MODE:
|
||||
return "Unrecognized GPT disk GUID setup mode";
|
||||
case ISO_NO_ROOT_DIR:
|
||||
return "Unable to obtain root directory";
|
||||
case ISO_SUSP_WRONG_CE_SIZE:
|
||||
return "Zero sized, oversized, or mislocated SUSP CE area found";
|
||||
case ISO_MULTI_OVER_IMPORTED:
|
||||
return "Multi-session would overwrite imported_iso interval";
|
||||
case ISO_ELTO_EFI_HIDDEN:
|
||||
return "El-Torito EFI image is hidden";
|
||||
case ISO_HFSPLUS_TOO_MANY_FILES:
|
||||
return "Too many files in HFS+ directory tree";
|
||||
case ISO_ZISOFS_TOO_MANY_PTR:
|
||||
return "Too many zisofs block pointers needed overall";
|
||||
case ISO_ZISOFS_BPT_UNDERRUN:
|
||||
return "Prevented zisofs block pointer counter underrun";
|
||||
case ISO_ZISOFS_UNKNOWN_SIZE:
|
||||
return "Cannot obtain size of zisofs compressed stream";
|
||||
case ISO_UNDEF_READ_FEATURE:
|
||||
return "Undefined IsoReadImageFeatures name";
|
||||
case ISO_TOO_MANY_CE:
|
||||
return "Too many CE entries for single file";
|
||||
case ISO_TOO_MANY_CE_FOR_LINUX:
|
||||
return "Too many CE entries for single file when mounted by Linux";
|
||||
case ISO_CE_REMOVING_ATTR:
|
||||
return "Too many CE entries for single file, removing attributes";
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
|
@ -531,7 +601,8 @@ int iso_msg_submit(int imgid, int errcode, int causedby, const char *fmt, ...)
|
|||
vsnprintf(msg, MAX_MSG_LEN, fmt, ap);
|
||||
va_end(ap);
|
||||
} else {
|
||||
strncpy(msg, iso_error_to_msg(errcode), MAX_MSG_LEN);
|
||||
strncpy(msg, iso_error_to_msg(errcode), MAX_MSG_LEN - 1);
|
||||
msg[MAX_MSG_LEN - 1] = 0;
|
||||
}
|
||||
|
||||
libiso_msgs_submit(libiso_msgr, imgid, ISO_ERR_CODE(errcode),
|
||||
|
|
378
libisofs/node.c
378
libisofs/node.c
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 - 2011 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2023 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -35,7 +35,7 @@ struct dir_iter_data
|
|||
IsoNode *pos;
|
||||
|
||||
/* Some control flags.
|
||||
* bit 0 -> 1 if next called, 0 reseted at start or on deletion
|
||||
* bit 0 -> 1 if next called, 0 reset at start or on deletion
|
||||
*/
|
||||
int flag;
|
||||
};
|
||||
|
@ -49,7 +49,7 @@ void iso_node_ref(IsoNode *node)
|
|||
}
|
||||
|
||||
/**
|
||||
* Decrements the reference couting of the given node.
|
||||
* Decrements the reference counting of the given node.
|
||||
* If it reach 0, the node is free, and, if the node is a directory,
|
||||
* its children will be unref() too.
|
||||
*/
|
||||
|
@ -327,32 +327,50 @@ enum IsoNodeType iso_node_get_type(IsoNode *node)
|
|||
* Set the name of a node.
|
||||
*
|
||||
* @param name The name in UTF-8 encoding
|
||||
* @param truncate_length (<64 = return on oversized name )
|
||||
* @param flag bit0= issue warning in case of truncation
|
||||
*/
|
||||
int iso_node_set_name(IsoNode *node, const char *name)
|
||||
int iso_node_set_name_trunc(IsoNode *node, const char *in_name,
|
||||
int truncate_length, int flag)
|
||||
{
|
||||
char *new;
|
||||
char *new, *name, *trunc = NULL;
|
||||
int ret;
|
||||
|
||||
if ((IsoNode*)node->parent == node) {
|
||||
/* you can't change name of the root node */
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
ret = ISO_WRONG_ARG_VALUE;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
name = (char *) in_name;
|
||||
if (truncate_length >= 64) {
|
||||
trunc = strdup(name);
|
||||
if (trunc == 0) {
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
goto ex;
|
||||
}
|
||||
ret = iso_truncate_rr_name(1, truncate_length, trunc, !(flag & 1));
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
name = trunc;
|
||||
}
|
||||
/* check if the name is valid */
|
||||
ret = iso_node_is_valid_name(name);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto ex;
|
||||
|
||||
if (node->parent != NULL) {
|
||||
/* check if parent already has a node with same name */
|
||||
if (iso_dir_get_node(node->parent, name, NULL) == 1) {
|
||||
return ISO_NODE_NAME_NOT_UNIQUE;
|
||||
ret = ISO_NODE_NAME_NOT_UNIQUE;
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
|
||||
new = strdup(name);
|
||||
if (new == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
goto ex;
|
||||
}
|
||||
free(node->name);
|
||||
node->name = new;
|
||||
|
@ -364,10 +382,29 @@ int iso_node_set_name(IsoNode *node, const char *name)
|
|||
iso_node_take(node);
|
||||
res = iso_dir_add_node(parent, node, 0);
|
||||
if (res < 0) {
|
||||
return res;
|
||||
ret = res;
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
return ISO_SUCCESS;
|
||||
ret = ISO_SUCCESS;
|
||||
ex:
|
||||
if (trunc != NULL)
|
||||
free(trunc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iso_node_set_name(IsoNode *node, const char *name)
|
||||
{
|
||||
return iso_node_set_name_trunc(node, name, 0, 0);
|
||||
}
|
||||
|
||||
int iso_image_set_node_name(IsoImage *image, IsoNode *node, const char *name,
|
||||
int flag)
|
||||
{
|
||||
if (image->truncate_mode == 0)
|
||||
if ((int) strlen(name) > image->truncate_length)
|
||||
return ISO_RR_NAME_TOO_LONG;
|
||||
return iso_node_set_name_trunc(node, name, image->truncate_length, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -377,6 +414,10 @@ int iso_node_set_name(IsoNode *node, const char *name)
|
|||
*/
|
||||
const char *iso_node_get_name(const IsoNode *node)
|
||||
{
|
||||
static char *root = {""};
|
||||
|
||||
if (node->name == NULL)
|
||||
return root;
|
||||
return node->name;
|
||||
}
|
||||
|
||||
|
@ -545,7 +586,7 @@ int iso_node_get_hidden(IsoNode *node)
|
|||
* if the dir already contains a node with the same name, whether to
|
||||
* replace or not the old node with this.
|
||||
* @return
|
||||
* number of nodes in dir if succes, < 0 otherwise
|
||||
* number of nodes in dir if success, < 0 otherwise
|
||||
*/
|
||||
int iso_dir_add_node(IsoDir *dir, IsoNode *child,
|
||||
enum iso_replace_mode replace)
|
||||
|
@ -610,6 +651,43 @@ int iso_dir_get_node(IsoDir *dir, const char *name, IsoNode **node)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int iso_dir_get_node_trunc(IsoDir *dir, int truncate_length,
|
||||
const char *name, IsoNode **node)
|
||||
{
|
||||
int ret;
|
||||
char *trunc = NULL;
|
||||
|
||||
if ((int) strlen(name) <= truncate_length) {
|
||||
ret = iso_dir_get_node(dir, name, node);
|
||||
return ret;
|
||||
}
|
||||
trunc = strdup(name);
|
||||
if (trunc == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
ret = iso_truncate_rr_name(1, truncate_length, trunc, 1);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
ret = iso_dir_get_node(dir, trunc, node);
|
||||
if (ret == 0)
|
||||
ret = 2;
|
||||
ex:;
|
||||
LIBISO_FREE_MEM(trunc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* API */
|
||||
int iso_image_dir_get_node(IsoImage *image, IsoDir *dir,
|
||||
const char *name, IsoNode **node, int flag)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (image->truncate_mode == 0 || (flag & 1))
|
||||
ret = iso_dir_get_node(dir, name, node);
|
||||
else
|
||||
ret = iso_dir_get_node_trunc(dir, image->truncate_length, name, node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of children of a directory.
|
||||
*
|
||||
|
@ -1036,7 +1114,7 @@ int iso_symlink_set_dest(IsoSymlink *link, const char *dest)
|
|||
* or regular files, this function has no effect.
|
||||
* @param w
|
||||
* The weight as a integer number, the greater this value is, the
|
||||
* closer from the begining of image the file will be written.
|
||||
* closer from the beginning of image the file will be written.
|
||||
*/
|
||||
void iso_node_set_sort_weight(IsoNode *node, int w)
|
||||
{
|
||||
|
@ -1048,6 +1126,7 @@ void iso_node_set_sort_weight(IsoNode *node, int w)
|
|||
}
|
||||
} else if (node->type == LIBISO_FILE) {
|
||||
((IsoFile*)node)->sort_weight = w;
|
||||
((IsoFile*)node)->explicit_weight = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1116,25 +1195,25 @@ int iso_file_get_old_image_lba(IsoFile *file, uint32_t *lba, int flag)
|
|||
{
|
||||
int ret;
|
||||
int section_count;
|
||||
struct iso_file_section *sections;
|
||||
struct iso_file_section *sections = NULL;
|
||||
|
||||
if (file == NULL || lba == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
ret = iso_file_get_old_image_sections(file, §ion_count, §ions, flag);
|
||||
if (ret <= 0) {
|
||||
ret = iso_file_get_old_image_sections(file, §ion_count, §ions, 0);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
}
|
||||
if (section_count != 1) {
|
||||
free(sections);
|
||||
if (sections != NULL)
|
||||
free(sections);
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
*lba = sections[0].block;
|
||||
free(sections);
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Like iso_file_get_old_image_lba(), but take an IsoNode.
|
||||
*
|
||||
|
@ -1172,20 +1251,27 @@ int iso_node_is_valid_name(const char *name)
|
|||
|
||||
/* guard against the empty string or big names... */
|
||||
if (name[0] == '\0')
|
||||
return ISO_RR_NAME_RESERVED;
|
||||
goto rr_reserved;
|
||||
if (strlen(name) > LIBISOFS_NODE_NAME_MAX)
|
||||
return ISO_RR_NAME_TOO_LONG;
|
||||
|
||||
/* ...against "." and ".." names... */
|
||||
if (!strcmp(name, ".") || !strcmp(name, "..")) {
|
||||
return ISO_RR_NAME_RESERVED;
|
||||
}
|
||||
if (!strcmp(name, ".") || !strcmp(name, ".."))
|
||||
goto rr_reserved;
|
||||
|
||||
/* ...and against names with '/' */
|
||||
if (strchr(name, '/') != NULL) {
|
||||
return ISO_RR_NAME_RESERVED;
|
||||
}
|
||||
if (strchr(name, '/') != NULL)
|
||||
goto rr_reserved;
|
||||
|
||||
return 1;
|
||||
|
||||
rr_reserved:;
|
||||
/* # define Libisofs_debug_rr_reserveD */
|
||||
#ifdef Libisofs_debug_rr_reserveD
|
||||
fprintf(stderr, "libisofs_DEBUG: ISO_RR_NAME_RESERVED with '%s'\n", name);
|
||||
#endif
|
||||
|
||||
return ISO_RR_NAME_RESERVED;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1205,8 +1291,12 @@ int iso_node_is_valid_link_dest(const char *dest)
|
|||
}
|
||||
|
||||
/* guard against the empty string or big dest... */
|
||||
if (dest[0] == '\0')
|
||||
if (dest[0] == '\0') {
|
||||
#ifdef Libisofs_debug_rr_reserveD
|
||||
fprintf(stderr, "libisofs_DEBUG: ISO_RR_NAME_RESERVED by empty link target\n");
|
||||
#endif
|
||||
return ISO_RR_NAME_RESERVED;
|
||||
}
|
||||
if (strlen(dest) > LIBISOFS_NODE_PATH_MAX)
|
||||
return ISO_RR_PATH_TOO_LONG;
|
||||
|
||||
|
@ -1275,7 +1365,11 @@ int iso_dir_insert(IsoDir *dir, IsoNode *node, IsoNode **pos,
|
|||
/* old file is newer */
|
||||
return ISO_NODE_NAME_NOT_UNIQUE;
|
||||
}
|
||||
/* fall down */
|
||||
if ((node->mode & S_IFMT) != ((*pos)->mode & S_IFMT)) {
|
||||
/* different file types */
|
||||
return ISO_NODE_NAME_NOT_UNIQUE;
|
||||
}
|
||||
break;
|
||||
case ISO_REPLACE_IF_SAME_TYPE:
|
||||
if ((node->mode & S_IFMT) != ((*pos)->mode & S_IFMT)) {
|
||||
/* different file types */
|
||||
|
@ -1366,6 +1460,7 @@ void iso_notify_dir_iters(IsoNode *node, int flag)
|
|||
int iso_node_new_root(IsoDir **root)
|
||||
{
|
||||
IsoDir *dir;
|
||||
time_t now;
|
||||
|
||||
dir = calloc(1, sizeof(IsoDir));
|
||||
if (dir == NULL) {
|
||||
|
@ -1373,7 +1468,8 @@ int iso_node_new_root(IsoDir **root)
|
|||
}
|
||||
dir->node.refcount = 1;
|
||||
dir->node.type = LIBISO_DIR;
|
||||
dir->node.atime = dir->node.ctime = dir->node.mtime = time(NULL);
|
||||
iso_nowtime(&now, 0);
|
||||
dir->node.atime = dir->node.ctime = dir->node.mtime = now;
|
||||
dir->node.mode = S_IFDIR | 0555;
|
||||
|
||||
/* set parent to itself, to prevent root to be added to another dir */
|
||||
|
@ -1430,6 +1526,8 @@ int iso_node_new_file(char *name, IsoStream *stream, IsoFile **file)
|
|||
new->node.type = LIBISO_FILE;
|
||||
new->node.name = name;
|
||||
new->node.mode = S_IFREG;
|
||||
new->from_old_session = 0;
|
||||
new->explicit_weight = 0;
|
||||
new->sort_weight = 0;
|
||||
new->stream = stream;
|
||||
|
||||
|
@ -1517,11 +1615,17 @@ int attrs_cleanout_name(char *del_name, size_t *num_attrs, char **names,
|
|||
size_t i, w;
|
||||
|
||||
for (w = i = 0; i < *num_attrs; i++) {
|
||||
if ((strcmp(names[i], del_name) == 0) ^ (flag & 1))
|
||||
continue;
|
||||
if ((strcmp(names[i], del_name) == 0) ^ (flag & 1)) {
|
||||
if (names[i] != NULL)
|
||||
free(names[i]);
|
||||
if (values[i] != NULL)
|
||||
free(values[i]);
|
||||
names[i] = values[i] = NULL;
|
||||
continue;
|
||||
}
|
||||
if (w == i) {
|
||||
w++;
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
names[w] = names[i];
|
||||
value_lengths[w] = value_lengths[i];
|
||||
|
@ -1720,12 +1824,13 @@ int attr_enlarge_list(char ***names, size_t **value_lengths, char ***values,
|
|||
|
||||
/* Merge attribute list of node and given new attribute list into
|
||||
attribute list returned by m_* parameters.
|
||||
The m_* paramters have finally to be freed by a call with bit15 set.
|
||||
The m_* parameters have finally to be freed by a call with bit15 set.
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= delete all old names which begin by "user."
|
||||
(but not if bit2 is set)
|
||||
bit2= delete the given names rather than overwrite
|
||||
their content
|
||||
bit3= with bit0: delete all old non-"isofs." names
|
||||
bit4= do not overwrite value of empty name
|
||||
bit5= do not overwrite isofs attributes
|
||||
bit15= release memory and return 1
|
||||
|
@ -1751,9 +1856,11 @@ int iso_node_merge_xattr(IsoNode *node, size_t num_attrs, char **names,
|
|||
return ret;
|
||||
|
||||
if ((flag & 1) && (!(flag & 4))) {
|
||||
/* Delete unmatched user space pairs */
|
||||
/* Delete unmatched settable pairs */
|
||||
for (j = 0; j < *m_num_attrs; j++) {
|
||||
if (strncmp((*m_names)[j], "user.", 5) != 0)
|
||||
if (strncmp((*m_names)[j], "isofs.", 6) == 0)
|
||||
continue;
|
||||
if (strncmp((*m_names)[j], "user.", 5) != 0 && !(flag & 8))
|
||||
continue;
|
||||
for (i = 0; i < num_attrs; i++) {
|
||||
if (names[i] == NULL || (*m_names)[j] == NULL)
|
||||
|
@ -1867,8 +1974,9 @@ int iso_node_set_attrs(IsoNode *node, size_t num_attrs, char **names,
|
|||
size_t *value_lengths, char **values, int flag)
|
||||
{
|
||||
int ret, acl_saved = 0;
|
||||
size_t sret, result_len, m_num = 0, *m_value_lengths = NULL, i;
|
||||
unsigned char *result;
|
||||
ssize_t sret;
|
||||
size_t result_len, m_num = 0, *m_value_lengths = NULL, i;
|
||||
unsigned char *result = NULL;
|
||||
char *a_acl = NULL, *d_acl = NULL, **m_names = NULL, **m_values = NULL;
|
||||
|
||||
if (!(flag & 8))
|
||||
|
@ -1881,7 +1989,7 @@ int iso_node_set_attrs(IsoNode *node, size_t num_attrs, char **names,
|
|||
node, num_attrs, names, value_lengths, values,
|
||||
&m_num, &m_names, &m_value_lengths, &m_values,
|
||||
(flag & 4) | (!(flag & 2)) | ((!(flag & 1)) << 4) |
|
||||
((flag & 16) << 1));
|
||||
((flag & 16) << 1) | (flag & 8));
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
num_attrs = m_num;
|
||||
|
@ -1907,38 +2015,91 @@ int iso_node_set_attrs(IsoNode *node, size_t num_attrs, char **names,
|
|||
}
|
||||
sret = aaip_encode(num_attrs, names, value_lengths, values,
|
||||
&result_len, &result, 0);
|
||||
if (sret == 0) {
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
if (sret < 0) {
|
||||
ret = sret;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
ret = iso_node_remove_xinfo(node, aaip_xinfo_func);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
ret = iso_node_add_xinfo(node, aaip_xinfo_func, result);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
if (ret == 0) {
|
||||
|
||||
/* >>> something is messed up with xinfo: an aa_string still exists */;
|
||||
|
||||
ret = ISO_ERROR;
|
||||
if (ret < 0) {
|
||||
if (result != NULL)
|
||||
free(result);
|
||||
goto ex;
|
||||
}
|
||||
if (acl_saved) {
|
||||
ret = iso_node_set_acl_text(node, a_acl, d_acl, 0);
|
||||
if (sret > 0) {
|
||||
ret = iso_node_add_xinfo(node, aaip_xinfo_func, result);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
if (ret == 0) {
|
||||
|
||||
/* >>> something is messed up with xinfo:
|
||||
an aa_string still exists */;
|
||||
|
||||
ret = ISO_ERROR;
|
||||
goto ex;
|
||||
}
|
||||
if (acl_saved) {
|
||||
ret = iso_node_set_acl_text(node, a_acl, d_acl, 0);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
ex:;
|
||||
/* Dispose eventual merged list */
|
||||
/* Dispose merged list if it was created */
|
||||
iso_node_merge_xattr(node, num_attrs, names, value_lengths, values,
|
||||
&m_num, &m_names, &m_value_lengths, &m_values, 1 << 15);
|
||||
/* Dispose ACL if saved */
|
||||
iso_node_get_acl_text(node, &a_acl, &d_acl, 1 << 15);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* @param flag
|
||||
bit0= delete ACL, too
|
||||
*/
|
||||
int iso_node_remove_fattr(IsoNode *node, int flag)
|
||||
{
|
||||
int ret;
|
||||
size_t num_attrs, *value_lengths = NULL, i, w;
|
||||
char **names = NULL, **values = NULL;
|
||||
|
||||
ret = iso_node_get_attrs(node, &num_attrs, &names, &value_lengths, &values,
|
||||
flag & 1);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
|
||||
/* Delete variables of all namespaces except isofs */
|
||||
w = 0;
|
||||
for (i = 0; i < num_attrs; i++) {
|
||||
if (strncmp(names[i], "isofs.", 6) != 0) {
|
||||
free(names[i]);
|
||||
names[i] = NULL;
|
||||
free(values[i]);
|
||||
values[i] = NULL;
|
||||
continue;
|
||||
}
|
||||
if (w != i) {
|
||||
/* move i to w , nullify i */
|
||||
names[w] = names[i];
|
||||
names[i] = NULL;
|
||||
values[w] = values[i];
|
||||
values[i] = NULL;
|
||||
value_lengths[w] = value_lengths[i];
|
||||
}
|
||||
w++;
|
||||
}
|
||||
num_attrs = w;
|
||||
ret = iso_node_set_attrs(node, num_attrs, names, value_lengths, values,
|
||||
(flag & 1) | 8);
|
||||
ex:;
|
||||
if (names != NULL)
|
||||
iso_node_get_attrs(NULL, &num_attrs, &names, &value_lengths, &values,
|
||||
1 << 15);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int iso_decode_acl(unsigned char *v_data, size_t v_len, size_t *consumed,
|
||||
char **text, size_t *text_fill, int flag)
|
||||
|
@ -2146,15 +2307,15 @@ int iso_node_set_acl_text(IsoNode *node, char *access_text, char *default_text,
|
|||
ret = ISO_AAIP_BAD_ACL_TEXT;
|
||||
goto ex;
|
||||
}
|
||||
ret = 1;
|
||||
if (a_text != NULL || d_text != NULL)
|
||||
ret = aaip_encode_both_acl(a_text, d_text, st_mode,
|
||||
&acl_len, &acl, 2 | 8);
|
||||
ret = aaip_encode_both_acl(a_text, d_text, st_mode,
|
||||
&acl_len, &acl,
|
||||
2 | 8 | ((flag & 4) << 2));
|
||||
} else {
|
||||
ret = 1;
|
||||
if (access_text != NULL || default_text != NULL)
|
||||
ret = aaip_encode_both_acl(access_text, default_text, st_mode,
|
||||
&acl_len, &acl, 2 | 8);
|
||||
&acl_len, &acl,
|
||||
2 | 8 | ((flag & 4) << 2));
|
||||
}
|
||||
if (ret == -1)
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
|
@ -2213,7 +2374,8 @@ int iso_node_set_acl_text(IsoNode *node, char *access_text, char *default_text,
|
|||
goto ex;
|
||||
}
|
||||
ret = aaip_encode_both_acl(access_text, default_text,
|
||||
st_mode, &acl_len, &acl, 2 | 8);
|
||||
st_mode, &acl_len, &acl,
|
||||
2 | 8 | ((flag & 4) << 2));
|
||||
if (ret < -3)
|
||||
goto ex;
|
||||
if (ret <= 0) {
|
||||
|
@ -2325,22 +2487,25 @@ int zisofs_zf_xinfo_cloner(void *old_data, void **new_data, int flag)
|
|||
* bit1= permission to overwrite existing zisofs_zf_info
|
||||
* bit2= if no zisofs header is found:
|
||||
* create xinfo with parameters which indicate no zisofs
|
||||
* bit8-bit15= maximum zisofs version to be recognized (0 means 1)
|
||||
* @return 1= zf xinfo added, 0= no zisofs data found ,
|
||||
* 2= found existing zf xinfo and flag bit1 was not set
|
||||
* <0 means error
|
||||
*/
|
||||
int iso_file_zf_by_magic(IsoFile *file, int flag)
|
||||
{
|
||||
int ret, stream_type, header_size_div4, block_size_log2;
|
||||
uint32_t uncompressed_size;
|
||||
int ret, stream_type, header_size_div4, block_size_log2, version;
|
||||
uint64_t uncompressed_size;
|
||||
IsoStream *stream, *input_stream;
|
||||
struct zisofs_zf_info *zf = NULL;
|
||||
void *xipt;
|
||||
uint8_t algo[2];
|
||||
|
||||
/* Intimate friendship with this function in filters/zisofs.c */
|
||||
int ziso_is_zisofs_stream(IsoStream *stream, int *stream_type,
|
||||
uint8_t zisofs_algo[2],
|
||||
int *header_size_div4, int *block_size_log2,
|
||||
uint32_t *uncompressed_size, int flag);
|
||||
uint64_t *uncompressed_size, int flag);
|
||||
|
||||
ret = iso_node_get_xinfo((IsoNode *) file, zisofs_zf_xinfo_func, &xipt);
|
||||
if (ret == 1) {
|
||||
|
@ -2357,13 +2522,18 @@ int iso_file_zf_by_magic(IsoFile *file, int flag)
|
|||
break;
|
||||
stream = input_stream;
|
||||
}
|
||||
ret = ziso_is_zisofs_stream(stream, &stream_type, &header_size_div4,
|
||||
version = ((flag >> 8) & 0xff);
|
||||
algo[0] = algo[1] = 0;
|
||||
ret = ziso_is_zisofs_stream(stream, &stream_type, algo, &header_size_div4,
|
||||
&block_size_log2, &uncompressed_size, 3);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (version < 2 && ret > 0 && (algo[0] != 'p' || algo[1] != 'z'))
|
||||
ret = 0;
|
||||
if (ret != 1 || stream_type != 2) {
|
||||
if (flag & 4)
|
||||
if (!(flag & 4))
|
||||
return 0;
|
||||
algo[0] = algo[1] = 0;
|
||||
header_size_div4 = 0;
|
||||
block_size_log2 = 0;
|
||||
uncompressed_size = 0;
|
||||
|
@ -2371,6 +2541,8 @@ int iso_file_zf_by_magic(IsoFile *file, int flag)
|
|||
zf = calloc(1, sizeof(struct zisofs_zf_info));
|
||||
if (zf == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
zf->zisofs_algo[0] = algo[0];
|
||||
zf->zisofs_algo[1] = algo[1];
|
||||
zf->uncompressed_size = uncompressed_size;
|
||||
zf->header_size_div4 = header_size_div4;
|
||||
zf->block_size_log2 = block_size_log2;
|
||||
|
@ -2388,7 +2560,7 @@ int iso_node_zf_by_magic(IsoNode *node, int flag)
|
|||
IsoDir *dir;
|
||||
|
||||
if (node->type == LIBISO_FILE)
|
||||
return iso_file_zf_by_magic((IsoFile *) node, flag);
|
||||
return iso_file_zf_by_magic((IsoFile *) node, flag & 0xff06);
|
||||
if (node->type != LIBISO_DIR || (flag & 8))
|
||||
return 0;
|
||||
|
||||
|
@ -2409,7 +2581,7 @@ int iso_node_zf_by_magic(IsoNode *node, int flag)
|
|||
return 0; /* Will not be zisofs format */
|
||||
}
|
||||
}
|
||||
hflag = flag & ~6;
|
||||
hflag = flag & 0xff06;
|
||||
if ((flag & 1) && file->from_old_session)
|
||||
hflag |= 1;
|
||||
ret = iso_file_zf_by_magic(file, hflag);
|
||||
|
@ -2566,6 +2738,7 @@ int iso_node_set_ino(IsoNode *node, ino_t ino, int flag)
|
|||
ret = iso_stream_set_image_ino(file->stream, ino, 0);
|
||||
if (ret < 0 || ret == 1)
|
||||
return ret;
|
||||
/* ret == 0 means that the stream is not from loaded ISO image */
|
||||
|
||||
} else if (node->type == LIBISO_SYMLINK) {
|
||||
symlink = (IsoSymlink *) node;
|
||||
|
@ -2630,7 +2803,7 @@ int iso_node_cmp_flag(IsoNode *n1, IsoNode *n2, int flag)
|
|||
if (n1->type != n2->type)
|
||||
return (n1->type < n2->type ? -1 : 1);
|
||||
|
||||
/* Imported or explicite ISO image node id has priority */
|
||||
/* Imported or explicit ISO image node id has priority */
|
||||
ret1 = (iso_node_get_id(n1, &fs_id1, &dev_id1, &ino_id1, 1) > 0);
|
||||
ret2 = (iso_node_get_id(n2, &fs_id2, &dev_id2, &ino_id2, 1) > 0);
|
||||
if (ret1 != ret2)
|
||||
|
@ -2756,6 +2929,8 @@ int iso_node_cmp_ino(IsoNode *n1, IsoNode *n2, int flag)
|
|||
}
|
||||
|
||||
|
||||
/* @param flag bit0= delete isofs.cx rather than setting it
|
||||
*/
|
||||
int iso_file_set_isofscx(IsoFile *file, unsigned int checksum_index,
|
||||
int flag)
|
||||
{
|
||||
|
@ -2765,9 +2940,14 @@ int iso_file_set_isofscx(IsoFile *file, unsigned int checksum_index,
|
|||
char *valuept;
|
||||
int i, ret;
|
||||
|
||||
valuept= (char *) value;
|
||||
if (flag & 1) {
|
||||
ret = iso_node_set_attrs((IsoNode *) file, (size_t) 1,
|
||||
&names, value_lengths, &valuept, 4 | 8);
|
||||
return ret;
|
||||
}
|
||||
for(i = 0; i < 4; i++)
|
||||
value[3 - i] = (checksum_index >> (8 * i)) & 0xff;
|
||||
valuept= (char *) value;
|
||||
ret = iso_node_set_attrs((IsoNode *) file, (size_t) 1,
|
||||
&names, value_lengths, &valuept, 2 | 8);
|
||||
return ret;
|
||||
|
@ -2846,6 +3026,50 @@ ex:;
|
|||
}
|
||||
|
||||
|
||||
int iso_root_set_isofsnt(IsoNode *node, uint32_t truncate_mode,
|
||||
uint32_t truncate_length, int flag)
|
||||
{
|
||||
char buffer[5 + 5], *wpt = buffer, *valuept = buffer;
|
||||
int result_len, ret;
|
||||
static char *names = "isofs.nt";
|
||||
static size_t value_lengths[1];
|
||||
|
||||
iso_util_encode_len_bytes(truncate_mode, wpt, 0, &result_len, 0);
|
||||
wpt += result_len;
|
||||
iso_util_encode_len_bytes(truncate_length, wpt, 0, &result_len, 0);
|
||||
wpt += result_len;
|
||||
value_lengths[0] = wpt - buffer;
|
||||
ret = iso_node_set_attrs(node, (size_t) 1,
|
||||
&names, value_lengths, &valuept, 2 | 8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int iso_root_get_isofsnt(IsoNode *node, uint32_t *truncate_mode,
|
||||
uint32_t *truncate_length, int flag)
|
||||
{
|
||||
int ret, len;
|
||||
size_t value_len;
|
||||
char *value = NULL, *rpt;
|
||||
|
||||
ret = iso_node_lookup_attr(node, "isofs.nt", &value_len, &value, 0);
|
||||
if (ret <= 0)
|
||||
goto ex;
|
||||
|
||||
rpt = value;
|
||||
iso_util_decode_len_bytes(truncate_mode, rpt, &len,
|
||||
value_len - (rpt - value), 0);
|
||||
rpt += len + 1;
|
||||
iso_util_decode_len_bytes(truncate_length, rpt, &len,
|
||||
value_len - (rpt - value), 0);
|
||||
ret= ISO_SUCCESS;
|
||||
ex:;
|
||||
if (value != NULL)
|
||||
free(value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag)
|
||||
{
|
||||
|
@ -2899,21 +3123,23 @@ int iso_file_make_md5(IsoFile *file, int flag)
|
|||
|
||||
if (file->from_old_session)
|
||||
dig = 1;
|
||||
md5= calloc(16, 1);
|
||||
md5 = calloc(16, 1);
|
||||
if (md5 == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
ret = iso_stream_make_md5(file->stream, md5, dig);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
if (ret < 0) {
|
||||
free(md5);
|
||||
return ret;
|
||||
}
|
||||
iso_node_remove_xinfo((IsoNode *) file, checksum_md5_xinfo_func);
|
||||
ret = iso_node_add_xinfo((IsoNode *) file, checksum_md5_xinfo_func, md5);
|
||||
if (ret == 0)
|
||||
ret = ISO_ERROR; /* should not happen after iso_node_remove_xinfo() */
|
||||
if (ret < 0) {
|
||||
free(md5);
|
||||
goto ex;
|
||||
return ret;
|
||||
}
|
||||
ret = 1;
|
||||
ex:;
|
||||
return ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 - 2011 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2023 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -149,8 +149,15 @@ struct Iso_File
|
|||
{
|
||||
IsoNode node;
|
||||
|
||||
/* 1 = The node was loaded from an existing ISO image and still refers
|
||||
to its data content there.
|
||||
*/
|
||||
unsigned int from_old_session : 1;
|
||||
|
||||
/* 1 = The node got attributed a weight by iso_node_set_sort_weight().
|
||||
*/
|
||||
unsigned int explicit_weight : 1;
|
||||
|
||||
/**
|
||||
* It sorts the order in which the file data is written to the CD image.
|
||||
* Higher weighting files are written at the beginning of image
|
||||
|
@ -277,7 +284,7 @@ int iso_node_new_symlink(char *name, char *dest, IsoSymlink **link);
|
|||
* Create a new special file node. As far as libisofs concerns,
|
||||
* an special file is a block device, a character device, a FIFO (named pipe)
|
||||
* or a socket. You can choose the specific kind of file you want to add
|
||||
* by setting mode propertly (see man 2 stat).
|
||||
* by setting mode properly (see man 2 stat).
|
||||
*
|
||||
* Note that special files are only written to image when Rock Ridge
|
||||
* extensions are enabled. Moreover, a special file is just a directory entry
|
||||
|
@ -415,6 +422,12 @@ int iso_aa_get_attrs(unsigned char *aa_string, size_t *num_attrs,
|
|||
int iso_aa_lookup_attr(unsigned char *aa_string, char *name,
|
||||
size_t *value_length, char **value, int flag);
|
||||
|
||||
/**
|
||||
* Delete variables of all namespaces except isofs
|
||||
*
|
||||
* @param flag bit0= delete ACL, too
|
||||
*/
|
||||
int iso_node_remove_fattr(IsoNode *node, int flag);
|
||||
|
||||
/**
|
||||
* Function to identify and manage ZF parameters which do not stem from ZF
|
||||
|
@ -430,9 +443,10 @@ int zisofs_zf_xinfo_func(void *data, int flag);
|
|||
* Parameter structure which is to be managed by zisofs_zf_xinfo_func.
|
||||
*/
|
||||
struct zisofs_zf_info {
|
||||
uint32_t uncompressed_size;
|
||||
uint64_t uncompressed_size;
|
||||
uint8_t header_size_div4;
|
||||
uint8_t block_size_log2;
|
||||
uint8_t zisofs_algo[2];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -480,7 +494,7 @@ int iso_node_cmp_flag(IsoNode *n1, IsoNode *n2, int flag);
|
|||
|
||||
|
||||
/**
|
||||
* Set the checksum index (typically comming from IsoFileSrc.checksum_index)
|
||||
* Set the checksum index (typically coming from IsoFileSrc.checksum_index)
|
||||
* of a regular file node. The index is encoded as xattr "isofs.cx" with
|
||||
* four bytes of value.
|
||||
*/
|
||||
|
@ -505,6 +519,16 @@ int iso_root_get_isofsca(IsoNode *node, uint32_t *start_lba, uint32_t *end_lba,
|
|||
int flag);
|
||||
|
||||
|
||||
/**
|
||||
* Record and get truncation parameters as of iso_image_set_truncate_mode() by
|
||||
* "isofs.nt".
|
||||
*/
|
||||
int iso_root_set_isofsnt(IsoNode *node, uint32_t truncate_mode,
|
||||
uint32_t truncate_length, int flag);
|
||||
int iso_root_get_isofsnt(IsoNode *node, uint32_t *truncate_mode,
|
||||
uint32_t *truncate_length, int flag);
|
||||
|
||||
|
||||
/**
|
||||
* Copy the xinfo list from one node to the another.
|
||||
*/
|
||||
|
@ -536,4 +560,10 @@ int zisofs_zf_xinfo_func(void *data, int flag);
|
|||
int zisofs_zf_xinfo_cloner(void *old_data, void **new_data, int flag);
|
||||
|
||||
|
||||
/* Performing search for possibly truncated node name.
|
||||
*/
|
||||
int iso_dir_get_node_trunc(IsoDir *dir, int truncate_length,
|
||||
const char *name, IsoNode **node);
|
||||
|
||||
|
||||
#endif /*LIBISO_NODE_H_*/
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2007 Mario Danic
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2023 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -41,6 +41,9 @@
|
|||
|
||||
#include "ecma119.h"
|
||||
|
||||
/* For ssize_t */
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#define SUSP_SIG(entry, a, b) ((entry->sig[0] == a) && (entry->sig[1] == b))
|
||||
|
||||
|
@ -63,10 +66,22 @@ struct susp_info
|
|||
uint32_t ce_block;
|
||||
uint32_t ce_len;
|
||||
|
||||
/* Storage for Continuation Area for a whole directory */
|
||||
size_t n_ce_susp_fields;
|
||||
uint8_t **ce_susp_fields;
|
||||
|
||||
/* The number of allocated members in ce_susp_fields */
|
||||
size_t alloc_ce_susp_fields;
|
||||
|
||||
/* Marks the start index in ce_susp_fields of the current node */
|
||||
size_t current_ce_start;
|
||||
|
||||
};
|
||||
|
||||
/* Step to increase allocated size of susp_info.ce_susp_fields */
|
||||
#define ISO_SUSP_CE_ALLOC_STEP 16
|
||||
|
||||
|
||||
/* SUSP 5.1 */
|
||||
struct susp_CE {
|
||||
uint8_t block[8];
|
||||
|
@ -186,11 +201,13 @@ struct susp_sys_user_entry
|
|||
* Available space in the System Use Area for the directory record.
|
||||
* @param ce
|
||||
* Will be filled with the space needed in a CE
|
||||
* @param base_ce
|
||||
* Fill of continuation area by previous nodes of same dir
|
||||
* @return
|
||||
* The size needed for the RR entries in the System Use Area
|
||||
*/
|
||||
size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t space,
|
||||
size_t *ce);
|
||||
ssize_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t space,
|
||||
size_t *ce, size_t base_ce);
|
||||
|
||||
/**
|
||||
* Fill a struct susp_info with the RR/SUSP entries needed for a given
|
||||
|
@ -205,7 +222,7 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t space,
|
|||
* Pointer to the struct susp_info where the entries will be stored.
|
||||
* If some entries need to go to a Continuation Area, they will be added
|
||||
* to the existing ce_susp_fields, and ce_len will be incremented
|
||||
* propertly. Please ensure ce_block is initialized propertly.
|
||||
* properly. Please ensure ce_block is initialized properly.
|
||||
* @return
|
||||
* 1 success, < 0 error
|
||||
*/
|
||||
|
@ -217,7 +234,7 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
|
|||
* fields are not written.
|
||||
* If info does not contain any SUSP entry this function just return.
|
||||
* After written, the info susp_fields array will be freed, and the counters
|
||||
* updated propertly.
|
||||
* updated properly.
|
||||
*/
|
||||
void rrip_write_susp_fields(Ecma119Image *t, struct susp_info *info,
|
||||
uint8_t *buf);
|
||||
|
@ -240,7 +257,7 @@ typedef struct susp_iterator SuspIterator;
|
|||
|
||||
SuspIterator *
|
||||
susp_iter_new(IsoDataSource *src, struct ecma119_dir_record *record,
|
||||
uint8_t len_skp, int msgid);
|
||||
uint32_t fs_blocks, uint8_t len_skp, int msgid);
|
||||
|
||||
/**
|
||||
* Get the next SUSP System User Entry using given iterator.
|
||||
|
@ -252,7 +269,8 @@ susp_iter_new(IsoDataSource *src, struct ecma119_dir_record *record,
|
|||
* @return
|
||||
* 1 on success, 0 if no more entries, < 0 error
|
||||
*/
|
||||
int susp_iter_next(SuspIterator *iter, struct susp_sys_user_entry **sue);
|
||||
int susp_iter_next(SuspIterator *iter, struct susp_sys_user_entry **sue,
|
||||
int flag);
|
||||
|
||||
/**
|
||||
* Free a given susp iterator.
|
||||
|
@ -344,6 +362,14 @@ int read_aaip_AL(struct susp_sys_user_entry *sue,
|
|||
*/
|
||||
int read_zisofs_ZF(struct susp_sys_user_entry *zf, uint8_t algorithm[2],
|
||||
uint8_t *header_size_div4, uint8_t *block_size_log2,
|
||||
uint32_t *uncompressed_size, int flag);
|
||||
uint64_t *uncompressed_size, int flag);
|
||||
|
||||
/**
|
||||
* Convert a RR filename to the requested charset.
|
||||
* @param flag bit0= do not issue error messages
|
||||
*/
|
||||
int iso_get_rr_name(IsoWriteOpts *opts, char *input_charset,
|
||||
char *output_charset, int imgid,
|
||||
char *str, char **name, int flag);
|
||||
|
||||
#endif /* LIBISO_ROCKRIDGE_H */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2023 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -35,6 +35,12 @@ struct susp_iterator
|
|||
IsoDataSource *src;
|
||||
int msgid;
|
||||
|
||||
/* Number of blocks in the ISO 9660 filesystem */
|
||||
uint32_t fs_blocks;
|
||||
|
||||
/* For detecting (nearly) endless loops */
|
||||
uint32_t ce_counter;
|
||||
|
||||
/* block and offset for next continuation area */
|
||||
uint32_t ce_block;
|
||||
uint32_t ce_off;
|
||||
|
@ -47,7 +53,7 @@ struct susp_iterator
|
|||
|
||||
SuspIterator*
|
||||
susp_iter_new(IsoDataSource *src, struct ecma119_dir_record *record,
|
||||
uint8_t len_skp, int msgid)
|
||||
uint32_t fs_blocks, uint8_t len_skp, int msgid)
|
||||
{
|
||||
int pad = (record->len_fi[0] + 1) % 2;
|
||||
struct susp_iterator *iter = malloc(sizeof(struct susp_iterator));
|
||||
|
@ -60,19 +66,48 @@ susp_iter_new(IsoDataSource *src, struct ecma119_dir_record *record,
|
|||
iter->size = record->len_dr[0] - record->len_fi[0] - 33 - pad;
|
||||
iter->src = src;
|
||||
iter->msgid = msgid;
|
||||
iter->fs_blocks = fs_blocks;
|
||||
|
||||
iter->ce_counter = 0;
|
||||
iter->ce_len = 0;
|
||||
iter->ce_block = 0;
|
||||
iter->ce_off = 0;
|
||||
iter->buffer = NULL;
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
int susp_iter_next(SuspIterator *iter, struct susp_sys_user_entry **sue)
|
||||
/* More than 1 MiB in a single file's CE area is suspicious */
|
||||
#define ISO_SUSP_MAX_CE_BYTES (1024 * 1024)
|
||||
|
||||
/* More than 100000 CE entries in a file is suspicious */
|
||||
#define ISO_SUSP_MAX_CE_HOPS 100000
|
||||
|
||||
|
||||
/* @param flag bit0 = First call on root:
|
||||
Not yet clear whether this is SUSP at all
|
||||
*/
|
||||
int susp_iter_next(SuspIterator *iter, struct susp_sys_user_entry **sue,
|
||||
int flag)
|
||||
{
|
||||
struct susp_sys_user_entry *entry;
|
||||
|
||||
process_entry:;
|
||||
entry = (struct susp_sys_user_entry*)(iter->base + iter->pos);
|
||||
|
||||
if (flag & 1) {
|
||||
/* Yet unclear whether it is SUSP at all */
|
||||
if (iter->size < 7)
|
||||
return 0;
|
||||
if (!SUSP_SIG(entry, 'S', 'P'))
|
||||
return 0;
|
||||
if (entry->len_sue[0] < 7)
|
||||
return 0;
|
||||
/* Looks like SUSP enough to pass the further processing here. */
|
||||
|
||||
/* In case of CE hop do not run this check again */
|
||||
flag &= ~1;
|
||||
}
|
||||
if ( (iter->pos + 4 > iter->size) || (SUSP_SIG(entry, 'S', 'T'))) {
|
||||
|
||||
/*
|
||||
|
@ -81,22 +116,31 @@ int susp_iter_next(SuspIterator *iter, struct susp_sys_user_entry **sue)
|
|||
* (IEEE 1281, SUSP. section 4)
|
||||
*/
|
||||
if (iter->ce_len) {
|
||||
uint32_t block, nblocks;
|
||||
uint32_t block, nblocks, skipped_blocks, skipped_bytes;
|
||||
|
||||
/* A CE has found, there is another continuation area */
|
||||
nblocks = DIV_UP(iter->ce_off + iter->ce_len, BLOCK_SIZE);
|
||||
/* A CE was found, there is another continuation area */
|
||||
skipped_blocks = iter->ce_off / BLOCK_SIZE;
|
||||
skipped_bytes = skipped_blocks * BLOCK_SIZE;
|
||||
nblocks = DIV_UP(iter->ce_off - skipped_bytes + iter->ce_len,
|
||||
BLOCK_SIZE);
|
||||
if (nblocks <= 0 || iter->ce_len > ISO_SUSP_MAX_CE_BYTES)
|
||||
return ISO_SUSP_WRONG_CE_SIZE;
|
||||
if (((uint64_t) iter->ce_block) + skipped_blocks + nblocks >
|
||||
(uint64_t) iter->fs_blocks)
|
||||
return ISO_SUSP_WRONG_CE_SIZE;
|
||||
iter->buffer = realloc(iter->buffer, nblocks * BLOCK_SIZE);
|
||||
|
||||
/* read all blocks needed to cache the full CE */
|
||||
/* Read blocks needed to cache the given CE area range */
|
||||
for (block = 0; block < nblocks; ++block) {
|
||||
int ret;
|
||||
ret = iter->src->read_block(iter->src, iter->ce_block + block,
|
||||
iter->buffer + block * BLOCK_SIZE);
|
||||
ret = iter->src->read_block(iter->src,
|
||||
iter->ce_block + skipped_blocks + block,
|
||||
iter->buffer + block * BLOCK_SIZE);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
iter->base = iter->buffer + iter->ce_off;
|
||||
iter->base = iter->buffer + (iter->ce_off - skipped_bytes);
|
||||
iter->pos = 0;
|
||||
iter->size = iter->ce_len;
|
||||
iter->ce_len = 0;
|
||||
|
@ -120,9 +164,9 @@ int susp_iter_next(SuspIterator *iter, struct susp_sys_user_entry **sue)
|
|||
if (iter->ce_len) {
|
||||
int ret;
|
||||
ret = iso_msg_submit(iter->msgid, ISO_UNSUPPORTED_SUSP, 0,
|
||||
"More than one CE System user entry has found in a single "
|
||||
"More than one CE System user entry was found in a single "
|
||||
"System Use field or continuation area. This breaks SUSP "
|
||||
"standard and it's not supported. Ignoring last CE. Maybe "
|
||||
"standard and is not supported. Ignoring last CE. Maybe "
|
||||
"the image is damaged.");
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
@ -134,10 +178,15 @@ int susp_iter_next(SuspIterator *iter, struct susp_sys_user_entry **sue)
|
|||
}
|
||||
|
||||
/* we don't want to return CE entry to the user */
|
||||
return susp_iter_next(iter, sue);
|
||||
if (++(iter->ce_counter) > ISO_SUSP_MAX_CE_HOPS) {
|
||||
iso_msg_submit(iter->msgid, ISO_WRONG_RR, 0,
|
||||
"Damaged RR/SUSP information: Too many CE hops.");
|
||||
return ISO_WRONG_RR;
|
||||
}
|
||||
goto process_entry;
|
||||
} else if (SUSP_SIG(entry, 'P', 'D')) {
|
||||
/* skip padding */
|
||||
return susp_iter_next(iter, sue);
|
||||
goto process_entry;
|
||||
}
|
||||
|
||||
*sue = entry;
|
||||
|
@ -211,10 +260,19 @@ int read_rr_TF(struct susp_sys_user_entry *tf, struct stat *st)
|
|||
|
||||
/* 1. Creation time */
|
||||
if (tf->data.TF.flags[0] & (1 << 0)) {
|
||||
|
||||
/* the creation is the recording time. we ignore this */
|
||||
/* TODO maybe it would be good to manage it in ms discs, where
|
||||
* the recording time could be different than now!! */
|
||||
/* Linux accepts ctime by Creation time and by Attributes time.
|
||||
* If both are given, then Attribute time will win.
|
||||
*/
|
||||
if (tf->len_sue[0] < 5 + (nts+1) * s) {
|
||||
/* RR TF entry too short. */
|
||||
return ISO_WRONG_RR;
|
||||
}
|
||||
if (s == 7) {
|
||||
time = iso_datetime_read_7(&tf->data.TF.t_stamps[nts*7]);
|
||||
} else {
|
||||
time = iso_datetime_read_17(&tf->data.TF.t_stamps[nts*17]);
|
||||
}
|
||||
st->st_ctime = time;
|
||||
++nts;
|
||||
}
|
||||
|
||||
|
@ -365,12 +423,18 @@ int read_rr_SL(struct susp_sys_user_entry *sl, char **dest, int *cont)
|
|||
if (*cont == 1) {
|
||||
/* new component */
|
||||
size_t size = strlen(*dest);
|
||||
int has_slash;
|
||||
|
||||
*dest = realloc(*dest, strlen(*dest) + len + 2);
|
||||
if (*dest == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
/* it is a new compoenent, add the '/' */
|
||||
if ((*dest)[size-1] != '/') {
|
||||
has_slash = 0;
|
||||
if (size > 0)
|
||||
if ((*dest)[size - 1] == '/')
|
||||
has_slash = 1;
|
||||
if (!has_slash) {
|
||||
(*dest)[size] = '/';
|
||||
(*dest)[size+1] = '\0';
|
||||
}
|
||||
|
@ -412,7 +476,7 @@ int read_rr_PN(struct susp_sys_user_entry *pn, struct stat *st)
|
|||
{
|
||||
int high_shift= 0;
|
||||
|
||||
if (pn == NULL || pn == NULL) {
|
||||
if (pn == NULL || st == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
if (pn->sig[0] != 'P' || pn->sig[1] != 'N') {
|
||||
|
@ -453,24 +517,27 @@ int read_aaip_AA(struct susp_sys_user_entry *sue,
|
|||
if (*is_done) {
|
||||
|
||||
/* To coexist with Apple ISO :
|
||||
Gracefully react on eventually trailing Apple AA
|
||||
Gracefully react on possibly trailing Apple AA
|
||||
*/
|
||||
if (sue->version[0] != 1 || sue->len_sue[0] == 7)
|
||||
return ISO_SUCCESS;
|
||||
|
||||
return ISO_WRONG_RR;
|
||||
}
|
||||
|
||||
|
||||
/* Eventually create or grow storage */
|
||||
if (*aa_size == 0 || *aa_string == NULL) {
|
||||
|
||||
/* Gracefully react on eventually leading Apple AA
|
||||
/* Gracefully react on possibly leading Apple AA
|
||||
*/
|
||||
if (sue->version[0] != 1 || sue->len_sue[0] < 9) {
|
||||
if (sue->version[0] != 1 || sue->len_sue[0] < 9)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* A valid AAIP AA entry has 5 header bytes and at least 1 component byte
|
||||
*/
|
||||
if (sue->len_sue[0] < 6)
|
||||
return ISO_WRONG_RR;
|
||||
|
||||
/* Possibly create or grow storage */
|
||||
if (*aa_size == 0 || *aa_string == NULL) {
|
||||
*aa_size = *aa_len + sue->len_sue[0];
|
||||
*aa_string = calloc(*aa_size, 1);
|
||||
*aa_len = 0;
|
||||
|
@ -526,7 +593,12 @@ int read_aaip_AL(struct susp_sys_user_entry *sue,
|
|||
if (sue->version[0] != 1)
|
||||
return ISO_WRONG_RR;
|
||||
|
||||
/* Eventually create or grow storage */
|
||||
/* A valid AL entry has 5 header bytes and at least 1 component byte
|
||||
*/
|
||||
if (sue->len_sue[0] < 6)
|
||||
return ISO_WRONG_RR;
|
||||
|
||||
/* Possibly create or grow storage */
|
||||
if (*aa_size == 0 || *aa_string == NULL) {
|
||||
*aa_size = *aa_len + sue->len_sue[0];
|
||||
*aa_string = calloc(*aa_size, 1);
|
||||
|
@ -563,29 +635,36 @@ int read_aaip_AL(struct susp_sys_user_entry *sue,
|
|||
}
|
||||
|
||||
/**
|
||||
* Reads the zisofs parameters from a ZF field (see doc/zisofs_format.txt).
|
||||
* Reads the zisofs parameters from a ZF field (see doc/zisofs_format.txt
|
||||
* and doc/zisofs2_format.txt).
|
||||
*
|
||||
* @return
|
||||
* 1 on success, < 0 on error
|
||||
*/
|
||||
int read_zisofs_ZF(struct susp_sys_user_entry *zf, uint8_t algorithm[2],
|
||||
uint8_t *header_size_div4, uint8_t *block_size_log2,
|
||||
uint32_t *uncompressed_size, int flag)
|
||||
uint64_t *uncompressed_size, int flag)
|
||||
{
|
||||
if (zf == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
if (zf->sig[0] != 'Z' || zf->sig[1] != 'F') {
|
||||
if ((zf->sig[0] != 'Z' || zf->sig[1] != 'F') &&
|
||||
(zf->sig[0] != 'Z' || zf->sig[1] != '2'))
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
if (zf->len_sue[0] != 16) {
|
||||
return ISO_WRONG_RR;
|
||||
}
|
||||
if (zf->version[0] > 2)
|
||||
return ISO_WRONG_RR;
|
||||
algorithm[0] = zf->data.ZF.parameters[0];
|
||||
algorithm[1] = zf->data.ZF.parameters[1];
|
||||
*header_size_div4 = zf->data.ZF.parameters[2];
|
||||
*block_size_log2 = zf->data.ZF.parameters[3];
|
||||
*uncompressed_size = iso_read_bb(&(zf->data.ZF.parameters[4]), 4, NULL);
|
||||
if (zf->version[0] == 1)
|
||||
*uncompressed_size = iso_read_bb(&(zf->data.ZF.parameters[4]), 4,
|
||||
NULL);
|
||||
else
|
||||
*uncompressed_size = iso_read_lsb64(&(zf->data.ZF.parameters[4]));
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 - 2011 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2022 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -22,6 +22,7 @@
|
|||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#ifndef PATH_MAX
|
||||
|
@ -164,15 +165,6 @@ IsoStream *fsrc_get_input_stream(IsoStream *stream, int flag)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
int fsrc_cmp_ino(IsoStream *s1, IsoStream *s2)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = iso_stream_cmp_ino(s1, s2, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fsrc_clone_stream(IsoStream *old_stream, IsoStream **new_stream,
|
||||
int flag)
|
||||
{
|
||||
|
@ -227,7 +219,7 @@ IsoStreamIface fsrc_stream_class = {
|
|||
fsrc_free,
|
||||
fsrc_update_size,
|
||||
fsrc_get_input_stream,
|
||||
fsrc_cmp_ino,
|
||||
NULL,
|
||||
fsrc_clone_stream
|
||||
};
|
||||
|
||||
|
@ -299,25 +291,25 @@ int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream)
|
|||
}
|
||||
|
||||
|
||||
int iso_stream_get_src_zf(IsoStream *stream, int *header_size_div4,
|
||||
int *block_size_log2, uint32_t *uncompressed_size,
|
||||
int flag)
|
||||
int iso_stream_get_src_zf(IsoStream *stream, uint8_t zisofs_algo[2],
|
||||
int *header_size_div4, int *block_size_log2,
|
||||
uint64_t *uncompressed_size, int flag)
|
||||
{
|
||||
int ret;
|
||||
FSrcStreamData *data;
|
||||
IsoFileSource *src;
|
||||
|
||||
/* Intimate friendship with libisofs/fs_image.c */
|
||||
int iso_ifs_source_get_zf(IsoFileSource *src, int *header_size_div4,
|
||||
int *block_size_log2, uint32_t *uncompressed_size, int flag);
|
||||
int iso_ifs_source_get_zf(IsoFileSource *src, uint8_t zisofs_algo[2],
|
||||
int *header_size_div4, int *block_size_log2,
|
||||
uint64_t *uncompressed_size, int flag);
|
||||
|
||||
if (stream->class != &fsrc_stream_class)
|
||||
return 0;
|
||||
data = stream->data;
|
||||
src = data->src;
|
||||
|
||||
ret = iso_ifs_source_get_zf(src, header_size_div4, block_size_log2,
|
||||
uncompressed_size, 0);
|
||||
ret = iso_ifs_source_get_zf(src, zisofs_algo, header_size_div4,
|
||||
block_size_log2, uncompressed_size, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -339,6 +331,7 @@ int cut_out_open(IsoStream *stream)
|
|||
{
|
||||
int ret;
|
||||
struct stat info;
|
||||
off_t src_size, pos;
|
||||
IsoFileSource *src;
|
||||
struct cut_out_stream *data;
|
||||
|
||||
|
@ -357,20 +350,26 @@ int cut_out_open(IsoStream *stream)
|
|||
return ret;
|
||||
}
|
||||
|
||||
{
|
||||
off_t ret;
|
||||
if (data->offset > info.st_size) {
|
||||
/* file is smaller than expected */
|
||||
ret = iso_file_source_lseek(src, info.st_size, 0);
|
||||
} else {
|
||||
ret = iso_file_source_lseek(src, data->offset, 0);
|
||||
}
|
||||
if (ret < 0) {
|
||||
return (int) ret;
|
||||
}
|
||||
if (S_ISREG(info.st_mode)) {
|
||||
src_size= info.st_size;
|
||||
} else {
|
||||
/* Determine src_size and lseekability of device */
|
||||
src_size = iso_file_source_determine_capacity(src,
|
||||
data->offset + data->size, 2);
|
||||
if (src_size <= 0)
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
if (data->offset > src_size) {
|
||||
/* file is smaller than expected */
|
||||
pos = iso_file_source_lseek(src, src_size, 0);
|
||||
} else {
|
||||
pos = iso_file_source_lseek(src, data->offset, 0);
|
||||
}
|
||||
if (pos < 0) {
|
||||
return (int) pos;
|
||||
}
|
||||
data->pos = 0;
|
||||
if (data->offset + data->size > info.st_size) {
|
||||
if (data->offset + data->size > src_size) {
|
||||
return 3; /* file smaller than expected */
|
||||
} else {
|
||||
return ISO_SUCCESS;
|
||||
|
@ -448,15 +447,6 @@ IsoStream* cut_out_get_input_stream(IsoStream *stream, int flag)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
int cut_out_cmp_ino(IsoStream *s1, IsoStream *s2)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = iso_stream_cmp_ino(s1, s2, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int cut_out_clone_stream(IsoStream *old_stream, IsoStream **new_stream,
|
||||
int flag)
|
||||
|
@ -517,7 +507,7 @@ IsoStreamIface cut_out_stream_class = {
|
|||
cut_out_free,
|
||||
cut_out_update_size,
|
||||
cut_out_get_input_stream,
|
||||
cut_out_cmp_ino,
|
||||
NULL,
|
||||
cut_out_clone_stream
|
||||
|
||||
};
|
||||
|
@ -526,6 +516,7 @@ int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
|
|||
IsoStream **stream)
|
||||
{
|
||||
int r;
|
||||
off_t src_size;
|
||||
struct stat info;
|
||||
IsoStream *str;
|
||||
struct cut_out_stream *data;
|
||||
|
@ -541,10 +532,16 @@ int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
|
|||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
if (!S_ISREG(info.st_mode)) {
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
|
||||
if (S_ISREG(info.st_mode)) {
|
||||
src_size = info.st_size;
|
||||
} else {
|
||||
/* Open src, do iso_source_lseek(SEEK_END), close src */
|
||||
src_size = iso_file_source_determine_capacity(src, offset + size, 3);
|
||||
if (src_size <= 0)
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
if (offset > info.st_size) {
|
||||
if (offset > src_size) {
|
||||
return ISO_FILE_OFFSET_TOO_BIG;
|
||||
}
|
||||
|
||||
|
@ -569,7 +566,7 @@ int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
|
|||
iso_file_source_ref(src);
|
||||
|
||||
data->offset = offset;
|
||||
data->size = MIN(info.st_size - offset, size);
|
||||
data->size = MIN(src_size - offset, size);
|
||||
|
||||
/* get the id numbers */
|
||||
data->dev_id = (dev_t) 0;
|
||||
|
@ -698,15 +695,6 @@ IsoStream* mem_get_input_stream(IsoStream *stream, int flag)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
int mem_cmp_ino(IsoStream *s1, IsoStream *s2)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = iso_stream_cmp_ino(s1, s2, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int mem_clone_stream(IsoStream *old_stream, IsoStream **new_stream,
|
||||
int flag)
|
||||
|
@ -763,7 +751,7 @@ IsoStreamIface mem_stream_class = {
|
|||
mem_free,
|
||||
mem_update_size,
|
||||
mem_get_input_stream,
|
||||
mem_cmp_ino,
|
||||
NULL,
|
||||
mem_clone_stream
|
||||
|
||||
};
|
||||
|
@ -879,12 +867,24 @@ void iso_stream_get_file_name(IsoStream *stream, char *name)
|
|||
strncpy(name, path, PATH_MAX - 1);
|
||||
name[PATH_MAX - 1] = 0;
|
||||
free(path);
|
||||
} else if (!strncmp(type, "boot", 4)) {
|
||||
strcpy(name, "BOOT CATALOG");
|
||||
} else if (!strncmp(type, "cout", 4)) {
|
||||
strcpy(name, "CUT_OUT FILE");
|
||||
} else if (!strncmp(type, "mem ", 4)) {
|
||||
strcpy(name, "MEM SOURCE");
|
||||
} else if (!strncmp(type, "boot", 4)) {
|
||||
strcpy(name, "BOOT CATALOG");
|
||||
} else if (!strncmp(type, "extf", 4)) {
|
||||
strcpy(name, "EXTERNAL FILTER");
|
||||
} else if (!strncmp(type, "ziso", 4)) {
|
||||
strcpy(name, "ZISOFS COMPRESSION FILTER");
|
||||
} else if (!strncmp(type, "osiz", 4)) {
|
||||
strcpy(name, "ZISOFS DECOMPRESSION FILTER");
|
||||
} else if (!strncmp(type, "gzip", 4)) {
|
||||
strcpy(name, "GZIP COMPRESSION FILTER");
|
||||
} else if (!strncmp(type, "pizg", 4)) {
|
||||
strcpy(name, "GZIP DECOMPRESSION FILTER");
|
||||
} else if (!strncmp(type, "user", 4)) {
|
||||
strcpy(name, "USER SUPPLIED STREAM");
|
||||
} else {
|
||||
strcpy(name, "UNKNOWN SOURCE");
|
||||
}
|
||||
|
@ -943,12 +943,22 @@ ex:;
|
|||
return path;
|
||||
}
|
||||
|
||||
/* @return 1 = ok , 0 = not an ISO image stream , <0 = error */
|
||||
/*
|
||||
@param flag bit0= in case of filter stream do not dig for base stream
|
||||
@return 1 = ok , 0 = not an ISO image stream , <0 = error
|
||||
*/
|
||||
int iso_stream_set_image_ino(IsoStream *stream, ino_t ino, int flag)
|
||||
{
|
||||
IsoStream *base_stream;
|
||||
|
||||
if (stream == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
if (!(flag & 1)) {
|
||||
base_stream = iso_stream_get_input_stream(stream, 1);
|
||||
if (base_stream != NULL)
|
||||
stream = base_stream;
|
||||
}
|
||||
if (stream->class == &fsrc_stream_class) {
|
||||
FSrcStreamData *fsrc_data = stream->data;
|
||||
fsrc_data->ino_id = ino;
|
||||
|
@ -957,6 +967,104 @@ int iso_stream_set_image_ino(IsoStream *stream, ino_t ino, int flag)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int iso_stream_cmp_ifs_sections(IsoStream *s1, IsoStream *s2, int *cmp_ret,
|
||||
int flag)
|
||||
{
|
||||
int ret;
|
||||
FSrcStreamData *fssd1, *fssd2;
|
||||
IsoFileSource *src1, *src2;
|
||||
|
||||
/* Must keep any suspect in the game to preserve transitivity of the
|
||||
calling function by ranking applicable streams lower than
|
||||
non-applicable. ones.
|
||||
*/
|
||||
if (s1->class != &fsrc_stream_class && s2->class != &fsrc_stream_class)
|
||||
return 0;
|
||||
|
||||
/* Compare eventual image data section LBA and sizes */
|
||||
if (s1->class == &fsrc_stream_class) {
|
||||
fssd1= (FSrcStreamData *) s1->data;
|
||||
src1 = fssd1->src;
|
||||
} else {
|
||||
src1 = NULL;
|
||||
}
|
||||
if (s2->class == &fsrc_stream_class) {
|
||||
fssd2= (FSrcStreamData *) s2->data;
|
||||
src2 = fssd2->src;
|
||||
} else {
|
||||
src2 = NULL;
|
||||
}
|
||||
ret = iso_ifs_sections_cmp(src1, src2, cmp_ret, 1);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Maintain and exploit a list of stream compare functions seen by
|
||||
iso_stream_cmp_ino(). This is needed to separate stream comparison
|
||||
families in order to keep iso_stream_cmp_ino() transitive while
|
||||
alternative stream->class->cmp_ino() decide inside the families.
|
||||
*/
|
||||
struct iso_streamcmprank {
|
||||
int (*cmp_func)(IsoStream *s1, IsoStream *s2);
|
||||
struct iso_streamcmprank *next;
|
||||
};
|
||||
|
||||
static struct iso_streamcmprank *streamcmpranks = NULL;
|
||||
|
||||
static
|
||||
int iso_get_streamcmprank(int (*cmp_func)(IsoStream *s1, IsoStream *s2),
|
||||
int flag)
|
||||
{
|
||||
int idx;
|
||||
struct iso_streamcmprank *cpr, *last_cpr = NULL;
|
||||
|
||||
idx = 0;
|
||||
for (cpr = streamcmpranks; cpr != NULL; cpr = cpr->next) {
|
||||
if (cpr->cmp_func == cmp_func)
|
||||
break;
|
||||
idx++;
|
||||
last_cpr = cpr;
|
||||
}
|
||||
if (cpr != NULL)
|
||||
return idx;
|
||||
LIBISO_ALLOC_MEM_VOID(cpr, struct iso_streamcmprank, 1);
|
||||
cpr->cmp_func = cmp_func;
|
||||
cpr->next = NULL;
|
||||
if (last_cpr != NULL)
|
||||
last_cpr->next = cpr;
|
||||
if (streamcmpranks == NULL)
|
||||
streamcmpranks = cpr;
|
||||
return idx;
|
||||
ex:;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static
|
||||
int iso_cmp_streamcmpranks(int (*cf1)(IsoStream *s1, IsoStream *s2),
|
||||
int (*cf2)(IsoStream *s1, IsoStream *s2))
|
||||
{
|
||||
int rank1, rank2;
|
||||
|
||||
rank1 = iso_get_streamcmprank(cf1, 0);
|
||||
rank2 = iso_get_streamcmprank(cf2, 0);
|
||||
return rank1 < rank2 ? -1 : 1;
|
||||
}
|
||||
|
||||
int iso_stream_destroy_cmpranks(int flag)
|
||||
{
|
||||
struct iso_streamcmprank *cpr, *next;
|
||||
|
||||
for (cpr = streamcmpranks; cpr != NULL; cpr = next) {
|
||||
next = cpr->next;
|
||||
LIBISO_FREE_MEM(cpr);
|
||||
}
|
||||
streamcmpranks = NULL;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, int flag)
|
||||
{
|
||||
|
@ -965,8 +1073,6 @@ int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, int flag)
|
|||
dev_t dev_id1, dev_id2;
|
||||
ino_t ino_id1, ino_id2;
|
||||
off_t size1, size2;
|
||||
FSrcStreamData *fssd1, *fssd2;
|
||||
|
||||
|
||||
/*
|
||||
#define Libisofs_stream_cmp_ino_debuG 1
|
||||
|
@ -983,10 +1089,72 @@ int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, int flag)
|
|||
if (s2 == NULL)
|
||||
return 1;
|
||||
|
||||
if (s1->class->version >= 3 && !(flag & 1)) {
|
||||
/* Filters may have smarter methods to compare themselves with others */
|
||||
ret = s1->class->cmp_ino(s1, s2);
|
||||
return ret;
|
||||
/* This stays transitive by the fact that
|
||||
iso_stream_cmp_ifs_sections() is transitive,
|
||||
returns > 0 if s1 or s2 are applicable,
|
||||
ret is -1 if s1 is applicable but s2 is not,
|
||||
ret is 1 if s1 is not applicable but s2 is.
|
||||
|
||||
Proof:
|
||||
Be A the set of applicable streams, S and G transitive and
|
||||
antisymmetric relations in respect to outcome {-1, 0, 1}.
|
||||
The combined relation R shall be defined by
|
||||
I. R(a,b) = S(a,b) if a in A or b in A, else G(a,b)
|
||||
Further S shall have the property
|
||||
II. S(a,b) = -1 if a in A and b not in A
|
||||
Then R can be proven to be transitive:
|
||||
By enumerating the 8 combinations of a,b,c being in A or not, we get
|
||||
5 cases of pure S or pure G. Three cases are mixed:
|
||||
a,b not in A, c in A : G(a,b) == -1, S(b,c) == -1 -> S(a,c) == -1
|
||||
Impossible because S(b,c) == -1 contradicts II.
|
||||
a,c not in A, b in A : S(a,b) == -1, S(b,c) == -1 -> G(a,c) == -1
|
||||
Impossible because S(a,b) == -1 contradicts II.
|
||||
b,c not in A, a in A : S(a,b) == -1, G(b,c) == -1 -> S(a,c) == -1
|
||||
Always true because S(a,c) == -1 by definition II.
|
||||
*/
|
||||
if (iso_stream_cmp_ifs_sections(s1, s2, &ret, 0) > 0)
|
||||
return ret; /* Both are unfiltered from loaded ISO filesystem */
|
||||
|
||||
if (!(flag & 1)) {
|
||||
/* Filters may have smarter methods to compare themselves with others.
|
||||
Transitivity is ensured by ranking mixed pairs by the rank of their
|
||||
comparison functions, and by ranking streams with .cmp_ino lower
|
||||
than streams without.
|
||||
(One could merge (class->version < 3) and (cmp_ino == NULL).)
|
||||
|
||||
Here we define S for "and" rather than "or"
|
||||
I. R(a,b) = S(a,b) if a in A and b in A, else G(a,b)
|
||||
and the function ranking in case of "exor" makes sure that
|
||||
II. G(a,b) = -1 if a in A and b not in A
|
||||
Again we get three mixed cases:
|
||||
a not in A, b,c in A : G(a,b) == -1, S(b,c) == -1 -> G(a,c) == -1
|
||||
Impossible because G(a,b) == -1 contradicts II.
|
||||
b not in A, a,c in A : G(a,b) == -1, G(b,c) == -1 -> S(a,c) == -1
|
||||
Impossible because G(b,c) == -1 contradicts II.
|
||||
c not in A, a,b in A : S(a,b) == -1, G(b,c) == -1 -> G(a,c) == -1
|
||||
Always true because G(a,c) == -1 by definition II.
|
||||
*/
|
||||
if ((s1->class->version >= 3) ^ (s2->class->version >= 3)) {
|
||||
/* One of both has no own com_ino function. Rank it as larger. */
|
||||
return s1->class->version >= 3 ? -1 : 1;
|
||||
} else if (s1->class->version >= 3) {
|
||||
if (s1->class->cmp_ino == s2->class->cmp_ino) {
|
||||
if (s1->class->cmp_ino == NULL) {
|
||||
/* Both are NULL. No decision by .cmp_ino(). */;
|
||||
} else {
|
||||
/* Both are compared by the same function */
|
||||
ret = s1->class->cmp_ino(s1, s2);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
/* Not the same cmp_ino() function. Decide by list rank of
|
||||
function while building the list on the fly.
|
||||
*/
|
||||
ret = iso_cmp_streamcmpranks(s1->class->cmp_ino,
|
||||
s2->class->cmp_ino);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iso_stream_get_id(s1, &fs_id1, &dev_id1, &ino_id1);
|
||||
|
@ -1042,14 +1210,6 @@ int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, int flag)
|
|||
|
||||
if (s1->class != s2->class)
|
||||
return (s1->class < s2->class ? -1 : 1);
|
||||
if (s1->class == &fsrc_stream_class) {
|
||||
/* Compare eventual image data section LBA and sizes */
|
||||
fssd1= (FSrcStreamData *) s1->data;
|
||||
fssd2= (FSrcStreamData *) s2->data;
|
||||
ret = iso_ifs_sections_cmp(fssd1->src, fssd2->src, 0);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
if (fs_id1 == 0 && dev_id1 == 0 && ino_id1 == 0) {
|
||||
return (s1 < s2 ? -1 : 1);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 - 2011 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2016 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -37,11 +37,11 @@ void iso_stream_get_file_name(IsoStream *stream, char *name);
|
|||
/**
|
||||
* Create a stream to read from a IsoFileSource.
|
||||
* The stream will take the ref. to the IsoFileSource, so after a successfully
|
||||
* exectution of this function, you musn't unref() the source, unless you
|
||||
* execution of this function, you must not unref() the source, unless you
|
||||
* take an extra ref.
|
||||
*
|
||||
* @return
|
||||
* 1 sucess, < 0 error
|
||||
* 1 success, < 0 error
|
||||
* Possible errors:
|
||||
*
|
||||
*/
|
||||
|
@ -52,7 +52,7 @@ int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream);
|
|||
* The stream will add a ref. to the IsoFileSource.
|
||||
*
|
||||
* @return
|
||||
* 1 sucess, < 0 error
|
||||
* 1 success, < 0 error
|
||||
*/
|
||||
int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
|
||||
IsoStream **stream);
|
||||
|
@ -65,9 +65,9 @@ int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
|
|||
* type, though, unless fsrc_stream_class would be used without FSrcStreamData.
|
||||
* @return 1= returned parameters are valid, 0=no ZF info found , <0 error
|
||||
*/
|
||||
int iso_stream_get_src_zf(IsoStream *stream, int *header_size_div4,
|
||||
int *block_size_log2, uint32_t *uncompressed_size,
|
||||
int flag);
|
||||
int iso_stream_get_src_zf(IsoStream *stream, uint8_t zisofs_algo[2],
|
||||
int *header_size_div4, int *block_size_log2,
|
||||
uint64_t *uncompressed_size, int flag);
|
||||
|
||||
/**
|
||||
* Set the inode number of a stream that is based on FSrcStreamData, i.e.
|
||||
|
@ -112,4 +112,13 @@ int iso_stream_clone_filter_common(IsoStream *old_stream,
|
|||
IsoStream **new_stream,
|
||||
IsoStream **new_input, int flag);
|
||||
|
||||
|
||||
/**
|
||||
* Dispose the internal list of stream class cmp_ino() functions. It is
|
||||
* a static global of stream.c, created and used by iso_stream_cmp_ino().
|
||||
* This function is supposed to be called by iso_finish() only.
|
||||
*/
|
||||
int iso_stream_destroy_cmpranks(int flag);
|
||||
|
||||
|
||||
#endif /*STREAM_H_*/
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2008 Vreixo Formoso
|
||||
* Copyright (c) 2012 Thomas Schmitt
|
||||
* Copyright (c) 2012 - 2024 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -42,10 +42,12 @@ int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag);
|
|||
*
|
||||
* @param buf
|
||||
* A buffer with at least 32 K allocated
|
||||
* @param flag
|
||||
* bit0= t->opts->ms_block is not counted in t->total_size
|
||||
* @return
|
||||
* 1 if success, < 0 on error
|
||||
*/
|
||||
int iso_write_system_area(Ecma119Image *t, uint8_t *buf);
|
||||
int iso_write_system_area(Ecma119Image *t, uint8_t *buf, int flag);
|
||||
|
||||
/**
|
||||
* Adjust t->tail_blocks to the eventual alignment needs of isohybrid booting.
|
||||
|
@ -72,7 +74,7 @@ int iso_compute_append_partitions(Ecma119Image *t, int flag);
|
|||
in the table.
|
||||
Requested entries with block_count == 0 get expanded to the start of
|
||||
the next requested entry resp. to image end, if no entry follows.
|
||||
start_block of a follwing entry must be at least a high as the sum of
|
||||
start_block of a following entry must be at least a high as the sum of
|
||||
start_block and block_count of the previous entry.
|
||||
Empty requested entries will be represented as 16 bytes of 0.
|
||||
*/
|
||||
|
@ -102,19 +104,27 @@ struct iso_mbr_partition_request {
|
|||
*/
|
||||
int desired_slot;
|
||||
|
||||
/* Only when representing an imported partition:
|
||||
Path of file in imported ISO which holds the partition content.
|
||||
NULL = no such file
|
||||
*/
|
||||
char *image_path;
|
||||
|
||||
};
|
||||
|
||||
/* Copies the content of req and registers it in t.mbr_req[].
|
||||
I.e. after the call the submitted storage of req can be disposed or re-used.
|
||||
Submit 0 as value flag.
|
||||
*/
|
||||
int iso_register_mbr_entry(Ecma119Image *t,
|
||||
int iso_register_mbr_entry(struct iso_mbr_partition_request **req_array,
|
||||
int *mbr_req_count,
|
||||
struct iso_mbr_partition_request *req, int flag);
|
||||
|
||||
/* Convenience frontend for iso_register_mbr_entry().
|
||||
name and type are 0-terminated strings, which may get silently truncated.
|
||||
*/
|
||||
int iso_quick_mbr_entry(Ecma119Image *t,
|
||||
int iso_quick_mbr_entry(struct iso_mbr_partition_request **req_array,
|
||||
int *mbr_req_count,
|
||||
uint64_t start_block, uint64_t block_count,
|
||||
uint8_t type_byte, uint8_t status_byte,
|
||||
int desired_slot);
|
||||
|
@ -125,12 +135,13 @@ int iso_quick_mbr_entry(Ecma119Image *t,
|
|||
Return value is 0 if occupied, 1 if free, and -1 if the slot number is
|
||||
out of range.
|
||||
*/
|
||||
int iso_mbr_entry_slot_is_free(Ecma119Image *t, int slot);
|
||||
int iso_mbr_entry_slot_is_free(struct iso_mbr_partition_request **req_array,
|
||||
int mbr_req_count, int slot);
|
||||
|
||||
|
||||
/* The parameter struct for production of a single Apple Partition Map entry.
|
||||
See also the partial APM description in doc/boot_sectors.txt.
|
||||
The list of entries is stored in Ecma119Image.apm_req.
|
||||
The list of entries is stored e.g. in Ecma119Image.apm_req, .apm_req_count.
|
||||
The size of a block can be chosen by setting Ecma119Image.apm_block_size.
|
||||
If an entry has start_block <=1, then its block_count will be adjusted
|
||||
to the final size of the partition map.
|
||||
|
@ -144,34 +155,43 @@ struct iso_apm_partition_request {
|
|||
/* Given in blocks of 2 KiB unless (Ecma119Image.apm_req_flags & 4).
|
||||
Written to the ISO image according to Ecma119Image.apm_block_size.
|
||||
*/
|
||||
uint32_t start_block;
|
||||
uint32_t block_count;
|
||||
uint64_t start_block;
|
||||
uint64_t block_count;
|
||||
|
||||
/* All 32 bytes get copied to the system area.
|
||||
Take care to pad up short strings by 0.
|
||||
*/
|
||||
uint8_t name[32];
|
||||
uint8_t type[32];
|
||||
|
||||
/* Status of the request object itself:
|
||||
bit0= this is an automatically placed filler partition
|
||||
*/
|
||||
uint32_t req_status;
|
||||
|
||||
/* Only when representing an imported partition:
|
||||
Path of file in imported ISO which holds the partition content.
|
||||
NULL = no such file
|
||||
*/
|
||||
char *image_path;
|
||||
|
||||
};
|
||||
|
||||
/* Copies the content of req and registers it in t.apm_req[].
|
||||
I.e. after the call the submitted storage of req can be disposed or re-used.
|
||||
Submit 0 as value flag.
|
||||
*/
|
||||
int iso_register_apm_entry(Ecma119Image *t,
|
||||
int iso_register_apm_entry(struct iso_apm_partition_request **req_array,
|
||||
int *apm_req_count,
|
||||
struct iso_apm_partition_request *req, int flag);
|
||||
|
||||
/* Convenience frontend for iso_register_apm_entry().
|
||||
name and type are 0-terminated strings, which may get silently truncated.
|
||||
*/
|
||||
int iso_quick_apm_entry(Ecma119Image *t,
|
||||
uint32_t start_block, uint32_t block_count, char *name, char *type);
|
||||
|
||||
|
||||
/* CRC-32 as of GPT and Ethernet.
|
||||
*/
|
||||
unsigned int iso_crc32_gpt(unsigned char *data, int count, int flag);
|
||||
|
||||
int iso_quick_apm_entry(struct iso_apm_partition_request **req_array,
|
||||
int *apm_req_count,
|
||||
uint32_t start_block, uint32_t block_count,
|
||||
char *name, char *type);
|
||||
|
||||
/* These two pseudo-random generators produce byte strings which will
|
||||
surely not duplicate in the first 256 calls. If more calls are necessary
|
||||
|
@ -182,10 +202,15 @@ unsigned int iso_crc32_gpt(unsigned char *data, int count, int flag);
|
|||
run on other machines with the same process number at the same time.
|
||||
*/
|
||||
|
||||
/* Produces a weakly random variation of a hardcoded real random uuid
|
||||
/* Produces a GPT disk or partition GUID.
|
||||
Pseudo-random by iso_generate_gpt_guid() if t->gpt_uuid_counter is 0.
|
||||
Else derived reproducibly by counter number from t->gpt_uuid_base.
|
||||
*/
|
||||
void iso_random_uuid(Ecma119Image *t, uint8_t uuid[16]);
|
||||
void iso_gpt_uuid(Ecma119Image *t, uint8_t uuid[16]);
|
||||
|
||||
/* Mark a given byte string as UUID version 4, RFC 4122.
|
||||
*/
|
||||
void iso_mark_guid_version_4(uint8_t *u);
|
||||
|
||||
/* The parameter struct for production of a single GPT entry.
|
||||
See also the partial GPT description in doc/boot_sectors.txt.
|
||||
|
@ -206,11 +231,10 @@ void iso_random_uuid(Ecma119Image *t, uint8_t uuid[16]);
|
|||
*/
|
||||
struct iso_gpt_partition_request {
|
||||
|
||||
/* Always given in blocks of 2 KiB.
|
||||
Written to the ISO image in blocks of 512.
|
||||
/* Always given in blocks of 512 bytes.
|
||||
*/
|
||||
uint32_t start_block;
|
||||
uint32_t block_count;
|
||||
uint64_t start_block;
|
||||
uint64_t block_count;
|
||||
|
||||
/* The registered GUID which defines the partition type */
|
||||
uint8_t type_guid[16];
|
||||
|
@ -231,23 +255,54 @@ struct iso_gpt_partition_request {
|
|||
Take care to pad up short strings by 0.
|
||||
*/
|
||||
uint8_t name[72];
|
||||
|
||||
/* Only if read from imported image: Table index of partition (first = 1)
|
||||
*/
|
||||
uint32_t idx;
|
||||
|
||||
/* Status of the request object itself:
|
||||
bit0= this is an automatically placed filler partition
|
||||
*/
|
||||
uint32_t req_status;
|
||||
|
||||
/* Desired partition number in emerging GPT: first = 1, no desire = 0
|
||||
GPT partitions get sorted by start LBA. Gaps of uncovered blocks get
|
||||
filled. If the resulting sequence positions the partition at a lower
|
||||
slot than desired, then empty slots get inserted to match the desire.
|
||||
If the sequence positions the partition at a higher slot, then a mere
|
||||
note is issued and the partition gets into the higher slot.
|
||||
*/
|
||||
int desired_slot;
|
||||
|
||||
/* Only when representing an imported partition:
|
||||
Path of file in imported ISO which holds the partition content.
|
||||
NULL = no such file
|
||||
*/
|
||||
char *image_path;
|
||||
};
|
||||
|
||||
/* Copies the content of req and registers it in t.gpt_req[].
|
||||
I.e. after the call the submitted storage of req can be disposed or re-used.
|
||||
Submit 0 as value flag.
|
||||
*/
|
||||
int iso_register_gpt_entry(Ecma119Image *t,
|
||||
int iso_register_gpt_entry(struct iso_gpt_partition_request **req_array,
|
||||
int *gpt_req_count,
|
||||
struct iso_gpt_partition_request *req, int flag);
|
||||
|
||||
/* Convenience frontend for iso_register_gpt_entry().
|
||||
name has to be already encoded as UTF-16LE.
|
||||
*/
|
||||
int iso_quick_gpt_entry(Ecma119Image *t,
|
||||
uint32_t start_block, uint32_t block_count,
|
||||
int iso_quick_gpt_entry(struct iso_gpt_partition_request **req_array,
|
||||
int *gpt_req_count,
|
||||
uint64_t start_block, uint64_t block_count,
|
||||
uint8_t type_guid[16], uint8_t partition_guid[16],
|
||||
uint64_t flags, uint8_t name[72]);
|
||||
|
||||
/* Deletes the partition requests for gap filling in GPT and APM.
|
||||
Purpose is to get the request list clean again after a multi-session
|
||||
emulation superblock was created and handed to the application.
|
||||
*/
|
||||
void iso_delete_gpt_apm_fillers(Ecma119Image *target, int flag);
|
||||
|
||||
/* Internal helper that will be used by system_area.c and make_isohybrid_mbr.c
|
||||
*/
|
||||
|
@ -255,14 +310,41 @@ int iso_write_gpt_header_block(Ecma119Image *t, uint32_t img_blocks,
|
|||
uint8_t *buf, uint32_t max_entries,
|
||||
uint32_t part_start, uint32_t p_arr_crc);
|
||||
|
||||
/* The description of a loaded MIPS Big Endian Volume Directory Entry
|
||||
*/
|
||||
struct iso_mips_voldir_entry {
|
||||
char name[9];
|
||||
uint32_t boot_block;
|
||||
uint32_t boot_bytes;
|
||||
};
|
||||
|
||||
/* The description of a loaded SUN Disk Label partition */
|
||||
struct iso_sun_disk_label_entry {
|
||||
int idx;
|
||||
uint16_t id_tag;
|
||||
uint16_t permissions;
|
||||
uint32_t start_cyl;
|
||||
uint32_t num_blocks;
|
||||
};
|
||||
|
||||
/* Creates the Partition Prepend writer.
|
||||
*/
|
||||
int partprepend_writer_create(Ecma119Image *target);
|
||||
|
||||
/* Creates the Inline Partition Append Writer
|
||||
*/
|
||||
int partappend_writer_create(Ecma119Image *target);
|
||||
|
||||
/* Creates the GPT backup tail writer.
|
||||
*/
|
||||
int gpt_tail_writer_create(Ecma119Image *target);
|
||||
|
||||
/* Not for execution but only to identify the writer by
|
||||
( writer->write_vol_desc == gpt_tail_writer_write_vol_desc )
|
||||
*/
|
||||
int gpt_tail_writer_write_vol_desc(IsoImageWriter *writer);
|
||||
|
||||
|
||||
/* Only for up to 36 characters ISO-8859-1 (or ASCII) input */
|
||||
void iso_ascii_utf_16le(uint8_t gap_name[72]);
|
||||
|
||||
|
@ -279,4 +361,14 @@ void iso_ascii_utf_16le(uint8_t gap_name[72]);
|
|||
#define Libisofs_grub2_sparc_patch_adr_poS 0x228
|
||||
#define Libisofs_grub2_sparc_patch_size_poS 0x230
|
||||
|
||||
|
||||
/* Put appended partitions into the writer range
|
||||
*/
|
||||
#define Libisofs_appended_partitions_inlinE yes
|
||||
#ifdef Libisofs_appended_partitions_inlinE
|
||||
/* For padding after appended partitions (and also after backup GPT)
|
||||
*/
|
||||
#define Libisofs_part_align_writeR yes
|
||||
#endif
|
||||
|
||||
#endif /* SYSTEM_AREA_H_ */
|
||||
|
|
536
libisofs/tree.c
536
libisofs/tree.c
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2011 Thomas Schmitt
|
||||
* Copyright (c) 2011 - 2022 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -23,6 +23,8 @@
|
|||
#include "builder.h"
|
||||
#include "messages.h"
|
||||
#include "tree.h"
|
||||
#include "util.h"
|
||||
#include "ecma119.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -42,11 +44,11 @@
|
|||
* parent, this functions fails with ISO_NODE_NAME_NOT_UNIQUE.
|
||||
* @param dir
|
||||
* place where to store a pointer to the newly created dir. No extra
|
||||
* ref is addded, so you will need to call iso_node_ref() if you really
|
||||
* ref is added, so you will need to call iso_node_ref() if you really
|
||||
* need it. You can pass NULL in this parameter if you don't need the
|
||||
* pointer.
|
||||
* @return
|
||||
* number of nodes in dir if succes, < 0 otherwise
|
||||
* number of nodes in dir if success, < 0 otherwise
|
||||
* Possible errors:
|
||||
* ISO_NULL_POINTER, if parent or name are NULL
|
||||
* ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists
|
||||
|
@ -86,7 +88,7 @@ int iso_tree_add_new_dir(IsoDir *parent, const char *name, IsoDir **dir)
|
|||
iso_node_set_hidden((IsoNode*)node, parent->node.hidden);
|
||||
|
||||
/* current time */
|
||||
now = time(NULL);
|
||||
iso_nowtime(&now, 0);
|
||||
iso_node_set_atime((IsoNode*)node, now);
|
||||
iso_node_set_ctime((IsoNode*)node, now);
|
||||
iso_node_set_mtime((IsoNode*)node, now);
|
||||
|
@ -99,6 +101,19 @@ int iso_tree_add_new_dir(IsoDir *parent, const char *name, IsoDir **dir)
|
|||
return iso_dir_insert(parent, (IsoNode*)node, pos, ISO_REPLACE_NEVER);
|
||||
}
|
||||
|
||||
int iso_image_add_new_dir(IsoImage *image, IsoDir *parent, const char *name,
|
||||
IsoDir **dir)
|
||||
{
|
||||
int ret;
|
||||
char *namept;
|
||||
|
||||
ret = iso_image_truncate_name(image, name, &namept, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = iso_tree_add_new_dir(parent, namept, dir);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new symlink to the directory tree. Permissions are set to 0777,
|
||||
* owner and hidden atts are taken from parent. You can modify any of them
|
||||
|
@ -113,7 +128,7 @@ int iso_tree_add_new_dir(IsoDir *parent, const char *name, IsoDir **dir)
|
|||
* destination of the link
|
||||
* @param link
|
||||
* place where to store a pointer to the newly created link. No extra
|
||||
* ref is addded, so you will need to call iso_node_ref() if you really
|
||||
* ref is added, so you will need to call iso_node_ref() if you really
|
||||
* need it. You can pass NULL in this parameter if you don't need the
|
||||
* pointer
|
||||
* @return
|
||||
|
@ -161,7 +176,7 @@ int iso_tree_add_new_symlink(IsoDir *parent, const char *name,
|
|||
iso_node_set_hidden((IsoNode*)node, parent->node.hidden);
|
||||
|
||||
/* current time */
|
||||
now = time(NULL);
|
||||
iso_nowtime(&now, 0);
|
||||
iso_node_set_atime((IsoNode*)node, now);
|
||||
iso_node_set_ctime((IsoNode*)node, now);
|
||||
iso_node_set_mtime((IsoNode*)node, now);
|
||||
|
@ -174,11 +189,25 @@ int iso_tree_add_new_symlink(IsoDir *parent, const char *name,
|
|||
return iso_dir_insert(parent, (IsoNode*)node, pos, ISO_REPLACE_NEVER);
|
||||
}
|
||||
|
||||
int iso_image_add_new_symlink(IsoImage *image, IsoDir *parent,
|
||||
const char *name, const char *dest,
|
||||
IsoSymlink **link)
|
||||
{
|
||||
int ret;
|
||||
char *namept;
|
||||
|
||||
ret = iso_image_truncate_name(image, name, &namept, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = iso_tree_add_new_symlink(parent, namept, dest, link);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new special file to the directory tree. As far as libisofs concerns,
|
||||
* an special file is a block device, a character device, a FIFO (named pipe)
|
||||
* or a socket. You can choose the specific kind of file you want to add
|
||||
* by setting mode propertly (see man 2 stat).
|
||||
* by setting mode properly (see man 2 stat).
|
||||
*
|
||||
* Note that special files are only written to image when Rock Ridge
|
||||
* extensions are enabled. Moreover, a special file is just a directory entry
|
||||
|
@ -201,7 +230,7 @@ int iso_tree_add_new_symlink(IsoDir *parent, const char *name,
|
|||
* device ID, equivalent to the st_rdev field in man 2 stat.
|
||||
* @param special
|
||||
* place where to store a pointer to the newly created special file. No
|
||||
* extra ref is addded, so you will need to call iso_node_ref() if you
|
||||
* extra ref is added, so you will need to call iso_node_ref() if you
|
||||
* really need it. You can pass NULL in this parameter if you don't need
|
||||
* the pointer.
|
||||
* @return
|
||||
|
@ -250,7 +279,7 @@ int iso_tree_add_new_special(IsoDir *parent, const char *name, mode_t mode,
|
|||
iso_node_set_hidden((IsoNode*)node, parent->node.hidden);
|
||||
|
||||
/* current time */
|
||||
now = time(NULL);
|
||||
iso_nowtime(&now, 0);
|
||||
iso_node_set_atime((IsoNode*)node, now);
|
||||
iso_node_set_ctime((IsoNode*)node, now);
|
||||
iso_node_set_mtime((IsoNode*)node, now);
|
||||
|
@ -263,6 +292,20 @@ int iso_tree_add_new_special(IsoDir *parent, const char *name, mode_t mode,
|
|||
return iso_dir_insert(parent, (IsoNode*)node, pos, ISO_REPLACE_NEVER);
|
||||
}
|
||||
|
||||
int iso_image_add_new_special(IsoImage *image, IsoDir *parent,
|
||||
const char *name, mode_t mode,
|
||||
dev_t dev, IsoSpecial **special)
|
||||
{
|
||||
int ret;
|
||||
char *namept;
|
||||
|
||||
ret = iso_image_truncate_name(image, name, &namept, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = iso_tree_add_new_special(parent, namept, mode, dev, special);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new regular file to the iso tree. Permissions are set to 0444,
|
||||
* owner and hidden atts are taken from parent. You can modify any of them
|
||||
|
@ -277,7 +320,7 @@ int iso_tree_add_new_special(IsoDir *parent, const char *name, mode_t mode,
|
|||
* IsoStream for the contents of the file
|
||||
* @param file
|
||||
* place where to store a pointer to the newly created file. No extra
|
||||
* ref is addded, so you will need to call iso_node_ref() if you really
|
||||
* ref is added, so you will need to call iso_node_ref() if you really
|
||||
* need it. You can pass NULL in this parameter if you don't need the
|
||||
* pointer
|
||||
* @return
|
||||
|
@ -325,7 +368,7 @@ int iso_tree_add_new_file(IsoDir *parent, const char *name, IsoStream *stream,
|
|||
iso_node_set_hidden((IsoNode*)node, parent->node.hidden);
|
||||
|
||||
/* current time */
|
||||
now = time(NULL);
|
||||
iso_nowtime(&now, 0);
|
||||
iso_node_set_atime((IsoNode*)node, now);
|
||||
iso_node_set_ctime((IsoNode*)node, now);
|
||||
iso_node_set_mtime((IsoNode*)node, now);
|
||||
|
@ -338,6 +381,19 @@ int iso_tree_add_new_file(IsoDir *parent, const char *name, IsoStream *stream,
|
|||
return iso_dir_insert(parent, (IsoNode*)node, pos, ISO_REPLACE_NEVER);
|
||||
}
|
||||
|
||||
int iso_image_add_new_file(IsoImage *image, IsoDir *parent, const char *name,
|
||||
IsoStream *stream, IsoFile **file)
|
||||
{
|
||||
int ret;
|
||||
char *namept;
|
||||
|
||||
ret = iso_image_truncate_name(image, name, &namept, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = iso_tree_add_new_file(parent, namept, stream, file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to follow or not symbolic links when added a file from a source
|
||||
* to IsoImage.
|
||||
|
@ -502,10 +558,10 @@ int iso_tree_add_node_builder(IsoImage *image, IsoDir *parent,
|
|||
int result;
|
||||
IsoNode *new;
|
||||
IsoNode **pos;
|
||||
char *name;
|
||||
char *name = NULL, *namept;
|
||||
|
||||
if (parent == NULL || src == NULL || builder == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
result = ISO_NULL_POINTER; goto ex;
|
||||
}
|
||||
if (node) {
|
||||
*node = NULL;
|
||||
|
@ -513,25 +569,31 @@ int iso_tree_add_node_builder(IsoImage *image, IsoDir *parent,
|
|||
|
||||
name = iso_file_source_get_name(src);
|
||||
|
||||
result = iso_image_truncate_name(image, name, &namept, 0);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
/* find place where to insert */
|
||||
result = iso_dir_exists(parent, name, &pos);
|
||||
free(name);
|
||||
result = iso_dir_exists(parent, namept, &pos);
|
||||
if (result) {
|
||||
/* a node with same name already exists */
|
||||
return ISO_NODE_NAME_NOT_UNIQUE;
|
||||
result = ISO_NODE_NAME_NOT_UNIQUE; goto ex;
|
||||
}
|
||||
|
||||
result = builder->create_node(builder, image, src, &new);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
result = builder->create_node(builder, image, src, namept, &new);
|
||||
if (result < 0)
|
||||
goto ex;
|
||||
|
||||
if (node) {
|
||||
*node = new;
|
||||
}
|
||||
|
||||
/* finally, add node to parent */
|
||||
return iso_dir_insert(parent, (IsoNode*)new, pos, ISO_REPLACE_NEVER);
|
||||
result = iso_dir_insert(parent, (IsoNode*)new, pos, ISO_REPLACE_NEVER);
|
||||
ex:
|
||||
if (name != NULL)
|
||||
free(name);
|
||||
return result;
|
||||
}
|
||||
|
||||
int iso_tree_add_node(IsoImage *image, IsoDir *parent, const char *path,
|
||||
|
@ -565,6 +627,7 @@ int iso_tree_add_new_node(IsoImage *image, IsoDir *parent, const char *name,
|
|||
IsoFileSource *file;
|
||||
IsoNode *new;
|
||||
IsoNode **pos;
|
||||
char *namept;
|
||||
|
||||
if (image == NULL || parent == NULL || name == NULL || path == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
|
@ -574,8 +637,12 @@ int iso_tree_add_new_node(IsoImage *image, IsoDir *parent, const char *name,
|
|||
*node = NULL;
|
||||
}
|
||||
|
||||
result = iso_image_truncate_name(image, name, &namept, 0);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
/* find place where to insert */
|
||||
result = iso_dir_exists(parent, name, &pos);
|
||||
result = iso_dir_exists(parent, namept, &pos);
|
||||
if (result) {
|
||||
/* a node with same name already exists */
|
||||
return ISO_NODE_NAME_NOT_UNIQUE;
|
||||
|
@ -587,7 +654,8 @@ int iso_tree_add_new_node(IsoImage *image, IsoDir *parent, const char *name,
|
|||
return result;
|
||||
}
|
||||
|
||||
result = image->builder->create_node(image->builder, image, file, &new);
|
||||
result = image->builder->create_node(image->builder, image, file,
|
||||
namept, &new);
|
||||
|
||||
/* free the file */
|
||||
iso_file_source_unref(file);
|
||||
|
@ -596,12 +664,6 @@ int iso_tree_add_new_node(IsoImage *image, IsoDir *parent, const char *name,
|
|||
return result;
|
||||
}
|
||||
|
||||
result = iso_node_set_name(new, name);
|
||||
if (result < 0) {
|
||||
iso_node_unref(new);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (node) {
|
||||
*node = new;
|
||||
}
|
||||
|
@ -616,12 +678,14 @@ int iso_tree_add_new_cut_out_node(IsoImage *image, IsoDir *parent,
|
|||
IsoNode **node)
|
||||
{
|
||||
int result;
|
||||
off_t src_size;
|
||||
struct stat info;
|
||||
IsoFilesystem *fs;
|
||||
IsoFileSource *src;
|
||||
IsoFile *new;
|
||||
IsoNode **pos;
|
||||
IsoStream *stream;
|
||||
char *namept;
|
||||
|
||||
if (image == NULL || parent == NULL || name == NULL || path == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
|
@ -631,8 +695,12 @@ int iso_tree_add_new_cut_out_node(IsoImage *image, IsoDir *parent,
|
|||
*node = NULL;
|
||||
}
|
||||
|
||||
result = iso_image_truncate_name(image, name, &namept, 0);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
/* find place where to insert */
|
||||
result = iso_dir_exists(parent, name, &pos);
|
||||
result = iso_dir_exists(parent, namept, &pos);
|
||||
if (result) {
|
||||
/* a node with same name already exists */
|
||||
return ISO_NODE_NAME_NOT_UNIQUE;
|
||||
|
@ -649,17 +717,22 @@ int iso_tree_add_new_cut_out_node(IsoImage *image, IsoDir *parent,
|
|||
iso_file_source_unref(src);
|
||||
return result;
|
||||
}
|
||||
if (!S_ISREG(info.st_mode)) {
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
|
||||
if (S_ISREG(info.st_mode)) {
|
||||
src_size = info.st_size;
|
||||
} else {
|
||||
src_size = iso_file_source_determine_capacity(src, offset + size, 3);
|
||||
if (src_size <= 0)
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
if (offset >= info.st_size) {
|
||||
if (offset >= src_size) {
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
|
||||
/* force regular file */
|
||||
result = image->builder->create_file(image->builder, image, src, &new);
|
||||
|
||||
/* free the file */
|
||||
/* Give up the newly acquired surplus reference to src */
|
||||
iso_file_source_unref(src);
|
||||
|
||||
if (result < 0) {
|
||||
|
@ -675,7 +748,7 @@ int iso_tree_add_new_cut_out_node(IsoImage *image, IsoDir *parent,
|
|||
iso_stream_unref(new->stream);
|
||||
new->stream = stream;
|
||||
|
||||
result = iso_node_set_name((IsoNode*)new, name);
|
||||
result = iso_node_set_name((IsoNode*)new, namept);
|
||||
if (result < 0) {
|
||||
iso_node_unref((IsoNode*)new);
|
||||
return result;
|
||||
|
@ -702,7 +775,7 @@ int check_excludes(IsoImage *image, const char *path)
|
|||
return 1;
|
||||
}
|
||||
} else {
|
||||
/* relative exclude, it is enought if a part of the path matches */
|
||||
/* relative exclude, it is enough if a part of the path matches */
|
||||
char *pos = (char*)path;
|
||||
while (pos != NULL) {
|
||||
pos++;
|
||||
|
@ -742,6 +815,176 @@ int check_special(IsoImage *image, mode_t mode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
void ascii_increment(char *name, int len, int pos, int rollover_carry)
|
||||
{
|
||||
int c;
|
||||
|
||||
again:;
|
||||
if (pos < 0 || pos >= len)
|
||||
pos = len - 1;
|
||||
c = name[pos];
|
||||
if (c >= '0' && c < '9') {
|
||||
c++;
|
||||
} else if (c == '9') {
|
||||
c = 'A';
|
||||
} else if (c >= 'A' && c < 'Z') {
|
||||
c++;
|
||||
} else if (c == 'Z') {
|
||||
c = '_';
|
||||
} else if (c == '_') {
|
||||
c = 'a';
|
||||
} else if (c >= 'a' && c < 'z') {
|
||||
c++;
|
||||
} else if (c == 'z') {
|
||||
c = '0';
|
||||
name[pos] = c;
|
||||
pos--;
|
||||
if (pos >= 0 || rollover_carry)
|
||||
goto again;
|
||||
return;
|
||||
} else {
|
||||
if (pos == len - 1 || name[pos + 1] == '.')
|
||||
c = '_'; /* Make first change less riddling */
|
||||
else
|
||||
c = '0'; /* But else use the full range of valid characters */
|
||||
}
|
||||
name[pos] = c;
|
||||
}
|
||||
|
||||
static
|
||||
int insert_underscores(char *name, int *len, int *at_pos, int count,
|
||||
char **new_name)
|
||||
{
|
||||
int ret;
|
||||
|
||||
LIBISO_ALLOC_MEM(*new_name, char, count + *len + 1);
|
||||
if (*at_pos > 0)
|
||||
memcpy(*new_name, name, *at_pos);
|
||||
if (count > 0)
|
||||
memset(*new_name + *at_pos, '_', count);
|
||||
if (*len > *at_pos)
|
||||
memcpy(*new_name + *at_pos + count, name + *at_pos, *len - *at_pos);
|
||||
(*new_name)[count + *len] = 0;
|
||||
*len += count;
|
||||
*at_pos += count;
|
||||
ret= ISO_SUCCESS;
|
||||
ex:;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int make_incrementable_name(char **name, char **unique_name, int *low_pos,
|
||||
int *rollover_carry, int *pre_check)
|
||||
{
|
||||
char *dpt, *npt;
|
||||
int first, len, ret;
|
||||
|
||||
/* The incrementable part of the file shall have at least 7 characters.
|
||||
There may be up to pow(2.0,32.0)*2048/33 = 266548273400 files.
|
||||
The set of increment result characters has 63 elements.
|
||||
pow(63.0,7.0) is nearly 15 times larger than 266548273400.
|
||||
*/
|
||||
static int min_incr = 7;
|
||||
|
||||
/* At most two suffixes of total length up to 12, like .tar.bz2,
|
||||
shall be preserved. The incrementable part will eventually be
|
||||
padded up.
|
||||
Incrementing begins before the last suffix in any case. But when this
|
||||
rolls over on short prefixes, then long last suffixes will get used
|
||||
as high characters of the incremental part. This is indicated by
|
||||
*rollover_carry which corresponds to the parameter of ascii_increment()
|
||||
with the same name.
|
||||
*/
|
||||
static int max_suffix = 12;
|
||||
|
||||
*rollover_carry = 0;
|
||||
*pre_check = 0;
|
||||
|
||||
len = strlen(*name);
|
||||
|
||||
/* Check if the part before the first dot is long enough.
|
||||
If not, then preserve the last two short suffixes.
|
||||
*/
|
||||
dpt = strchr(*name, '.');
|
||||
if (dpt != NULL)
|
||||
if ((dpt - *name) < min_incr)
|
||||
dpt = strrchr(*name, '.');
|
||||
if (dpt != NULL) {
|
||||
first= (dpt - *name);
|
||||
if (dpt > *name && len - first < max_suffix) {
|
||||
for(npt = dpt - 1; npt >= *name && *npt != '.'; npt--);
|
||||
if (npt >= *name) {
|
||||
if (len - (npt - *name) <= max_suffix) {
|
||||
first= (npt - *name);
|
||||
dpt = npt;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
first= len;
|
||||
if (first < min_incr && (len - first) <= max_suffix) {
|
||||
ret = insert_underscores(*name, &len, &first, min_incr - first,
|
||||
unique_name);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
*pre_check = 1; /* It might now already be unique */
|
||||
|
||||
} else if (len < 64) {
|
||||
/* Insert an underscore to preserve the original name at least for the
|
||||
first few increments
|
||||
*/
|
||||
ret = insert_underscores(*name, &len, &first, 1, unique_name);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
*pre_check = 1;
|
||||
|
||||
} else {
|
||||
LIBISO_ALLOC_MEM(*unique_name, char, len + 1);
|
||||
memcpy(*unique_name, *name, len);
|
||||
if (first < min_incr)
|
||||
*rollover_carry = 1; /* Do not get caged before the dots */
|
||||
}
|
||||
(*unique_name)[len] = 0;
|
||||
*low_pos = first - 1;
|
||||
ret = 1;
|
||||
ex:;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static
|
||||
int make_really_unique_name(IsoDir *parent, char **name, char **unique_name,
|
||||
IsoNode ***pos, int flag)
|
||||
{
|
||||
int ret, rollover_carry = 0, pre_check = 0, ascii_idx = -1, len;
|
||||
|
||||
ret = make_incrementable_name(name, unique_name, &ascii_idx,
|
||||
&rollover_carry, &pre_check);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
len = strlen(*unique_name);
|
||||
while (1) {
|
||||
if (!pre_check)
|
||||
ascii_increment(*unique_name, len, ascii_idx, !!rollover_carry);
|
||||
else
|
||||
pre_check = 0;
|
||||
ret = iso_dir_exists(parent, *unique_name, pos);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
if (ret == 0)
|
||||
break;
|
||||
}
|
||||
*name = *unique_name;
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
if (ret < 0) {
|
||||
LIBISO_FREE_MEM(*unique_name);
|
||||
*unique_name = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively add a given directory to the image tree.
|
||||
*
|
||||
|
@ -750,12 +993,12 @@ int check_special(IsoImage *image, mode_t mode)
|
|||
*/
|
||||
int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir)
|
||||
{
|
||||
int ret;
|
||||
int ret, dir_is_open = 0;
|
||||
IsoNodeBuilder *builder;
|
||||
IsoFileSource *file;
|
||||
IsoNode **pos;
|
||||
struct stat info;
|
||||
char *name, *path;
|
||||
char *name, *path, *allocated_name = NULL;
|
||||
IsoNode *new;
|
||||
enum iso_replace_mode replace;
|
||||
|
||||
|
@ -771,8 +1014,9 @@ int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir)
|
|||
ret = iso_msg_submit(image->id, ISO_NULL_POINTER, ret,
|
||||
"Can't open dir. NULL pointer caught as dir name");
|
||||
}
|
||||
return ret;
|
||||
goto ex;
|
||||
}
|
||||
dir_is_open = 1;
|
||||
|
||||
builder = image->builder;
|
||||
|
||||
|
@ -785,15 +1029,16 @@ int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir)
|
|||
if (ret < 0) {
|
||||
/* error reading dir */
|
||||
ret = iso_msg_submit(image->id, ret, ret, "Error reading dir");
|
||||
goto ex;
|
||||
}
|
||||
break;
|
||||
break; /* End of directory */
|
||||
}
|
||||
|
||||
path = iso_file_source_get_path(file);
|
||||
if (path == NULL) {
|
||||
ret = iso_msg_submit(image->id, ISO_NULL_POINTER, ret,
|
||||
"NULL pointer caught as file path");
|
||||
return ret;
|
||||
goto ex;
|
||||
}
|
||||
name = strrchr(path, '/') + 1;
|
||||
|
||||
|
@ -807,6 +1052,17 @@ int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir)
|
|||
"Error when adding file %s", path);
|
||||
goto dir_rec_continue;
|
||||
}
|
||||
|
||||
if (image->do_deeper_tree_inspection) {
|
||||
if (image->tree_loaded == 0 && image->rr_loaded == 0) {
|
||||
iso_image_assess_ecma119_name(image, &info, path, name);
|
||||
} else if (image->tree_loaded == 1) {
|
||||
iso_image_assess_joliet_name(image, &info, path, name);
|
||||
}
|
||||
if (info.st_size > MAX_ISO_FILE_SECTION_SIZE &&
|
||||
image->tree_compliance != NULL)
|
||||
image->tree_compliance->iso_level = 3;
|
||||
}
|
||||
|
||||
if (check_excludes(image, path)) {
|
||||
iso_msg_debug(image->id, "Skipping excluded file %s", path);
|
||||
|
@ -827,19 +1083,25 @@ int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir)
|
|||
|
||||
/* find place where to insert */
|
||||
ret = iso_dir_exists(parent, name, &pos);
|
||||
/* TODO
|
||||
* if (ret && replace == ISO_REPLACE_ASK) {
|
||||
* replace = /....
|
||||
* }
|
||||
*/
|
||||
|
||||
/* chek if we must insert or not */
|
||||
/* TODO check for other replace behavior */
|
||||
if (ret && (replace == ISO_REPLACE_NEVER)) {
|
||||
/* skip file */
|
||||
goto dir_rec_continue;
|
||||
if (ret) {
|
||||
/* Resolve name collision
|
||||
e.g. caused by fs_image.c:make_hopefully_unique_name()
|
||||
*/
|
||||
LIBISO_FREE_MEM(allocated_name); allocated_name = NULL;
|
||||
ret = make_really_unique_name(parent, &name, &allocated_name, &pos,
|
||||
0);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
image->collision_warnings++;
|
||||
if (image->collision_warnings < ISO_IMPORT_COLL_WARN_MAX) {
|
||||
ret = iso_msg_submit(image->id, ISO_IMPORT_COLLISION, 0,
|
||||
"File name collision resolved with %s . Now: %s",
|
||||
path, name);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* if we are here we must insert. Give user a chance for cancel */
|
||||
if (image->report) {
|
||||
int r = image->report(image, file);
|
||||
|
@ -848,7 +1110,7 @@ int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir)
|
|||
goto dir_rec_continue;
|
||||
}
|
||||
}
|
||||
ret = builder->create_node(builder, image, file, &new);
|
||||
ret = builder->create_node(builder, image, file, name, &new);
|
||||
if (ret < 0) {
|
||||
ret = iso_msg_submit(image->id, ISO_FILE_CANT_ADD, ret,
|
||||
"Error when adding file %s", path);
|
||||
|
@ -884,14 +1146,17 @@ dir_rec_continue:;
|
|||
/* check for error severity to decide what to do */
|
||||
if (ret < 0) {
|
||||
ret = iso_msg_submit(image->id, ret, 0, NULL);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
} /* while */
|
||||
|
||||
iso_file_source_close(dir);
|
||||
return ret < 0 ? ret : ISO_SUCCESS;
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
if (dir_is_open)
|
||||
iso_file_source_close(dir);
|
||||
LIBISO_FREE_MEM(allocated_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iso_tree_add_dir_rec(IsoImage *image, IsoDir *parent, const char *dir)
|
||||
|
@ -927,7 +1192,10 @@ int iso_tree_add_dir_rec(IsoImage *image, IsoDir *parent, const char *dir)
|
|||
return result;
|
||||
}
|
||||
|
||||
int iso_tree_path_to_node(IsoImage *image, const char *path, IsoNode **node)
|
||||
/* @param flag bit0= truncate according to image truncate mode and length
|
||||
*/
|
||||
int iso_tree_path_to_node_flag(IsoImage *image, const char *path,
|
||||
IsoNode **node, int flag)
|
||||
{
|
||||
int result;
|
||||
IsoNode *n;
|
||||
|
@ -949,6 +1217,8 @@ int iso_tree_path_to_node(IsoImage *image, const char *path, IsoNode **node)
|
|||
}
|
||||
|
||||
ptr = strdup(path);
|
||||
if (ptr == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
result = 0;
|
||||
|
||||
/* get the first component of the path */
|
||||
|
@ -961,7 +1231,12 @@ int iso_tree_path_to_node(IsoImage *image, const char *path, IsoNode **node)
|
|||
}
|
||||
dir = (IsoDir *)n;
|
||||
|
||||
result = iso_dir_get_node(dir, component, &n);
|
||||
if ((flag & 1) && image->truncate_mode == 1) {
|
||||
result = iso_dir_get_node_trunc(dir, image->truncate_length,
|
||||
component, &n);
|
||||
} else {
|
||||
result = iso_dir_get_node(dir, component, &n);
|
||||
}
|
||||
if (result != 1) {
|
||||
n = NULL;
|
||||
break;
|
||||
|
@ -977,6 +1252,16 @@ int iso_tree_path_to_node(IsoImage *image, const char *path, IsoNode **node)
|
|||
return result;
|
||||
}
|
||||
|
||||
int iso_tree_path_to_node(IsoImage *image, const char *path, IsoNode **node)
|
||||
{
|
||||
return iso_tree_path_to_node_flag(image, path, node, 0);
|
||||
}
|
||||
|
||||
int iso_image_path_to_node(IsoImage *image, const char *path, IsoNode **node)
|
||||
{
|
||||
return iso_tree_path_to_node_flag(image, path, node, 1);
|
||||
}
|
||||
|
||||
char *iso_tree_get_node_path(IsoNode *node)
|
||||
{
|
||||
char *path = NULL, *parent_path = NULL;
|
||||
|
@ -1008,6 +1293,67 @@ ex:;
|
|||
return path;
|
||||
}
|
||||
|
||||
/* Note: No reference is taken to the found node.
|
||||
Warning: Do not submit next_above uninitialized.
|
||||
Submit NULL if next_above is not of interest.
|
||||
@param flag bit0= recursion
|
||||
*/
|
||||
int iso_tree_get_node_of_block(IsoImage *image, IsoDir *dir, uint32_t block,
|
||||
IsoNode **found, uint32_t *next_above, int flag)
|
||||
{
|
||||
int ret, section_count, i;
|
||||
IsoDirIter *iter = NULL;
|
||||
IsoNode *node;
|
||||
IsoDir *subdir;
|
||||
IsoFile *file;
|
||||
struct iso_file_section *sections = NULL;
|
||||
uint32_t na = 0;
|
||||
|
||||
if (dir == NULL)
|
||||
dir = image->root;
|
||||
|
||||
ret = iso_dir_get_children(dir, &iter);
|
||||
while (iso_dir_iter_next(iter, &node) == 1 ) {
|
||||
|
||||
if (ISO_NODE_IS_FILE(node)) {
|
||||
file = (IsoFile *) node;
|
||||
ret = iso_file_get_old_image_sections(file, §ion_count,
|
||||
§ions, 0);
|
||||
if (ret <= 0)
|
||||
continue;
|
||||
for (i = 0; i < section_count; i++) {
|
||||
if (sections[i].block <= block &&
|
||||
block - sections[i].block <
|
||||
(((off_t) sections[i].size) + 2047) / 2048) {
|
||||
*found = node;
|
||||
ret = 1; goto ex;
|
||||
}
|
||||
if ((na == 0 || sections[i].block < na) &&
|
||||
sections[i].block > block)
|
||||
na = sections[i].block;
|
||||
}
|
||||
free(sections); sections = NULL;
|
||||
} else if (ISO_NODE_IS_DIR(node)) {
|
||||
subdir = (IsoDir *) node;
|
||||
ret = iso_tree_get_node_of_block(image, subdir, block, found, &na,
|
||||
1);
|
||||
if (ret != 0)
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
if (next_above != NULL && (na > 0 || !(flag & 1)))
|
||||
if (*next_above == 0 || *next_above > na || !(flag & 1))
|
||||
*next_above = na;
|
||||
ret = 0;
|
||||
ex:
|
||||
if (sections != NULL)
|
||||
free(sections);
|
||||
if (iter != NULL)
|
||||
iso_dir_iter_free(iter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------- tree cloning ------------------------------ */
|
||||
|
||||
static
|
||||
|
@ -1109,6 +1455,8 @@ int iso_tree_clone_file(IsoFile *old_file,
|
|||
if (ret < 0)
|
||||
goto ex;
|
||||
new_stream = NULL; /* now owned by new_file */
|
||||
new_file->from_old_session = old_file->from_old_session;
|
||||
new_file->explicit_weight = old_file->explicit_weight;
|
||||
new_file->sort_weight = old_file->sort_weight;
|
||||
*new_node = (IsoNode *) new_file;
|
||||
ret = ISO_SUCCESS;
|
||||
|
@ -1159,18 +1507,36 @@ int iso_tree_clone_special(IsoSpecial *node,
|
|||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
/* API */
|
||||
int iso_tree_clone(IsoNode *node,
|
||||
IsoDir *new_parent, char *new_name, IsoNode **new_node,
|
||||
int flag)
|
||||
|
||||
/* @param flag bit0= Merge directories rather than ISO_NODE_NAME_NOT_UNIQUE.
|
||||
bit1= issue warning in case of truncation
|
||||
*/
|
||||
int iso_tree_clone_trunc(IsoNode *node, IsoDir *new_parent,
|
||||
char *new_name_in, IsoNode **new_node,
|
||||
int truncate_length, int flag)
|
||||
{
|
||||
int ret = ISO_SUCCESS;
|
||||
char *new_name, *trunc = NULL;
|
||||
|
||||
*new_node = NULL;
|
||||
new_name = new_name_in;
|
||||
if (truncate_length >= 64 && (int) strlen(new_name) > truncate_length) {
|
||||
trunc = strdup(new_name);
|
||||
if (trunc == 0) {
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
goto ex;
|
||||
}
|
||||
ret = iso_truncate_rr_name(1, truncate_length, trunc, !(flag & 2));
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
new_name = trunc;
|
||||
}
|
||||
if (iso_dir_get_node(new_parent, new_name, new_node) == 1) {
|
||||
if (! (node->type == LIBISO_DIR && (*new_node)->type == LIBISO_DIR &&
|
||||
(flag & 1))) {
|
||||
*new_node = NULL;
|
||||
return ISO_NODE_NAME_NOT_UNIQUE;
|
||||
ret = ISO_NODE_NAME_NOT_UNIQUE;
|
||||
goto ex;
|
||||
}
|
||||
} else
|
||||
flag &= ~1;
|
||||
|
@ -1191,10 +1557,42 @@ int iso_tree_clone(IsoNode *node,
|
|||
ret = ISO_SUCCESS; /* API says they are silently ignored */
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (flag & 1)
|
||||
return 2; /* merged two directories, *new_node is not new */
|
||||
goto ex;
|
||||
if (flag & 1) {
|
||||
ret = 2; /* merged two directories, *new_node is not new */
|
||||
goto ex;
|
||||
}
|
||||
ret = iso_tree_copy_node_attr(node, *new_node, 0);
|
||||
|
||||
ex:;
|
||||
if (trunc != NULL)
|
||||
free(trunc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_tree_clone(IsoNode *node,
|
||||
IsoDir *new_parent, char *new_name, IsoNode **new_node,
|
||||
int flag)
|
||||
{
|
||||
return iso_tree_clone_trunc(node, new_parent, new_name, new_node, 0,
|
||||
flag & 1);
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_image_tree_clone(IsoImage *image, IsoNode *node, IsoDir *new_parent,
|
||||
char *new_name, IsoNode **new_node, int flag)
|
||||
{
|
||||
int length, ret;
|
||||
|
||||
if (image->truncate_mode == 0)
|
||||
length = 0;
|
||||
else
|
||||
length = image->truncate_length;
|
||||
ret = iso_tree_clone_trunc(node, new_parent, new_name, new_node, length,
|
||||
flag & 3);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,4 +19,9 @@
|
|||
*/
|
||||
int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir);
|
||||
|
||||
|
||||
int iso_tree_get_node_of_block(IsoImage *image, IsoDir *dir, uint32_t block,
|
||||
IsoNode **found, uint32_t *next_above, int flag);
|
||||
|
||||
|
||||
#endif /*LIBISO_IMAGE_TREE_H_*/
|
||||
|
|
462
libisofs/util.c
462
libisofs/util.c
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2007 Mario Danic
|
||||
* Copyright (c) 2009 - 2012 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2022 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -17,7 +17,7 @@
|
|||
#include "libisofs.h"
|
||||
#include "messages.h"
|
||||
#include "joliet.h"
|
||||
#include "../version.h"
|
||||
#include "node.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
@ -241,8 +241,8 @@ ex:;
|
|||
return retval;
|
||||
}
|
||||
|
||||
int strnconv(const char *str, const char *icharset, const char *ocharset,
|
||||
size_t len, char **output)
|
||||
int strnconvl(const char *str, const char *icharset, const char *ocharset,
|
||||
size_t len, char **output, size_t *out_len)
|
||||
{
|
||||
size_t inbytes;
|
||||
size_t outbytes;
|
||||
|
@ -278,7 +278,8 @@ int strnconv(const char *str, const char *icharset, const char *ocharset,
|
|||
*ret = '\0';
|
||||
iso_iconv_close(&conv, 0);
|
||||
|
||||
*output = malloc(ret - out + 1);
|
||||
*out_len = ret - out;
|
||||
*output = malloc(*out_len + 1);
|
||||
if (*output == NULL) {
|
||||
retval = ISO_OUT_OF_MEM;
|
||||
goto ex;
|
||||
|
@ -291,6 +292,15 @@ ex:;
|
|||
return retval;
|
||||
}
|
||||
|
||||
int strnconv(const char *str, const char *icharset, const char *ocharset,
|
||||
size_t len, char **output)
|
||||
{
|
||||
size_t l;
|
||||
|
||||
return strnconvl(str, icharset, ocharset, len, output, &l);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a str in a specified codeset to WCHAR_T.
|
||||
* The result must be free() when no more needed
|
||||
|
@ -425,6 +435,7 @@ int str2ascii(const char *icharset, const char *input, char **output)
|
|||
|
||||
ret_ = malloc(numchars + 1);
|
||||
if (ret_ == NULL) {
|
||||
free(wsrc_);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
outbytes = numchars;
|
||||
|
@ -434,7 +445,9 @@ int str2ascii(const char *icharset, const char *input, char **output)
|
|||
conv_ret = iso_iconv_open(&conv, "ASCII", "WCHAR_T", 0);
|
||||
if (conv_ret <= 0) {
|
||||
free(wsrc_);
|
||||
wsrc_ = NULL;
|
||||
free(ret_);
|
||||
ret = ret_ = NULL;
|
||||
}
|
||||
} else if (result != (int) ISO_CHARSET_CONV_ERROR)
|
||||
return result;
|
||||
|
@ -583,8 +596,10 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
|
|||
loop_limit = inbytes + 3;
|
||||
|
||||
ret_ = malloc((numchars+1) * sizeof(uint16_t));
|
||||
if (ret_ == NULL)
|
||||
if (ret_ == NULL) {
|
||||
free(wsrc_);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
outbytes = numchars * sizeof(uint16_t);
|
||||
ret = ret_;
|
||||
|
||||
|
@ -592,7 +607,9 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
|
|||
conv_ret = iso_iconv_open(&conv, "UCS-2BE", "WCHAR_T", 0);
|
||||
if (conv_ret <= 0) {
|
||||
free(wsrc_);
|
||||
wsrc_ = NULL;
|
||||
free(ret_);
|
||||
ret = ret_ = NULL;
|
||||
}
|
||||
} else if (result != (int) ISO_CHARSET_CONV_ERROR)
|
||||
return result;
|
||||
|
@ -667,18 +684,137 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
|
|||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static int valid_d_char(char c)
|
||||
int str2utf16be(const char *icharset, const char *input, uint16_t **output)
|
||||
{
|
||||
int result;
|
||||
wchar_t *wsrc_ = NULL;
|
||||
char *src;
|
||||
char *ret = NULL;
|
||||
char *ret_ = NULL;
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret = 0;
|
||||
int direct_conv = 0;
|
||||
size_t loop_counter = 0, loop_limit = 3;
|
||||
size_t numchars;
|
||||
size_t outbytes;
|
||||
size_t inbytes;
|
||||
size_t n;
|
||||
|
||||
if (icharset == NULL || input == NULL || output == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
|
||||
/*
|
||||
Try the direct conversion.
|
||||
*/
|
||||
conv_ret = iso_iconv_open(&conv, "UTF-16BE", (char *) icharset, 0);
|
||||
if (conv_ret > 0) {
|
||||
direct_conv = 1;
|
||||
src = (char *) input;
|
||||
inbytes = strlen(input);
|
||||
loop_limit = inbytes + 3;
|
||||
outbytes = (2 * inbytes + 1) * sizeof(uint16_t);
|
||||
ret_ = malloc(outbytes);
|
||||
if (ret_ == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
ret = ret_;
|
||||
} else {
|
||||
/* Try via intermediate character set WCHAR_T.
|
||||
*/
|
||||
result = str2wchar(icharset, input, &wsrc_);
|
||||
if (result == (int) ISO_SUCCESS) {
|
||||
src = (char *)wsrc_;
|
||||
numchars = wcslen(wsrc_);
|
||||
|
||||
inbytes = numchars * sizeof(wchar_t);
|
||||
loop_limit = inbytes + 3;
|
||||
|
||||
ret_ = malloc((2 * numchars+1) * sizeof(uint16_t));
|
||||
if (ret_ == NULL) {
|
||||
free(wsrc_);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
outbytes = 2 * numchars * sizeof(uint16_t);
|
||||
ret = ret_;
|
||||
|
||||
/* initialize iconv */
|
||||
conv_ret = iso_iconv_open(&conv, "UTF-16BE", "WCHAR_T", 0);
|
||||
if (conv_ret <= 0) {
|
||||
free(wsrc_);
|
||||
free(ret_);
|
||||
}
|
||||
} else if (result != (int) ISO_CHARSET_CONV_ERROR)
|
||||
return result;
|
||||
}
|
||||
|
||||
if (conv_ret <= 0) {
|
||||
return ISO_CHARSET_CONV_ERROR;
|
||||
}
|
||||
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
while (n == (size_t) -1) {
|
||||
/* The destination buffer is too small. Stops here. */
|
||||
if (errno == E2BIG)
|
||||
break;
|
||||
|
||||
/* An incomplete multi bytes sequence was found. We
|
||||
* can't do anything here. That's quite unlikely. */
|
||||
if (errno == EINVAL)
|
||||
break;
|
||||
|
||||
/* The last possible error is an invalid multi bytes
|
||||
* sequence. Just replace the character with a "_".
|
||||
* Probably the character doesn't exist in UCS */
|
||||
set_ucsbe((uint16_t*) ret, '_');
|
||||
ret += sizeof(uint16_t);
|
||||
outbytes -= sizeof(uint16_t);
|
||||
|
||||
if (!outbytes)
|
||||
break;
|
||||
|
||||
/* There was an error with one character but some other remain
|
||||
* to be converted. That's probably a multibyte character.
|
||||
* See above comment. */
|
||||
if (direct_conv) {
|
||||
src++;
|
||||
inbytes--;
|
||||
} else {
|
||||
src += sizeof(wchar_t);
|
||||
inbytes -= sizeof(wchar_t);
|
||||
}
|
||||
|
||||
if (!inbytes)
|
||||
break;
|
||||
|
||||
/* Just to appease my remorse about unclear loop ends */
|
||||
loop_counter++;
|
||||
if (loop_counter > loop_limit)
|
||||
break;
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
}
|
||||
iso_iconv_close(&conv, 0);
|
||||
|
||||
/* close the UTF-16 string */
|
||||
set_ucsbe((uint16_t*) ret, '\0');
|
||||
if (wsrc_ != NULL)
|
||||
free(wsrc_);
|
||||
|
||||
*output = (uint16_t*)ret_;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int valid_d_char(char c)
|
||||
{
|
||||
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c == '_');
|
||||
}
|
||||
|
||||
static int valid_a_char(char c)
|
||||
int valid_a_char(char c)
|
||||
{
|
||||
return (c >= ' ' && c <= '"') || (c >= '%' && c <= '?') ||
|
||||
(c >= 'A' && c <= 'Z') || (c == '_');
|
||||
}
|
||||
|
||||
static int valid_j_char(uint16_t c)
|
||||
int valid_j_char(uint16_t c)
|
||||
{
|
||||
return cmp_ucsbe(&c, ' ') != -1 && cmp_ucsbe(&c, '*') && cmp_ucsbe(&c, '/')
|
||||
&& cmp_ucsbe(&c, ':') && cmp_ucsbe(&c, ';') && cmp_ucsbe(&c, '?')
|
||||
|
@ -1080,7 +1216,7 @@ uint16_t *iso_j_file_id(const uint16_t *src, int flag)
|
|||
{
|
||||
uint16_t *dot, *retval = NULL;
|
||||
size_t lname, lext, lnname, lnext, pos, i, maxchar = 64;
|
||||
uint16_t *dest = NULL;
|
||||
uint16_t *dest = NULL, c;
|
||||
|
||||
LIBISO_ALLOC_MEM_VOID(dest, uint16_t, LIBISO_JOLIET_NAME_MAX);
|
||||
/* was: 66 = 64 (name + ext) + 1 (.) + 1 (\0) */
|
||||
|
@ -1120,7 +1256,7 @@ uint16_t *iso_j_file_id(const uint16_t *src, int flag)
|
|||
|
||||
/* Convert up to lnname characters of the filename. */
|
||||
for (i = 0; i < lnname; i++) {
|
||||
uint16_t c = src[i];
|
||||
c = src[i];
|
||||
if (valid_j_char(c)) {
|
||||
dest[pos++] = c;
|
||||
} else {
|
||||
|
@ -1128,6 +1264,8 @@ uint16_t *iso_j_file_id(const uint16_t *src, int flag)
|
|||
pos++;
|
||||
}
|
||||
}
|
||||
if (pos > 0)
|
||||
iso_handle_split_utf16(dest + (pos - 1));
|
||||
|
||||
if ((flag & 1) && lnext <= 0)
|
||||
goto is_done;
|
||||
|
@ -1145,6 +1283,7 @@ uint16_t *iso_j_file_id(const uint16_t *src, int flag)
|
|||
pos++;
|
||||
}
|
||||
}
|
||||
iso_handle_split_utf16(dest + (pos - 1));
|
||||
|
||||
is_done:;
|
||||
set_ucsbe(dest + pos, '\0');
|
||||
|
@ -1181,6 +1320,7 @@ uint16_t *iso_j_dir_id(const uint16_t *src, int flag)
|
|||
set_ucsbe(dest + i, '_');
|
||||
}
|
||||
}
|
||||
iso_handle_split_utf16(dest + (len - 1));
|
||||
set_ucsbe(dest + len, '\0');
|
||||
retval = ucsdup(dest);
|
||||
ex:
|
||||
|
@ -1262,6 +1402,8 @@ uint16_t *ucsncpy(uint16_t *dest, const uint16_t *src, size_t n)
|
|||
{
|
||||
n = MIN(n, ucslen(src) + 1);
|
||||
memcpy(dest, src, n*2);
|
||||
if (n >= 2)
|
||||
iso_handle_split_utf16(dest + (n - 2));
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
@ -1341,6 +1483,14 @@ void iso_lsb(uint8_t *buf, uint32_t num, int bytes)
|
|||
buf[i] = (num >> (8 * i)) & 0xff;
|
||||
}
|
||||
|
||||
void iso_lsb64(uint8_t *buf, uint64_t num)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; ++i)
|
||||
buf[i] = (num >> (8 * i)) & 0xff;
|
||||
}
|
||||
|
||||
void iso_msb(uint8_t *buf, uint32_t num, int bytes)
|
||||
{
|
||||
int i;
|
||||
|
@ -1401,6 +1551,26 @@ uint32_t iso_read_bb(const uint8_t *buf, int bytes, int *error)
|
|||
return v1;
|
||||
}
|
||||
|
||||
uint64_t iso_read_lsb64(const uint8_t *buf)
|
||||
{
|
||||
int i;
|
||||
uint64_t ret = 0;
|
||||
|
||||
for (i=0; i < 8; i++)
|
||||
ret += ((uint64_t) buf[i]) << (i * 8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t iso_read_msb64(const uint8_t *buf)
|
||||
{
|
||||
int i;
|
||||
uint64_t ret = 0;
|
||||
|
||||
for (i=0; i < 8; i++)
|
||||
ret += ((uint64_t) buf[7 - i]) << (i * 8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iso_datetime_7(unsigned char *buf, time_t t, int always_gmt)
|
||||
{
|
||||
static int tzsetup = 0;
|
||||
|
@ -1421,14 +1591,36 @@ void iso_datetime_7(unsigned char *buf, time_t t, int always_gmt)
|
|||
#else
|
||||
if (tm.tm_isdst < 0)
|
||||
tm.tm_isdst = 0;
|
||||
tzoffset = ( - timezone / 60 / 15 ) + 4 * tm.tm_isdst;
|
||||
#ifndef Libburnia_timezonE
|
||||
#define Libburnia_timezonE timezone
|
||||
#endif
|
||||
#if Libburnia_timezonE == 0
|
||||
always_gmt = 1;
|
||||
#endif
|
||||
tzoffset = ( - Libburnia_timezonE / 60 / 15 ) + 4 * tm.tm_isdst;
|
||||
#endif /* ! HAVE_TM_GMTOFF */
|
||||
|
||||
if (tzoffset > 52 || tzoffset < -48 || always_gmt) {
|
||||
/* absurd timezone offset, represent time in GMT */
|
||||
gmtime_r(&t, &tm);
|
||||
tzoffset = 0;
|
||||
}
|
||||
|
||||
if (tm.tm_year < 0) {
|
||||
tm.tm_year = 0;
|
||||
tm.tm_mon = 0;
|
||||
tm.tm_mday = 1;
|
||||
tm.tm_hour = 0;
|
||||
tm.tm_min = 0;
|
||||
tm.tm_sec = 0;
|
||||
} else if (tm.tm_year > 255) {
|
||||
tm.tm_year = 255;
|
||||
tm.tm_mon = 11;
|
||||
tm.tm_mday = 31;
|
||||
tm.tm_hour = 23;
|
||||
tm.tm_min = 59;
|
||||
tm.tm_sec = 59;
|
||||
}
|
||||
buf[0] = tm.tm_year;
|
||||
buf[1] = tm.tm_mon + 1;
|
||||
buf[2] = tm.tm_mday;
|
||||
|
@ -1467,8 +1659,14 @@ void iso_datetime_17(unsigned char *buf, time_t t, int always_gmt)
|
|||
#else
|
||||
if (tm.tm_isdst < 0)
|
||||
tm.tm_isdst = 0;
|
||||
tzoffset = ( - timezone / 60 / 15 ) + 4 * tm.tm_isdst;
|
||||
#ifndef Libburnia_timezonE
|
||||
#define Libburnia_timezonE timezone
|
||||
#endif
|
||||
#if Libburnia_timezonE == 0
|
||||
always_gmt = 1;
|
||||
#endif
|
||||
tzoffset = ( - Libburnia_timezonE / 60 / 15 ) + 4 * tm.tm_isdst;
|
||||
#endif /* ! HAVE_TM_GMTOFF */
|
||||
|
||||
if (tzoffset > 52 || tzoffset < -48 || always_gmt) {
|
||||
/* absurd timezone offset, represent time in GMT */
|
||||
|
@ -1476,12 +1674,18 @@ void iso_datetime_17(unsigned char *buf, time_t t, int always_gmt)
|
|||
tzoffset = 0;
|
||||
}
|
||||
|
||||
sprintf((char*)&buf[0], "%04d", tm.tm_year + 1900);
|
||||
sprintf((char*)&buf[4], "%02d", tm.tm_mon + 1);
|
||||
sprintf((char*)&buf[6], "%02d", tm.tm_mday);
|
||||
sprintf((char*)&buf[8], "%02d", tm.tm_hour);
|
||||
sprintf((char*)&buf[10], "%02d", tm.tm_min);
|
||||
sprintf((char*)&buf[12], "%02d", MIN(59, tm.tm_sec));
|
||||
if (tm.tm_year <= -1900) {
|
||||
strcpy((char *) buf, "00010101000000");
|
||||
} else if (tm.tm_year >= 8100) {
|
||||
strcpy((char *) buf, "99991231235959");
|
||||
} else {
|
||||
sprintf((char*)&buf[0], "%04d", tm.tm_year + 1900);
|
||||
sprintf((char*)&buf[4], "%02d", tm.tm_mon + 1);
|
||||
sprintf((char*)&buf[6], "%02d", tm.tm_mday);
|
||||
sprintf((char*)&buf[8], "%02d", tm.tm_hour);
|
||||
sprintf((char*)&buf[10], "%02d", tm.tm_min);
|
||||
sprintf((char*)&buf[12], "%02d", MIN(59, tm.tm_sec));
|
||||
}
|
||||
memcpy(&buf[14], "00", 2);
|
||||
buf[16] = tzoffset;
|
||||
|
||||
|
@ -1629,6 +1833,7 @@ time_t iso_datetime_read_7(const uint8_t *buf)
|
|||
tm.tm_hour = buf[3];
|
||||
tm.tm_min = buf[4];
|
||||
tm.tm_sec = buf[5];
|
||||
tm.tm_isdst = 0;
|
||||
|
||||
return timegm(&tm) - ((int8_t)buf[6]) * 60 * 15;
|
||||
}
|
||||
|
@ -1645,8 +1850,9 @@ time_t iso_datetime_read_17(const uint8_t *buf)
|
|||
sscanf((char*)&buf[12], "%2d", &tm.tm_sec);
|
||||
tm.tm_year -= 1900;
|
||||
tm.tm_mon -= 1;
|
||||
tm.tm_isdst = 0;
|
||||
|
||||
return timegm(&tm) - ((int8_t)buf[6]) * 60 * 15;
|
||||
return timegm(&tm) - ((int8_t)buf[16]) * 60 * 15;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1766,7 +1972,7 @@ char *ucs2str(const char *buf, size_t len)
|
|||
|
||||
outbytes = (inbytes+1) * MB_LEN_MAX;
|
||||
|
||||
/* ensure enought space */
|
||||
/* ensure enough space */
|
||||
out = calloc(outbytes, 1);
|
||||
if (out == NULL)
|
||||
return NULL;
|
||||
|
@ -1801,16 +2007,25 @@ ex:;
|
|||
|
||||
void iso_lib_version(int *major, int *minor, int *micro)
|
||||
{
|
||||
|
||||
*major = iso_lib_header_version_major;
|
||||
*minor = iso_lib_header_version_minor;
|
||||
*micro = iso_lib_header_version_micro;
|
||||
|
||||
/* No more: values from version.h generated from version.h.in and
|
||||
macro values defined in configure.ac
|
||||
|
||||
*major = LIBISOFS_MAJOR_VERSION;
|
||||
*minor = LIBISOFS_MINOR_VERSION;
|
||||
*micro = LIBISOFS_MICRO_VERSION;
|
||||
*/
|
||||
}
|
||||
|
||||
int iso_lib_is_compatible(int major, int minor, int micro)
|
||||
{
|
||||
int cmajor, cminor, cmicro;
|
||||
|
||||
/* for now, the rule is that library is compitable if requested
|
||||
/* for now, the rule is that library is compatible if requested
|
||||
* version is lower */
|
||||
iso_lib_version(&cmajor, &cminor, &cmicro);
|
||||
|
||||
|
@ -1878,6 +2093,17 @@ int iso_util_dec_to_uint32(char *dec, uint32_t *value, int flag)
|
|||
}
|
||||
|
||||
|
||||
int iso_util_bin_to_hex(char *target, uint8_t *bytes, int num_bytes, int flag)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_bytes; i++)
|
||||
sprintf(target + 2 * i, "%-2.2x", bytes[i]);
|
||||
target[2 * num_bytes] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int iso_util_hex_to_bin(char *hex, char *bin, int bin_size, int *bin_count,
|
||||
int flag)
|
||||
{
|
||||
|
@ -2050,6 +2276,7 @@ unexpected_type:;
|
|||
goto ex;
|
||||
} else if (range_start != ctx_start_lba) {
|
||||
ret = ISO_MD5_TAG_MISPLACED;
|
||||
goto ex;
|
||||
}
|
||||
ret = iso_md5_clone(ctx, &cloned_ctx);
|
||||
if (ret < 0)
|
||||
|
@ -2092,3 +2319,194 @@ uint16_t iso_htons(uint16_t v)
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* If an UTF-16 surrogate pair was split : Change to UTF-16 '_'.
|
||||
(UCS-2 is promised to reserve 0xd800 to 0xdbff for UTF-16).
|
||||
*/
|
||||
void iso_handle_split_utf16(uint16_t *utf_word)
|
||||
{
|
||||
unsigned char *hb;
|
||||
|
||||
hb = (unsigned char *) utf_word;
|
||||
if ((hb[0] & 0xfc) == 0xd8)
|
||||
set_ucsbe(utf_word, '_');
|
||||
}
|
||||
|
||||
|
||||
int iso_clone_mem(char *in, char **out, size_t size)
|
||||
{
|
||||
if (in == NULL) {
|
||||
*out = NULL;
|
||||
return 1;
|
||||
}
|
||||
if (size == 0)
|
||||
size = strlen(in) + 1;
|
||||
*out = calloc(1, size);
|
||||
if (*out == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
memcpy(*out, in, size);
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int iso_clone_mgtd_mem(char *in, char **out, size_t size)
|
||||
{
|
||||
if (*out != NULL)
|
||||
free(*out);
|
||||
return iso_clone_mem(in, out, size);
|
||||
}
|
||||
|
||||
|
||||
/** Convert a text into a number of type double and multiply it by unit code
|
||||
[kmgt] (2^10 to 2^40) or [s] (2048) or [d] (512).
|
||||
(Also accepts capital letters.)
|
||||
@param text Input like "42", "223062s", "3m" or "-1g"
|
||||
@param flag Bitfield for control purposes:
|
||||
bit0= return -1 rather than 0 on failure
|
||||
bit1= if scaled then compute the last byte of the last unit
|
||||
@return The derived value
|
||||
*/
|
||||
off_t iso_scanf_io_size(char *text, int flag)
|
||||
{
|
||||
int c;
|
||||
off_t ret = 0, fac = 1;
|
||||
char *rpt;
|
||||
|
||||
for (rpt = text; *rpt >= '0' && *rpt <= '9'; rpt++)
|
||||
ret = ret * 10 + (*rpt - '0');
|
||||
if (rpt == text)
|
||||
return (off_t) (flag & 1 ? -1 : 0);
|
||||
c = *rpt;
|
||||
if (c=='k' || c=='K')
|
||||
fac = 1024;
|
||||
else if (c=='m' || c=='M')
|
||||
fac = 1024 * 1024;
|
||||
else if (c=='g' || c=='G')
|
||||
fac = 1024 * 1024 * 1024;
|
||||
else if (c=='t' || c=='T')
|
||||
fac = ((off_t) 1024) * 1024 * 1024 * 1024;
|
||||
else if (c=='s' || c=='S')
|
||||
fac = 2048;
|
||||
else if (c=='d' || c=='D')
|
||||
fac = 512;
|
||||
ret *= fac;
|
||||
if (flag & 2)
|
||||
ret += fac - 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Find backward from idx the start byte of a possible UTF-8 character.
|
||||
https://en.wikipedia.org/wiki/UTF-8#Description
|
||||
*/
|
||||
static
|
||||
int find_utf8_start(char *name, int idx, int flag)
|
||||
{
|
||||
unsigned char *uname, uch;
|
||||
int i;
|
||||
|
||||
uname= (unsigned char *) name;
|
||||
if ((uname[idx] & 0xc0) != 0x80)
|
||||
return idx; /* not an UTF-8 tail byte */
|
||||
for (i = 0; i < 5 && idx - 1 - i >= 0; i++) { /* up to deprecated 6-byte codes */
|
||||
uch = uname[idx - 1 - i];
|
||||
if ((uch & 0xe0) == 0xc0 || (uch & 0xf0) == 0xe0 ||
|
||||
(uch & 0xf8) == 0xf0 || (uch & 0xfc) == 0xf8 ||
|
||||
(uch & 0xfe) == 0xfc)
|
||||
return (idx - 1 - i); /* UTF-8 start byte found */
|
||||
if ((uch & 0xc0) != 0x80)
|
||||
return idx; /* not an UTF-8 tail byte, so no UTF-8 */
|
||||
}
|
||||
return idx; /* no UTF-8 start found */
|
||||
}
|
||||
|
||||
/* @param flag bit0= do not issue warning message
|
||||
*/
|
||||
int iso_truncate_rr_name(int truncate_mode, int truncate_length,
|
||||
char *name, int flag)
|
||||
{
|
||||
int neck, goal, ret, l, i;
|
||||
static int hash_size = 32;
|
||||
void *ctx = NULL;
|
||||
char hashval[16];
|
||||
|
||||
l = strlen(name);
|
||||
if (l <= truncate_length)
|
||||
return ISO_SUCCESS;
|
||||
if (truncate_mode == 0)
|
||||
return ISO_RR_NAME_TOO_LONG;
|
||||
|
||||
/* Compute hash */
|
||||
ret = iso_md5_start(&ctx);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
ret = iso_md5_compute(ctx, name, l > 4095 ? 4095 : l);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
ret = iso_md5_end(&ctx, hashval);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
|
||||
if (!(flag & 1))
|
||||
iso_msg_submit(-1, ISO_RR_NAME_TRUNCATED, 0,
|
||||
"File name had to be truncated and MD5 marked: %s", name);
|
||||
|
||||
/* Avoid to produce incomplete UTF-8 characters */
|
||||
goal = truncate_length - hash_size - 1;
|
||||
neck = find_utf8_start(name, goal, 0);
|
||||
for (; neck < goal; neck++)
|
||||
name[neck] = '_';
|
||||
|
||||
/* Write colon and hash text over end of truncated name */
|
||||
name[goal] = ':';
|
||||
goal++;
|
||||
for (i = 0; goal < truncate_length - 1 && i < hash_size / 2; goal += 2) {
|
||||
sprintf(name + goal, "%2.2x", *((unsigned char *) (hashval + i)));
|
||||
i++;
|
||||
}
|
||||
name[truncate_length] = 0;
|
||||
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
if (ctx != NULL)
|
||||
iso_md5_end(&ctx, hashval);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* API */
|
||||
int iso_truncate_leaf_name(int mode, int length, char *name, int flag)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (mode < 0 || mode > 1)
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
if (length < 64 || length > LIBISOFS_NODE_NAME_MAX)
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
ret = iso_truncate_rr_name(mode, length, name, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* API */
|
||||
/* @param flag bit0= *now contains the time to be set as nowtime override
|
||||
bit1= disable the nowtime override
|
||||
@return 1= *now is not overridden , 2= *now is overridden
|
||||
*/
|
||||
int iso_nowtime(time_t *now, int flag)
|
||||
{
|
||||
static int now_time_overridden = 0;
|
||||
static time_t now_time_override = 0;
|
||||
|
||||
if (flag & 1) {
|
||||
now_time_overridden = 1;
|
||||
now_time_override = *now;
|
||||
}
|
||||
if (flag & 2) {
|
||||
now_time_overridden = 0;
|
||||
}
|
||||
*now = time(NULL);
|
||||
if (!now_time_overridden)
|
||||
return 1;
|
||||
*now = now_time_override;
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 - 2012 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2022 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -21,6 +21,12 @@
|
|||
|
||||
#include <time.h>
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
@ -49,16 +55,23 @@ int iso_init_locale(int flag);
|
|||
* @param ocharset
|
||||
* Output charset. Must be supported by iconv
|
||||
* @param output
|
||||
* Location where the pointer to the ouput string will be stored
|
||||
* Location where the pointer to the output string will be stored
|
||||
* @return
|
||||
* 1 on success, < 0 on error
|
||||
*/
|
||||
int strconv(const char *input, const char *icharset, const char *ocharset,
|
||||
char **output);
|
||||
|
||||
/* Like strconv but processing len input bytes rather than strlen(input)
|
||||
*/
|
||||
int strnconv(const char *str, const char *icharset, const char *ocharset,
|
||||
size_t len, char **output);
|
||||
|
||||
/* Like strnconv but also returning the number of bytes in *output.
|
||||
*/
|
||||
int strnconvl(const char *str, const char *icharset, const char *ocharset,
|
||||
size_t len, char **output, size_t *out_len);
|
||||
|
||||
/**
|
||||
* Convert a given string from any input charset to ASCII
|
||||
*
|
||||
|
@ -67,7 +80,7 @@ int strnconv(const char *str, const char *icharset, const char *ocharset,
|
|||
* @param input
|
||||
* Input string
|
||||
* @param output
|
||||
* Location where the pointer to the ouput string will be stored
|
||||
* Location where the pointer to the output string will be stored
|
||||
* @return
|
||||
* 1 on success, < 0 on error
|
||||
*/
|
||||
|
@ -82,12 +95,28 @@ int str2ascii(const char *icharset, const char *input, char **output);
|
|||
* @param input
|
||||
* Input string
|
||||
* @param output
|
||||
* Location where the pointer to the ouput string will be stored
|
||||
* Location where the pointer to the output string will be stored
|
||||
* @return
|
||||
* 1 on success, < 0 on error
|
||||
*/
|
||||
int str2ucs(const char *icharset, const char *input, uint16_t **output);
|
||||
|
||||
/**
|
||||
* Convert a given string from any input charset to UTF-16BE charset,
|
||||
* used for HFS+ file identifiers.
|
||||
* (UTF-16 differs from older UCS-2 by having multi word characters.)
|
||||
*
|
||||
* @param icharset
|
||||
* Input charset. Must be supported by iconv
|
||||
* @param input
|
||||
* Input string
|
||||
* @param output
|
||||
* Location where the pointer to the output string will be stored
|
||||
* @return
|
||||
* 1 on success, < 0 on error
|
||||
*/
|
||||
int str2utf16be(const char *icharset, const char *input, uint16_t **output);
|
||||
|
||||
/**
|
||||
* Create a level 1 directory identifier.
|
||||
*
|
||||
|
@ -220,15 +249,28 @@ uint16_t *ucscpy(uint16_t *dest, const uint16_t *src);
|
|||
*/
|
||||
uint16_t *ucsncpy(uint16_t *dest, const uint16_t *src, size_t n);
|
||||
|
||||
/**
|
||||
* Check whether utf_word is the first surrogate word of a pair.
|
||||
* If so, change it to UTF-16 character '_'.
|
||||
*/
|
||||
void iso_handle_split_utf16(uint16_t *utf_word);
|
||||
|
||||
/**
|
||||
* Convert a given input string to d-chars.
|
||||
* @return
|
||||
* 1 on succes, < 0 error, 0 if input was null (output is set to null)
|
||||
* 1 on success, < 0 error, 0 if input was null (output is set to null)
|
||||
*/
|
||||
int str2d_char(const char *icharset, const char *input, char **output);
|
||||
int str2a_char(const char *icharset, const char *input, char **output);
|
||||
|
||||
/* Check for membership in the d-, a-, or j-character set */
|
||||
int valid_d_char(char c);
|
||||
int valid_a_char(char c);
|
||||
int valid_j_char(uint16_t c);
|
||||
|
||||
|
||||
void iso_lsb(uint8_t *buf, uint32_t num, int bytes);
|
||||
void iso_lsb64(uint8_t *buf, uint64_t num);
|
||||
void iso_msb(uint8_t *buf, uint32_t num, int bytes);
|
||||
void iso_bb(uint8_t *buf, uint32_t num, int bytes);
|
||||
|
||||
|
@ -244,6 +286,9 @@ uint32_t iso_read_msb(const uint8_t *buf, int bytes);
|
|||
*/
|
||||
uint32_t iso_read_bb(const uint8_t *buf, int bytes, int *error);
|
||||
|
||||
uint64_t iso_read_lsb64(const uint8_t *buf);
|
||||
uint64_t iso_read_msb64(const uint8_t *buf);
|
||||
|
||||
/**
|
||||
* Records the date/time into a 7 byte buffer (ECMA-119, 9.1.5)
|
||||
*
|
||||
|
@ -362,13 +407,19 @@ size_t iso_rbtree_get_size(IsoRBTree *tree);
|
|||
* without counting the final NULL item.
|
||||
* @return
|
||||
* A sorted array with the contents of the tree, or NULL if there is not
|
||||
* enought memory to allocate the array. You should free(3) the array when
|
||||
* enough memory to allocate the array. You should free(3) the array when
|
||||
* no more needed. Note that the array is NULL-terminated, and thus it
|
||||
* has size + 1 length.
|
||||
*/
|
||||
void **iso_rbtree_to_array(IsoRBTree *tree, int (*include_item)(void *),
|
||||
size_t *size);
|
||||
|
||||
/** Predict the size of the array which gets returned by iso_rbtree_to_array().
|
||||
*/
|
||||
size_t iso_rbtree_count_array(IsoRBTree *tree, size_t initial_count,
|
||||
int (*include_item)(void *));
|
||||
|
||||
|
||||
/**
|
||||
* Create a new hash table.
|
||||
*
|
||||
|
@ -515,6 +566,14 @@ int iso_util_eval_md5_tag(char *block, int desired, uint32_t lba,
|
|||
int iso_util_tag_magic(int tag_type, char **tag_magic, int *len, int flag);
|
||||
|
||||
|
||||
int iso_util_bin_to_hex(char *target, uint8_t *bytes, int num_bytes, int flag);
|
||||
|
||||
int iso_util_hex_to_bin(char *hex, char *bin, int bin_size, int *bin_count,
|
||||
int flag);
|
||||
|
||||
int iso_truncate_rr_name(int truncate_mode, int truncate_length,
|
||||
char *name, int flag);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* In md5.h these function prototypes would be neighbors of (Ecma119Image *)
|
||||
|
@ -577,6 +636,29 @@ void *iso_alloc_mem(size_t size, size_t count, int flag);
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
@param in Valid memory or NULL
|
||||
@param out Returns valid memory or NULL
|
||||
@param size Number of bytes to copy. 0 means strlen(in)+1 if not NULL.
|
||||
@return 1 or ISO_OUT_OF_MEM
|
||||
*/
|
||||
int iso_clone_mem(char *in, char **out, size_t size);
|
||||
|
||||
/* Like iso_clone_mem but first freeing *out if not NULL
|
||||
*/
|
||||
int iso_clone_mgtd_mem(char *in, char **out, size_t size);
|
||||
|
||||
/** Convert a text into a number of type double and multiply it by unit code
|
||||
[kmgt] (2^10 to 2^40) or [s] (2048) or [d] (512).
|
||||
(Also accepts capital letters.)
|
||||
@param text Input like "42", "223062s", "3m" or "-1g"
|
||||
@param flag Bitfield for control purposes:
|
||||
bit0= return -1 rather than 0 on failure
|
||||
bit1= if scaled then compute the last byte of the last unit
|
||||
@return The derived value
|
||||
*/
|
||||
off_t iso_scanf_io_size(char *text, int flag);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2014 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
|
@ -322,9 +323,10 @@ int iso_htable_create(size_t size, hash_funtion_t hash,
|
|||
{
|
||||
IsoHTable *t;
|
||||
|
||||
if (table == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
if (size <= 0)
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
if (table == NULL)
|
||||
return ISO_NULL_POINTER;
|
||||
|
||||
t = malloc(sizeof(IsoHTable));
|
||||
if (t == NULL) {
|
||||
|
|
|
@ -277,7 +277,7 @@ size_t rbtree_to_array_aux(struct iso_rbnode *root, void **array, size_t pos,
|
|||
* NULL pointer.
|
||||
* @return
|
||||
* A sorted array with the contents of the tree, or NULL if there is not
|
||||
* enought memory to allocate the array. You should free(3) the array when
|
||||
* enough memory to allocate the array. You should free(3) the array when
|
||||
* no more needed. Note that the array is NULL-terminated, and thus it
|
||||
* has size + 1 length.
|
||||
*/
|
||||
|
@ -308,3 +308,38 @@ void ** iso_rbtree_to_array(IsoRBTree *tree, int (*include_item)(void *),
|
|||
return array;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
size_t rbtree_count_array_aux(struct iso_rbnode *root, size_t pos,
|
||||
int (*include_item)(void *))
|
||||
{
|
||||
if (root == NULL) {
|
||||
return pos;
|
||||
}
|
||||
pos = rbtree_count_array_aux(root->ch[0], pos, include_item);
|
||||
if (include_item == NULL || include_item(root->data)) {
|
||||
|
||||
/*
|
||||
{
|
||||
IsoFileSrc* src = (IsoFileSrc*) root->data;
|
||||
fprintf(stderr, "libisofs_DEBUG: rbtree_count_array_aux : not taken : '%s'\n",
|
||||
iso_stream_get_source_path(src->stream, 0));
|
||||
}
|
||||
*/
|
||||
|
||||
pos++;
|
||||
}
|
||||
pos = rbtree_count_array_aux(root->ch[1], pos, include_item);
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
size_t iso_rbtree_count_array(IsoRBTree *tree, size_t initial_count,
|
||||
int (*include_item)(void *))
|
||||
{
|
||||
size_t pos;
|
||||
|
||||
pos = rbtree_count_array_aux(tree->root, initial_count, include_item);
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,13 +29,13 @@ struct Iso_Image_Writer
|
|||
};
|
||||
|
||||
/**
|
||||
* This is the function all Writers shoudl call to write data to image.
|
||||
* This is the function all Writers should call to write data to image.
|
||||
* Currently, it is just a wrapper for write(2) Unix system call.
|
||||
*
|
||||
* It is implemented in ecma119.c
|
||||
*
|
||||
* @return
|
||||
* 1 on sucess, < 0 error
|
||||
* 1 on success, < 0 error
|
||||
*/
|
||||
int iso_write(Ecma119Image *target, void *buf, size_t count);
|
||||
|
||||
|
|
Loading…
Reference in New Issue