Compare commits
589 Commits
release-1.
...
release-1.
Author | SHA1 | Date | |
---|---|---|---|
e7dd325ff6 | |||
0447496710 | |||
496b8051c5 | |||
63c074b0aa | |||
2be47f9af8 | |||
bf5678c6d4 | |||
9d64318502 | |||
866f647fad | |||
2f134dcdcb | |||
b14ee71d51 | |||
c5c9d4e7bf | |||
6321ed4d97 | |||
188e36178b | |||
cbfa9afcf1 | |||
cb519b3692 | |||
8407d9e936 | |||
d482eb4c96 | |||
1786ceb276 | |||
f51fc50356 | |||
02de4570d1 | |||
2a41b4817c | |||
9440e3061c | |||
122dfe7b87 | |||
03662f0832 | |||
eb09bcf9e5 | |||
5880636a50 | |||
b5fb98a2a3 | |||
b269557743 | |||
0fd7d4d7eb | |||
d8dca37d65 | |||
cd84f0927f | |||
477bbb89bb | |||
31fcdc0ba6 | |||
7c05d2a865 | |||
3d15642307 | |||
872b5c6c67 | |||
ec35bb21c0 | |||
93f3cb1823 | |||
fea7be5168 | |||
bd25db9283 | |||
97eec6162c | |||
17e8cb6697 | |||
9e01d3654e | |||
009ce1be8f | |||
c79299ba08 | |||
b3701f0b18 | |||
83b864efd2 | |||
cd0f57dd1a | |||
4c9cb6b96b | |||
9c334891cf | |||
2f6103b783 | |||
f32ee7da83 | |||
52972811f8 | |||
089982022c | |||
a6316ff05c | |||
02a972a2d7 | |||
da8ad0d2aa | |||
79e6312397 | |||
b3a183fceb | |||
355f1f7ea2 | |||
57fd669d1d | |||
6047464b6b | |||
e8b94e7b50 | |||
49dd9dc993 | |||
93e1fc52d0 | |||
4838cd59a7 | |||
d51b1738dd | |||
6252ae2065 | |||
cb1e56478a | |||
05d0ee4a37 | |||
c6aedc9eb5 | |||
505bf23aa4 | |||
ccef2f29da | |||
b904926443 | |||
7bdc4c96f5 | |||
fa5e27458a | |||
7c29a94ab6 | |||
a4c1e04820 | |||
50132d4ff7 | |||
4c1c1ea152 | |||
a16d4a28f4 | |||
4633ea3bc8 | |||
430c005666 | |||
af55722830 | |||
d1da5718c7 | |||
afb2878773 | |||
4e7432c20f | |||
7ef616f268 | |||
d5f1eb9c65 | |||
28b41bce2c | |||
5ac3216933 | |||
05a2171e04 | |||
188a41f041 | |||
fbe7f1e89d | |||
d04abdcfbd | |||
a6542e5fa9 | |||
78d2c02ad8 | |||
48453ef1da | |||
7928c4ec3f | |||
379e223a5c | |||
e4750907e3 | |||
8f76b59541 | |||
0433b7ea75 | |||
d8fb8b26a6 | |||
b9ccdeda72 | |||
d04f438ba1 | |||
e35cb88328 | |||
83fb614462 | |||
e5f6811795 | |||
f3b836194c | |||
3a870d23e3 | |||
06ea46c8d5 | |||
d427a03192 | |||
2b6071b445 | |||
fc448e09c9 | |||
7b7da47d86 | |||
01c7a0d5ec | |||
905f4f898f | |||
b9ec876c40 | |||
72ef369a40 | |||
218e26c974 | |||
395128ef5f | |||
7a3560035a | |||
7ac5b75748 | |||
6c3dc3ce4a | |||
bdbaf81e9c | |||
c8ed18695f | |||
d3fefe4735 | |||
6db3f6ca44 | |||
bf19f73ea6 | |||
6947bfe5ec | |||
94f8503b57 | |||
cb519e221e | |||
d09a317f51 | |||
2beb0d001b | |||
6c9b81a474 | |||
393cc070f3 | |||
006caa2fd2 | |||
c47167058a | |||
5a3d84cbbb | |||
5f6e64b792 | |||
d4b8cbe474 | |||
a0719328ea | |||
c8776e605e | |||
003aa5832e | |||
a78864252e | |||
e56a782b89 | |||
9e17516e0d | |||
e29cd723dd | |||
b0694b4e25 | |||
850302dde5 | |||
26b4222948 | |||
782bb7854e | |||
9c33eb5f10 | |||
8e55195edc | |||
527b613607 | |||
0819f93f79 | |||
3b0ba17f3d | |||
0611f468c2 | |||
5c6ce72c02 | |||
585a54d020 | |||
7ea6d4ebcb | |||
3e33fa5fa1 | |||
cdc336a02b | |||
288eb75745 | |||
210b5817cb | |||
2fe0bf511b | |||
af23ad0f90 | |||
0fc4421e15 | |||
6ed2404420 | |||
a22c16d5ef | |||
5384342336 | |||
a97c66ebb8 | |||
1c2851b5ba | |||
cbea1335d8 | |||
6da58860ec | |||
c47451d12b | |||
a068a1349a | |||
eae886bcb5 | |||
288e778875 | |||
8e687db01d | |||
273182aa2a | |||
e26d07ee77 | |||
1b5caac764 | |||
42821af4e6 | |||
c17ba1980a | |||
1df1642a61 | |||
c07f42dfd4 | |||
443156e100 | |||
2f517301de | |||
0bce145343 | |||
6d64bc23cf | |||
25295d2bb0 | |||
3370f666f9 | |||
ad279352e3 | |||
dfd74d3d04 | |||
593844b0ed | |||
083795cba2 | |||
3b06d25a37 | |||
9e5158f59e | |||
d93be961e1 | |||
8c1c0775d6 | |||
2f8bd3ac01 | |||
6edc1ac057 | |||
a394f4dfd2 | |||
dd27f579eb | |||
1ac59bec46 | |||
af843e446f | |||
e6e037f87e | |||
ca2643b52b | |||
ed8066580a | |||
97ec68530b | |||
185cbd99bf | |||
0e00aeb638 | |||
03b45c3151 | |||
b82ca42f87 | |||
1a8a216822 | |||
ef528f2f0e | |||
bedfa914d5 | |||
5383ae2faa | |||
d23462657b | |||
b41e36365d | |||
985015cea1 | |||
27d4c79d0e | |||
5b78efb12a | |||
2c2fb7caf2 | |||
d51cefb097 | |||
7637d13e11 | |||
b9b5284f22 | |||
afa65e9f2a | |||
5e1aaca232 | |||
fea649835c | |||
44f475a4ef | |||
60eb7e883c | |||
9b4e0b611a | |||
1be57e34ec | |||
b0e68bbcaa | |||
fa61b94ac8 | |||
3e3c15812b | |||
88555bd059 | |||
ba47d1534c | |||
b7dc0f4057 | |||
0ab9f5f8d2 | |||
1338f29d62 | |||
bc5e2227c8 | |||
654ff82345 | |||
6baeae70e0 | |||
b987972660 | |||
c78526abce | |||
b95e1bb85c | |||
7aa2582129 | |||
3f29d70aba | |||
567d3ddafb | |||
c47f85c639 | |||
40310b4fd7 | |||
f34c274f21 | |||
46e96ee616 | |||
7e60e60e62 | |||
d55ed2d1ca | |||
77c8349c56 | |||
b1c7ed6e29 | |||
e886722d65 | |||
b80b339de3 | |||
efbd05203d | |||
6ca1d76d60 | |||
e1b54056e8 | |||
d5cd610ac7 | |||
91f5ebb376 | |||
ff3b439bda | |||
4672c79181 | |||
83cb07b23c | |||
439a14da1d | |||
d66eef42f6 | |||
337bade549 | |||
eb6503a8ad | |||
1a2e1c767e | |||
858c5479c8 | |||
d36b3d04a8 | |||
da41eb8c6e | |||
775b7a11b4 | |||
23679b86ff | |||
a4f07eb3b3 | |||
6905ab3e56 | |||
05e7f84966 | |||
6e5f840f11 | |||
df37211b7b | |||
bd81e44da0 | |||
37792c5713 | |||
4fb98d9c3c | |||
57a14ec0be | |||
c5d8c26653 | |||
4ff777ee58 | |||
46bb5945c6 | |||
a585d6a32d | |||
b77917fb63 | |||
4673733c4b | |||
f3e63e3cf7 | |||
fb9b3a298c | |||
1539ff120e | |||
20cc592765 | |||
1dd05f63a7 | |||
fe07c87788 | |||
8c58e2a012 | |||
b6b8b1625c | |||
042dbd01ed | |||
7001121a3f | |||
942ec97c7b | |||
8b2edd7ca4 | |||
2e6c3efda2 | |||
2e63856dee | |||
b211ce6804 | |||
4c2a24514d | |||
b07d60bbfc | |||
e8f6f924bd | |||
7a8995f322 | |||
2c88e74798 | |||
2d441cca5d | |||
7e49fb553b | |||
af367561a6 | |||
85bedae639 | |||
bbd198a81b | |||
2a08471c04 | |||
72bdd7a3d0 | |||
bab3cf0c7c | |||
862d4fb571 | |||
27277914c6 | |||
2d3bbe51ed | |||
5288cec97d | |||
09b314c66f | |||
55e134fb1c | |||
9882d983b9 | |||
6fd859a2c1 | |||
4d10b8c73c | |||
0ebc8fe186 | |||
912e0cd1be | |||
3a60720099 | |||
c166a49889 | |||
6fc3bb6777 | |||
d7401f0a4c | |||
6a3273dc72 | |||
0897896713 | |||
1de0284eaa | |||
7c6c3466e9 | |||
3528795b55 | |||
3b95f4c4c4 | |||
2cc387fcce | |||
45bee0a849 | |||
7fd36ffade | |||
5427fa9e17 | |||
ce17f78d59 | |||
1bbdb97a2d | |||
f39e73d2ce | |||
74bc1808a1 | |||
ad251e8c7d | |||
cb3a6f8bb0 | |||
a3285f6e5d | |||
36502f8ae3 | |||
21109ffcf1 | |||
bcd4b88319 | |||
714ef6493a | |||
01b2ee088b | |||
2ed96d89f9 | |||
cc71d9e30b | |||
4fd7faa636 | |||
d2c19ed2b4 | |||
63df7749fa | |||
e9eb22f514 | |||
e57e45e40b | |||
1ed3ba7933 | |||
3e2479c095 | |||
bc7e8acb74 | |||
8770148cad | |||
6fc6a09040 | |||
a72fd6a309 | |||
82f39020cf | |||
1842921b2c | |||
ab11c954d9 | |||
177864bd13 | |||
ed986aa4ea | |||
45bf3d9717 | |||
c1df1c9fd8 | |||
a7ae64e3c7 | |||
6cb5f802af | |||
a8b20b87aa | |||
201e7f15df | |||
f040f31d05 | |||
9e2d82fc78 | |||
1a5c02a27e | |||
e5a4e33ebd | |||
fae423fb54 | |||
e97bd3ed2d | |||
2c540b1f43 | |||
6982971796 | |||
3c7c534ded | |||
262e49ad6b | |||
502bea814e | |||
fa784d619c | |||
977161cda1 | |||
dc2b27ca51 | |||
abd2137906 | |||
ff95a84130 | |||
f384961808 | |||
81dd6ce55a | |||
125789feef | |||
37efffcf26 | |||
b2c281d0c6 | |||
8a2fa9fe2e | |||
1247edff95 | |||
a2fe1a4100 | |||
4eb4146474 | |||
ce35aefb32 | |||
269e0b19a5 | |||
0a8bb0e9b8 | |||
76f2a5f4d3 | |||
e49f9672bc | |||
37f880797d | |||
475eb36978 | |||
ac9116c64e | |||
b1c218c280 | |||
ebea7c29ef | |||
09c49f777a | |||
5f76be9d76 | |||
305fe3f496 | |||
191c3245af | |||
b5b30b1c75 | |||
6a1bbaa902 | |||
bddc44d1ca | |||
9b61ff377c | |||
22fed6bedb | |||
3433592f69 | |||
d787ecbcd9 | |||
182edb3a00 | |||
cb25d4d4e5 | |||
afdef92343 | |||
2bc7084315 | |||
6d10908a58 | |||
2ba54fafe7 | |||
ca63dac7e3 | |||
f885da8087 | |||
8438db02cf | |||
ce19db5e19 | |||
aeb5258ae2 | |||
f10c2d7779 | |||
82bfcf429a | |||
8fb8c01a0f | |||
73910e2f3c | |||
9c5fc21679 | |||
3a82f213e0 | |||
6892c734e2 | |||
66f6937c17 | |||
baa5b7cd42 | |||
f2658ef173 | |||
ecdb3aeb1d | |||
745a878884 | |||
6ae8386c23 | |||
b90e613246 | |||
bbc3caf86b | |||
b086d53274 | |||
17b36623a6 | |||
286648574d | |||
317bba395e | |||
541b41b6a1 | |||
91a8be5262 | |||
91e99703b4 | |||
dd7dac3397 | |||
43d4833dd6 | |||
dd1629b5ca | |||
bc8138ce78 | |||
2d568c1dbb | |||
842b62d111 | |||
4f3357e3ec | |||
9ffe91c372 | |||
7e2add413a | |||
004aefd0b7 | |||
00955ba85c | |||
4a79812d15 | |||
9b2f97e4b7 | |||
35cfb756be | |||
2835fccfa4 | |||
31c7f68990 | |||
4e0ca258de | |||
9653854462 | |||
6e95f8bbcb | |||
ce3aa0d5c7 | |||
d5bfc552c4 | |||
bad54a5967 | |||
49b0a89bfe | |||
265df5fbe3 | |||
f089bcf66a | |||
062e5f0bf0 | |||
d932bfcdea | |||
3ef67cb49d | |||
f08ae22dbe | |||
45d316d1ca | |||
4d8fc6ffee | |||
023e413624 | |||
d361186bca | |||
e7d9559d16 | |||
94eecbb123 | |||
777f74ea0b | |||
2b8d47ddd8 | |||
e839b7b368 | |||
1334027a83 | |||
8d3a0a6a9e | |||
7b7ea41f12 | |||
bb5886094e | |||
b076ce9b44 | |||
05f26898f3 | |||
a698f0ee22 | |||
e69854b35f | |||
228995c148 | |||
071e14f9b0 | |||
b08d6271ab | |||
431d31fff6 | |||
a37571c6c5 | |||
6e98006640 | |||
d264e818c3 | |||
d0f740facf | |||
944b5a6152 | |||
b51232fef4 | |||
99f037e210 | |||
c794a48a06 | |||
47d599e8c3 | |||
0a87e838df | |||
e945e38add | |||
6d68abc707 | |||
e80dd0735b | |||
c276681735 | |||
1d723f0834 | |||
1a4b2a2584 | |||
4eb2a7199c | |||
6d5e68fd01 | |||
fed8b23017 | |||
e3329a98a9 | |||
49efbdad76 | |||
9538a5d57b | |||
66dc6c2d0e | |||
81608815ae | |||
ae5ab4a08f | |||
76b6737570 | |||
9210a57500 | |||
8a752b50fa | |||
c38b1a3a3a | |||
73c9c7f244 | |||
0b9f03bb23 | |||
d1c3a017e3 | |||
b200feceed | |||
7958b2ea22 | |||
c0bdf4d3b5 | |||
71efc996e3 | |||
61383dea2d | |||
270cd1cad5 | |||
559e9b564d | |||
d8a56f60ef | |||
10e3b2939a | |||
ba67523278 | |||
f09964cf51 | |||
e4a70a823d | |||
655d86b97a | |||
f2f780115b | |||
b6be8457f7 | |||
1238c19494 | |||
2caf527f67 | |||
43eae7502b | |||
e035146e01 | |||
de3e21629f | |||
d79a3fcec4 | |||
de079cec42 | |||
b33d06eb0c | |||
dfdaa2902a | |||
0173c51c23 | |||
a118127e9c | |||
1f24b39879 | |||
16863755be | |||
b25ac0f52d | |||
5c59295e72 | |||
85893bf58b | |||
722327e4b8 | |||
ab0a981814 | |||
38483d894e | |||
1082e628d1 | |||
74c68224c7 | |||
200697898d | |||
a3eeda3d23 | |||
92073c45ef | |||
81cded618d | |||
84c0bd37ff | |||
4e60feaeab | |||
d6e150a10e |
@ -1,7 +1,7 @@
|
||||
Vreixo Formoso <metalpain2002@yahoo.es>,
|
||||
Mario Danic <mario.danic@gmail.com>,
|
||||
Thomas Schmitt <scdbackup@gmx.net>
|
||||
Copyright (C) 2007-2010 Vreixo Formoso, Mario Danic, Thomas Schmitt
|
||||
Copyright (C) 2007-2015 Vreixo Formoso, Mario Danic, Thomas Schmitt
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
254
ChangeLog
254
ChangeLog
@ -1,6 +1,256 @@
|
||||
bzr branch lp:libisofs/for-libisoburn (to become libisofs-1.0.2.tar.gz)
|
||||
|
||||
libisofs-1.4.6.tar.gz Fri Sep 16 2016
|
||||
===============================================================================
|
||||
- no novelties yet
|
||||
* 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
|
||||
call of iso_init() would try to dereference.
|
||||
* The sort weight of data files loaded from ISO image is now 2 exp 28 to 1
|
||||
rather than 2 exp 31 - 1 to - 2 exp 31
|
||||
|
||||
libisofs-1.3.0.tar.gz Fri May 17 2013
|
||||
===============================================================================
|
||||
* Bug fix: GPT header CRC was computed from all 512 bytes rather than from 92.
|
||||
* Bug fix: Unspecified Expiration Time and Effective Time of ISO volume was
|
||||
represented by 0-bytes rather than ASCII '0' digits.
|
||||
* Bug fix: Reserved and unused fields of APM entries were not zeroed.
|
||||
* Bug fix: The protective MBR partition for GPT started at block 0 instead of 1.
|
||||
* New option bits with el_torito_set_isolinux_options() and
|
||||
iso_write_opts_set_system_area() to control GRUB2 patching of
|
||||
boot image and MBR.
|
||||
* New API calls iso_image_set_sparc_core() and iso_image_get_sparc_core().
|
||||
|
||||
libisofs-1.2.8.tar.gz Mon Mar 18 2013
|
||||
===============================================================================
|
||||
* Bug fix: Image size prediction altered the pointers to MD5 of data files
|
||||
which stem from a previous session.
|
||||
* Bug fix: Reading damaged Rock Ridge data could cause SIGSEGV by NULL.
|
||||
* New API call iso_image_get_pvd_times().
|
||||
|
||||
libisofs-1.2.6.tar.gz Tue Jan 08 2013
|
||||
===============================================================================
|
||||
* Bug fix: Appended partitions did not obey cylinder alignment
|
||||
* Bug fix: Non-zero partition offset zeroized the MBR copies of GPT partition
|
||||
table entries
|
||||
* Bug fix: Isohybrid production without any boot image led to SIGSEGV by NULL
|
||||
* Bug fix: Prevented a memory fault when reading damaged Rock Ridge information
|
||||
|
||||
libisofs-1.2.4.tar.gz Fri Jul 20 2012
|
||||
===============================================================================
|
||||
* Bug fix: Memory corruption when reading bootable image that was truncated
|
||||
before the storage location of the boot catalog
|
||||
* Bug fix: Symbol iso_fs_global_id was missing in libisofs.ver.
|
||||
* Bug fix: Volume descriptors of Joliet and ISO 9660:1999 beared non-zero
|
||||
Effective Date, involuntarily restricting the early end of
|
||||
their lifetime.
|
||||
* Bug fix: File Structure Version field of ISO 9660:1999 Enhanced Volume
|
||||
Descriptor was 1 instead of 2.
|
||||
* Bug fix: The separator dot of Joliet names was byte swapped on big-endian
|
||||
machines.
|
||||
* Bug fix: Joliet name comparison was done as signed bytes and thus produced
|
||||
a peculiar sorting order.
|
||||
* Bug fix: Partition cylinder alignment worked only if both, El Torito and
|
||||
application provided system area data were present.
|
||||
* New API function iso_write_opts_set_hfsplus
|
||||
* New API functions iso_hfsplus_xinfo_func(), iso_hfsplus_xinfo_new(), and
|
||||
new struct iso_hfsplus_xinfo_data.
|
||||
* New API call iso_write_opts_set_hfsp_serial_number()
|
||||
* New API calls iso_image_hfsplus_bless and iso_image_hfsplus_get_blessed(),
|
||||
and new public enum IsoHfsplusBlessings.
|
||||
* New API calls so_write_opts_set_prep_img(), iso_write_opts_set_efi_bootp()
|
||||
* New API call iso_write_opts_set_hfsp_block_size()
|
||||
* New API call iso_tree_resolve_symlink()
|
||||
* New system area sub type CHRP with iso_write_opts_set_system_area()
|
||||
* New option bits 2 to 8 for GPT and APM with el_torito_set_isolinux_options()
|
||||
* New flag bit with iso_node_set_attrs() to protect namespace "isofs"
|
||||
* New IsoHideNodeFlag value LIBISO_HIDE_ON_HFSPLUS
|
||||
|
||||
libisofs-1.2.2.tar.gz Mon Apr 02 2012
|
||||
===============================================================================
|
||||
* New API call iso_write_opts_set_rr_reloc()
|
||||
* Bug fix: Directory name mapping to ISO level 1 was too liberal if
|
||||
iso_write_opts_set_allow_dir_id_ext() was enabled
|
||||
* New API call iso_write_opts_set_allow_7bit_ascii()
|
||||
* Improved standards compliance for ISO level 1 names with partly relaxed
|
||||
constraints.
|
||||
|
||||
libisofs-1.2.0.tar.gz Sat Jan 28 2012
|
||||
===============================================================================
|
||||
* Extended influence of iso_write_opts_set_dir_rec_mtime() to Joliet and
|
||||
ISO 9660:1999.
|
||||
|
||||
libisofs-1.1.6.tar.gz Tue Sep 27 2011
|
||||
===============================================================================
|
||||
* Bug fix: On Solaris: False out-of-memory errors when writing images.
|
||||
* Bug fix: On FreeBSD: No ACLs were recorded.
|
||||
* Bug fix: ACL entries of groups and of user id 0 were not properly recorded
|
||||
and cannot be restored.
|
||||
* Bug fix: On FreeBSD: The function for restoring ACLs and xattr returned
|
||||
error, even if no xattr were to be restored.
|
||||
* New API call iso_local_attr_support()
|
||||
* Enabled recording and restoring of extattr on FreeBSD.
|
||||
|
||||
libisofs-1.1.4.tar.gz Mon Aug 08 2011
|
||||
===============================================================================
|
||||
* Bug fix: The function for restoring ACLs and xattr returned error on systems
|
||||
other than Linux and FreeBSD, even if nothing was to be restored.
|
||||
|
||||
libisofs-1.1.2.tar.gz Fri Jul 08 2011
|
||||
===============================================================================
|
||||
* New API call iso_image_get_bootcat()
|
||||
|
||||
libisofs-1.1.0.tar.gz Sat Jun 18 2011
|
||||
===============================================================================
|
||||
* Bug fix: Padding as of iso_write_opts_set_tail_blocks() was added only
|
||||
after cylinder alignment as of iso_write_opts_set_system_area()
|
||||
and thus spoiled this alignment.
|
||||
|
||||
libisofs-1.0.8.tar.gz Thu May 12 2011
|
||||
===============================================================================
|
||||
* Bug fix: iso_write_opts_set_system_area() with system area types
|
||||
1=MIPS Big Endian and 2=MIPS Little Endian caused SIGSEGV.
|
||||
* Bug fix: SIGSEGV if the path given by iso_image_add_mips_boot_file()
|
||||
does not exist in the image at image production time.
|
||||
* Bug fix: While loading an ISO image: Several reads to malloc
|
||||
memory occured with byte index -1. (Found by Valgrind after
|
||||
years of operation without visible problems.)
|
||||
* Bug fix: Closed a memory leak of 32 kB per loaded ISO image.
|
||||
|
||||
libisofs-1.0.6.tar.gz Sat Apr 09 2011
|
||||
===============================================================================
|
||||
* New API call iso_write_opts_set_joliet_long_names()
|
||||
* New error codes for oversized file addresses
|
||||
|
||||
libisofs-1.0.4.tar.gz Thu Mar 10 2011
|
||||
===============================================================================
|
||||
* Bug fix: Compilation failed if --disable-zlib was configured
|
||||
* Bug fix: isohybrid image size was not aligned to cylinder boundary.
|
||||
* New no_md5 value 2 for API call iso_read_opts_set_no_md5()
|
||||
* New option bits 8 and 9 with iso_write_opts_set_system_area()
|
||||
|
||||
libisofs-1.0.2.tar.gz Tue Feb 23 2011
|
||||
===============================================================================
|
||||
* Bug fix: iso_write_opts_set_aaip(opts, 1) could cause fatal miscalculation
|
||||
of the root directory size. This eventually truncated directory
|
||||
tree and spoiled all data file content.
|
||||
* Bug fix: Volume Descriptor Set Terminator contained non-zero bytes in
|
||||
the reserved field (ECMA-119 8.3.4). The bytes stem from the
|
||||
previously written Volume Descriptor.
|
||||
* New API calls iso_tree_clone(), iso_stream_clone.
|
||||
* New IsoFileSourceIface version 2 with method clone_src().
|
||||
* New IsoStreamIface version 4 with method clone_stream().
|
||||
* New public function prototype iso_node_xinfo_cloner.
|
||||
* New API calls iso_node_xinfo_make_clonable(), iso_node_xinfo_get_cloner().
|
||||
* New public iso_node_xinfo_cloner instance aaip_xinfo_cloner().
|
||||
* New API calls iso_node_get_next_xinfo(), iso_node_remove_all_xinfo().
|
||||
* New API call iso_node_remove_tree().
|
||||
* New API call iso_write_opts_set_old_empty().
|
||||
|
||||
libisofs-1.0.0.tar.gz Mon Jan 17 2011
|
||||
===============================================================================
|
||||
|
17
Makefile.am
17
Makefile.am
@ -6,13 +6,14 @@ pkgconfigdir=$(LIBBURNIA_PKGCONFDIR)
|
||||
libincludedir=$(includedir)/libisofs
|
||||
|
||||
lib_LTLIBRARIES = libisofs/libisofs.la
|
||||
ACLOCAL_AMFLAGS = -I ./
|
||||
|
||||
## ========================================================================= ##
|
||||
|
||||
# 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.
|
||||
@ -65,6 +66,11 @@ libisofs_libisofs_la_SOURCES = \
|
||||
libisofs/rockridge_read.c \
|
||||
libisofs/joliet.h \
|
||||
libisofs/joliet.c \
|
||||
libisofs/hfsplus.h \
|
||||
libisofs/hfsplus.c \
|
||||
libisofs/hfsplus_decompose.c \
|
||||
libisofs/hfsplus_classes.c \
|
||||
libisofs/hfsplus_case.c \
|
||||
libisofs/eltorito.h \
|
||||
libisofs/eltorito.c \
|
||||
libisofs/system_area.h \
|
||||
@ -83,7 +89,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)"
|
||||
|
||||
## ========================================================================= ##
|
||||
|
||||
@ -219,6 +225,12 @@ demo_demo_SOURCES = demo/demo.c
|
||||
# test/mocked_fsrc.h \
|
||||
# test/mocked_fsrc.c
|
||||
|
||||
# "make clean" shall remove a few stubborn .libs directories
|
||||
# which George Danchev reported Dec 03 2011.
|
||||
# Learned from: http://www.gnu.org/software/automake/manual/automake.html#Clean
|
||||
clean-local:
|
||||
-rm -rf demo/.libs
|
||||
|
||||
## ========================================================================= ##
|
||||
|
||||
## Build documentation (You need Doxygen for this to work)
|
||||
@ -249,6 +261,7 @@ nodist_pkgconfig_DATA = \
|
||||
# ts A80114 : added aaip-os*
|
||||
|
||||
EXTRA_DIST = \
|
||||
bootstrap \
|
||||
libisofs-1.pc.in \
|
||||
version.h.in \
|
||||
doc/doxygen.conf.in \
|
||||
|
10
README
10
README
@ -4,14 +4,17 @@
|
||||
|
||||
Released under GPL (see COPYING file for details).
|
||||
|
||||
Copyright (C) 2008 - 2010 Vreixo Formoso, Mario Danic, Thomas Schmitt
|
||||
Copyright (C) 2008 - 2016 Vreixo Formoso,
|
||||
Mario Danic,
|
||||
Vladimir Serbinenko,
|
||||
Thomas Schmitt
|
||||
|
||||
libisofs is part of the libburnia project (libburnia-project.org)
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Download, Build and Installation
|
||||
|
||||
libisofs code is mantained in a Bazaar repository at Launchpad
|
||||
libisofs code is maintained in a Bazaar repository at Launchpad
|
||||
(https://launchpad.net/libisofs/). You can download it with:
|
||||
|
||||
$ bzr branch lp:libisofs/for-libisoburn
|
||||
@ -34,7 +37,7 @@ 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
|
||||
@ -54,6 +57,7 @@ applications which use it. This dependency can be avoided by configure options
|
||||
--disable-libacl avoid use of ACL functions like acl_to_text()
|
||||
--disable-xattr avoid use of xattr functions like listxattr()
|
||||
--disable-zlib avoid use of zlib functions like compress2()
|
||||
--disable-libjte avoid use of libjte functions
|
||||
|
||||
See INSTALL file for general options of ./configure.
|
||||
|
||||
|
26
acinclude.m4
26
acinclude.m4
@ -1,7 +1,7 @@
|
||||
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 +16,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
|
||||
@ -141,10 +147,12 @@ AC_DEFUN([LIBISOFS_ASSERT_VERS_LIBS],
|
||||
LDFLAGS="$LDFLAGS -Wl,--version-script=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=libisofs/libisofs.ver"
|
||||
fi
|
||||
LDFLAGS="$libburnia_save_LDFLAGS"
|
||||
AC_SUBST(LIBLDFLAGS)
|
||||
])
|
||||
|
||||
|
||||
@ -198,3 +206,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"
|
||||
])
|
||||
|
||||
|
@ -1,10 +1,7 @@
|
||||
#!/bin/sh -x
|
||||
|
||||
aclocal
|
||||
aclocal -I .
|
||||
libtoolize --copy --force
|
||||
autoconf
|
||||
|
||||
# ts A61101 : libburn is not prepared for config.h
|
||||
# autoheader
|
||||
|
||||
automake --foreign --add-missing --copy --include-deps
|
||||
|
96
configure.ac
96
configure.ac
@ -1,4 +1,4 @@
|
||||
AC_INIT([libisofs], [1.0.0], [http://libburnia-project.org])
|
||||
AC_INIT([libisofs], [1.4.6], [http://libburnia-project.org])
|
||||
AC_PREREQ([2.50])
|
||||
dnl AC_CONFIG_HEADER([config.h])
|
||||
|
||||
@ -8,6 +8,7 @@ AC_CANONICAL_TARGET
|
||||
LIBBURNIA_SET_FLAGS
|
||||
|
||||
AM_INIT_AUTOMAKE([subdir-objects])
|
||||
AC_CONFIG_MACRO_DIR([./])
|
||||
|
||||
dnl
|
||||
dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match
|
||||
@ -25,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
|
||||
@ -39,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=0
|
||||
LIBISOFS_MICRO_VERSION=0
|
||||
LIBISOFS_MINOR_VERSION=4
|
||||
LIBISOFS_MICRO_VERSION=6
|
||||
LIBISOFS_VERSION=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION.$LIBISOFS_MICRO_VERSION
|
||||
|
||||
AC_SUBST(LIBISOFS_MAJOR_VERSION)
|
||||
@ -50,10 +51,10 @@ AC_SUBST(LIBISOFS_VERSION)
|
||||
|
||||
dnl Libtool versioning
|
||||
LT_RELEASE=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION
|
||||
# 2011.01.16 development jump has not yet happened
|
||||
# SONAME = 44 - 38 = 6 . Library name = libisofs.6.38.0
|
||||
LT_CURRENT=44
|
||||
LT_AGE=38
|
||||
# 2016.07.01 development jump has not yet happened
|
||||
# SONAME = 88 - 82 = 6 . Library name = libisofs.6.82.0
|
||||
LT_CURRENT=88
|
||||
LT_AGE=82
|
||||
LT_REVISION=0
|
||||
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
|
||||
|
||||
@ -91,7 +92,7 @@ LIBBURNIA_ASSERT_ICONV
|
||||
|
||||
AC_PROG_LIBTOOL
|
||||
AC_SUBST(LIBTOOL_DEPS)
|
||||
LIBTOOL="$LIBTOOL --silent"
|
||||
# LIBTOOL="$LIBTOOL --silent"
|
||||
|
||||
AC_PROG_INSTALL
|
||||
|
||||
@ -113,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])],
|
||||
@ -139,7 +150,7 @@ if test x$enable_debug != xyes; then
|
||||
CFLAGS="-DNDEBUG $CFLAGS"
|
||||
else
|
||||
if test x$GCC = xyes; then
|
||||
CFLAGS="-g -pedantic -Wall $CFLAGS"
|
||||
CFLAGS="-g -pedantic -Wall -Wextra -Wno-unused-parameter -Wno-char-subscripts $CFLAGS"
|
||||
fi
|
||||
CFLAGS="-DDEBUG $CFLAGS"
|
||||
fi
|
||||
@ -159,31 +170,68 @@ LIBBURNIA_SET_PKGCONFIG
|
||||
dnl Add compiler-specific flags
|
||||
|
||||
AC_ARG_ENABLE(libacl,
|
||||
[ --enable-libacl Enable use of libacl by libisofs, default=yes],
|
||||
[ --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
|
||||
AC_CHECK_HEADER(sys/acl.h, AC_CHECK_LIB(acl, acl_to_text, , LIBACL_DEF= ), LIBACL_DEF= )
|
||||
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
|
||||
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 - B51212
|
||||
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)
|
||||
XATTR_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= )
|
||||
XATTR_DEF="-DLibisofs_with_aaip_xattR"
|
||||
AC_CHECK_HEADER(attr/xattr.h, AC_CHECK_LIB(c, listxattr, X= ,
|
||||
XATTR_DEF= ), XATTR_DEF= )
|
||||
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
|
||||
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
|
||||
XATTR_DEF=
|
||||
echo "disabled local processing of extended file attributes"
|
||||
fi
|
||||
AC_SUBST(XATTR_DEF)
|
||||
|
||||
|
334
demo/demo.c
334
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",
|
||||
@ -50,6 +52,7 @@ static char helptext[][80] = {
|
||||
#include <fcntl.h>
|
||||
#include <err.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#ifndef PATH_MAX
|
||||
@ -57,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
|
||||
@ -94,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);
|
||||
@ -355,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);
|
||||
@ -365,14 +385,18 @@ 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;
|
||||
}
|
||||
|
||||
iso_write_opts_free(opts);
|
||||
|
||||
while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
|
||||
fwrite(buf, 1, 2048, fp);
|
||||
result = fwrite(buf, 1, 2048, fp);
|
||||
if (result < 2048) {
|
||||
printf ("Cannot write block. errno= %d\n", errno);
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
burn_src->free_data(burn_src);
|
||||
@ -440,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);
|
||||
@ -468,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");
|
||||
@ -517,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;
|
||||
}
|
||||
|
||||
|
||||
@ -537,79 +577,101 @@ int gesture_iso_read(int argc, char **argv)
|
||||
|
||||
int gesture_iso_cat(int argc, char **argv)
|
||||
{
|
||||
int res;
|
||||
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) {
|
||||
fwrite(buf, 1, res, stdout);
|
||||
}
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Error reading, err = %d\n", res);
|
||||
return 1;
|
||||
write_ret = fwrite(buf, 1, res, stdout);
|
||||
if (write_ret < res) {
|
||||
printf ("Cannot write block to stdout. errno= %d\n", errno);
|
||||
iso_file_source_close(file);
|
||||
ret = 1; goto ex;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -623,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);
|
||||
@ -643,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);
|
||||
@ -665,54 +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) {
|
||||
fwrite(buf, 1, 2048, fp);
|
||||
result = fwrite(buf, 1, 2048, fp);
|
||||
if (result < 2048) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -726,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) {
|
||||
@ -753,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);
|
||||
@ -781,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;
|
||||
}
|
||||
|
||||
@ -808,25 +904,39 @@ 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) {
|
||||
fwrite(buf, 1, 2048, fp);
|
||||
result = fwrite(buf, 1, 2048, fp);
|
||||
if (result < 2048) {
|
||||
printf ("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 (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;
|
||||
}
|
||||
|
||||
|
||||
|
1123
doc/boot_sectors.txt
1123
doc/boot_sectors.txt
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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
|
||||
@ -1143,7 +1119,8 @@ HIDE_UNDOC_RELATIONS = YES
|
||||
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
|
||||
# have no effect if this option is set to NO (the default)
|
||||
|
||||
HAVE_DOT = YES
|
||||
# ts B10415: dot causes sigsegv on Debian buildd
|
||||
HAVE_DOT = NO
|
||||
|
||||
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
|
||||
# will generate a graph for each documented class showing the direct and
|
||||
|
187
doc/iso_hybrid_fs.txt
Normal file
187
doc/iso_hybrid_fs.txt
Normal file
@ -0,0 +1,187 @@
|
||||
|
||||
Overview of ISO 9660 hybrid filesystems as libisofs output
|
||||
|
||||
by Thomas Schmitt - mailto:scdbackup@gmx.net
|
||||
Libburnia project - mailto:libburn-hackers@pykix.org
|
||||
07 Jun 2012
|
||||
|
||||
|
||||
The overall framework for the filesystem images produced by libisofs is given
|
||||
by ECMA-119, which is also known as ISO 9660. The hybrid aspect is the
|
||||
opportunity to add access structures of other filesystems.
|
||||
|
||||
The framework suggests a logical block size of 2048 and divides the space of
|
||||
filesystem blocks into several parts:
|
||||
|
||||
- The System Area. Beginning at the image start block.
|
||||
32 KiB of arbitrary data, which are not considered to be
|
||||
part of structure or payload of the ISO image.
|
||||
|
||||
- The Volume Descriptors. Beginning at image start block + 16.
|
||||
The Primary Volume Descriptor block is the starting point of the ECMA-119
|
||||
tree of directories and files. Among other information, it records the size
|
||||
of the image block space. Other descriptor blocks may lead to boot images
|
||||
or to the directory trees of add-on filesystems (e.g. Joliet).
|
||||
|
||||
- The area of directory structures and data file content.
|
||||
libisofs divides it into two sub areas:
|
||||
|
||||
- Directory structures.
|
||||
They record the file names and attributes of the ECMA-119 tree and
|
||||
of eventual add-on filesystem.
|
||||
|
||||
- Data file content.
|
||||
The blocks in this area are referred by zero or more file entries in the
|
||||
directory trees. They store the data content or regular files. Start block
|
||||
address of a file and exact byte count are stored in the trees.
|
||||
|
||||
|
||||
libisofs may slide-in some data blocks which are neither part of the structure
|
||||
nor part of file content. See doc/checksums.txt, Checksum Array, Checksum Tags.
|
||||
In the same way, the superblocks of other filesystems could be inserted into
|
||||
the image.
|
||||
|
||||
The only block addresses which are fixely occupied are image_start+16 (Primary
|
||||
Volume Descriptor) and image_start+17 (first possible position of Volume
|
||||
Descriptor Set Terminator).
|
||||
Nevertheless, libisofs considers as reserved the blocks image_start+16 to
|
||||
image_start+31, because add-ons like El Torito, Joliet, or ISO 9660:1999
|
||||
need their own volume descriptors stored before the volume descriptor set
|
||||
terminator block. Only one volume descriptor per add-on filesystem may be
|
||||
written there, and its exact position will be chosen by libisofs.
|
||||
|
||||
|
||||
The System Area in image_start to image_start+15 may be used for a partition
|
||||
table or the superblock of an additional filesystem structure.
|
||||
Another place for superblocks is after image_start+31. E.g. UDF stores its
|
||||
Anchor at block address 256, or at media_size - 1 - 256, or at media_size - 1.
|
||||
|
||||
In both cases the superblocks would point to filesystem-specific data which
|
||||
are stored in the area of directory structures. These data would then refer to
|
||||
the same file contents as the ECMA-119 directory structure.
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
What libisofs needs to get implemented for a new add-on filesystem:
|
||||
|
||||
The emerging overall image is represented by an Ecma119Image object.
|
||||
This is an instance of quite fat struct ecma119_image which, among many
|
||||
others, holds some parameters which are specific to the implemented add-on
|
||||
filesystems. It is defined in libisofs/ecma119.h.
|
||||
It gets programmed by applications via API calls for IsoWriteOpts which is
|
||||
defined as struct iso_write_opts in libisofs/ecma119.h.
|
||||
|
||||
|
||||
The content of the System Area may be submitted opaquely via
|
||||
Ecma119Image.system_area_data or it may get generated underneath
|
||||
libisofs/system_area.c:iso_write_system_area() by a specific "System area type"
|
||||
in Ecma119Image.system_area_options. The latter happens when the block adresses
|
||||
of all components, directories, and files are determined. (One may have to
|
||||
dig deep in the graph of objects to obtain everything.)
|
||||
|
||||
If a new system area type is needed, then it has to be documented in
|
||||
libisofs/ecma119.h at struct ecma119_image.system_area_options and in
|
||||
libisofs/libisofs.h at call iso_write_opts_set_system_area(). See e.g.
|
||||
"MIPS Big Endian Volume Header".
|
||||
|
||||
libisofs/system_area.h offers an inner API to define partitions for Apple
|
||||
Partition Map (APM) and for GPT from within the compute_data_blocks methods
|
||||
of the IsoImageWriter objects (see below). If both get combined, then
|
||||
APM block size must be 2048. In this case, the partition entries of APM
|
||||
and GPT overwrite the following bytes of the submitted
|
||||
Ecma119Image.system_area_data:
|
||||
0x0000 to 0x0007 by { 0x45, 0x52, 0x08 0x00, 0xeb, 0x02, 0xff, 0xff}
|
||||
0x0200 to 0x02ff by GPT header block
|
||||
0x0800 to APM_end by APM blocks (APM_end = 2048*(Num_APM_partitions + 1)
|
||||
APM_end+1 to 0x7fff by GPT entries
|
||||
This offers still room for a PC-BIOS MBR which has essentially no-op commands
|
||||
in its first 8 bytes.
|
||||
If no GPT is desired, then the bytes after APM_end stay unaltered.
|
||||
If more modesty with overwriting is needed, then this would have to be caused
|
||||
by either a specialized system area type or by additional elements of the
|
||||
inner API for APM and GPT.
|
||||
|
||||
|
||||
The layout of the areas above image_start+16 is defined in function
|
||||
libisofs/ecma119.c:ecma119_image_new(). This is done by creating and
|
||||
registering writer objects.
|
||||
Writers are instances of typedef struct Iso_Image_Writer IsoImageWriter.
|
||||
The struct is defined in libisofs/writer.h.
|
||||
|
||||
The Joliet writer is a comprehensive example of an add-on filesystem writer.
|
||||
|
||||
First it gets counted for the allocation of the registration array
|
||||
if (target->joliet) {
|
||||
nwriters++;
|
||||
}
|
||||
|
||||
Later it gets created and registered
|
||||
if (target->joliet) {
|
||||
ret = joliet_writer_create(target);
|
||||
|
||||
The function libisofs/joliet.c:joliet_writer_create() accounts for one block
|
||||
that will hold the Joliet volume descriptor
|
||||
/* we need the volume descriptor */
|
||||
target->curblock++;
|
||||
Not all add-on filesystems will need a volume descriptor. Joliet does.
|
||||
|
||||
joliet_writer_create() further generates a tree of JolietNode objects by
|
||||
traversing the image model tree of IsoNode objects.
|
||||
ret = joliet_tree_create(target);
|
||||
If a JolietNode represents a regular file then it refers to an IsoFileSrc
|
||||
object, which represents its data content in the emerging image.
|
||||
struct Iso_File_Src is defined in libisofs/filesrc.h.
|
||||
|
||||
|
||||
libisofs will call the methods of the writer object when it computes the
|
||||
block addresses of the various image components, when it writes volume
|
||||
descriptors, when it writes directory trees, and when it finally disposes the
|
||||
Ecma119Image object.
|
||||
Before calling the first method, it will publish the number of data file
|
||||
content blocks in Ecma119Image.filesrc_blocks.
|
||||
|
||||
The method IsoImageWriter.compute_data_blocks() has to predict the storage
|
||||
needs in the area of directory trees.
|
||||
It computes and records Joliet-specific addresses and sizes:
|
||||
Ecma119Image.joliet_ndirs, Ecma119Image.joliet_l_path_table_pos,
|
||||
Ecma119Image.joliet_m_path_table_pos , Ecma119Image.joliet_path_table_size
|
||||
Ecma119Image.j_part_l_path_table_pos, Ecma119Image.j_part_m_path_table_pos
|
||||
as well as the sizes and block addresses of Joliet directories.
|
||||
It increases the counter of virtually written blocks:
|
||||
Ecma119Image.curblock
|
||||
which is used to determine the start addresses of the image parts and
|
||||
finally gives the overall image size.
|
||||
|
||||
The method IsoImageWriter.write_vol_desc() composes and writes the Joliet
|
||||
volume descriptor. (Such writing is not necessarily needed for add-on
|
||||
filesystems.)
|
||||
|
||||
IsoImageWriter.write_data() writes the records of the Joliet directory tree.
|
||||
This has to be exactly the same number of blocks by which Ecma119Image.curblock
|
||||
was increased during IsoImageWriter.compute_data_blocks().
|
||||
When it gets called, the number of content data extents, their sizes, and their
|
||||
addresses are known: JolietNode.IsoFileSrc->nsections, ->sections[].size,
|
||||
->sections[].block.
|
||||
struct iso_file_section is defined in libisofs/libisofs.h.
|
||||
|
||||
IsoImageWriter.free_data() disposes the writer and the JolietNode tree.
|
||||
|
||||
|
||||
Further examples for add-on writers are those created by:
|
||||
|
||||
hfsplus_writer_create() is in charge for initial part of an
|
||||
embedded HFS+ filesystem
|
||||
hfsplus_tail_writer_create() is in charge for trailing part of HFS+
|
||||
after the data file content area
|
||||
gpt_tail_writer_create() is in charge for the backup GPT near the
|
||||
end of the ISO image
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
This text is under
|
||||
Copyright (c) 2012 Thomas Schmitt <scdbackup@gmx.net>
|
||||
It shall only be modified in sync with libisofs. Please mail change requests to
|
||||
mailing list <libburn-hackers@pykix.org> or to the copyright holder in private.
|
||||
If you make use of the license to derive modified versions of libisofs then
|
||||
you are entitled to modify this text under that same license.
|
||||
|
@ -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
|
||||
@ -157,9 +155,10 @@ types. "system." is file system dependent and often restricted in the
|
||||
choice of names. "user." is portable and allows to choose about any name.
|
||||
|
||||
Namespace "isofs." is defined for internal use of AAIP enhanced ISO 9660
|
||||
file systems. Names in this namespace should be registered at libburnia.org.
|
||||
file systems. Names in this namespace should be registered at
|
||||
libburnia-project.org.
|
||||
|
||||
Further namespaces may be registered at libburnia.org.
|
||||
Further namespaces may be registered at libburnia-project.org.
|
||||
|
||||
The reserved start bytes of names have the following meaning
|
||||
0x01 escape reserved character at start of name
|
||||
@ -218,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
|
||||
@ -236,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.
|
||||
@ -444,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.
|
||||
|
@ -8,7 +8,9 @@
|
||||
|
||||
|
||||
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,6 +24,8 @@ 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 be attached to the root directory entry
|
||||
and be global for the whole image.
|
||||
|
||||
Format of Value:
|
||||
START_LEN | START_BYTES | END_LEN | END_BYTES |
|
||||
@ -63,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.
|
||||
@ -105,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
|
||||
@ -121,6 +126,75 @@ Registered:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name:
|
||||
isofs.hb
|
||||
|
||||
Purpose:
|
||||
Records the IsoHfsplusBlessings blessing of a IsoNode as defined
|
||||
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.
|
||||
|
||||
Format of Value:
|
||||
BLESSING
|
||||
This is a single byte out of {'p', 'i', 's', '9', 'x'} for
|
||||
ISO_HFSPLUS_BLESS_PPC_BOOTDIR, ISO_HFSPLUS_BLESS_INTEL_BOOTFILE,
|
||||
ISO_HFSPLUS_BLESS_SHOWFOLDER, ISO_HFSPLUS_BLESS_OS9_FOLDER,
|
||||
ISO_HFSPLUS_BLESS_OSX_FOLDER.
|
||||
|
||||
Example:
|
||||
{ 'p' }
|
||||
|
||||
Registered:
|
||||
07 Jun 2012 by Thomas Schmitt for xorriso.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Name:
|
||||
isofs.hx
|
||||
|
||||
Purpose:
|
||||
Records the iso_hfsplus_xinfo_data information as defined in libisofs.h.
|
||||
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.
|
||||
|
||||
Format of Value:
|
||||
VERSION_LEN | VERSION | CREATOR | TYPE
|
||||
VERSION_LEN complies to ISO 9660 Format section 7.1.1.
|
||||
The byte string VERSION begins with the most significant byte.
|
||||
VERSION == 0 is the only one that is currently defined. It assures the
|
||||
existence of 4 bytes CREATOR and 4 bytes TYPE.
|
||||
Higher versions will keep these 8 bytes and possibly add new ones.
|
||||
|
||||
Example:
|
||||
{ 1, 0, 'Y', 'Y', 'D', 'N', 'T', 'E', 'X', 'T' }
|
||||
|
||||
Registered:
|
||||
07 Jun 2012 by Thomas Schmitt for xorriso.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
|
||||
@ -132,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:
|
||||
@ -150,7 +224,7 @@ Registered:
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
This text is under
|
||||
Copyright (c) 2009 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Copyright (c) 2009 - 2011 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.
|
||||
|
@ -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,7 @@
|
||||
|
||||
To be included by aaip_0_2.c
|
||||
|
||||
Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2+
|
||||
Copyright (c) 2009 - 2011 Thomas Schmitt, libburnia project, GPLv2+
|
||||
|
||||
*/
|
||||
|
||||
@ -28,6 +28,29 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
/* ------------------------------ Inquiry --------------------------------- */
|
||||
|
||||
/* See also API iso_local_attr_support().
|
||||
@param flag
|
||||
Bitfield for control purposes
|
||||
bit0= inquire availability of ACL
|
||||
bit1= inquire availability of xattr
|
||||
bit2 - bit7= Reserved for future types.
|
||||
It is permissibile to set them to 1 already now.
|
||||
bit8 and higher: reserved, submit 0
|
||||
@return
|
||||
Bitfield corresponding to flag.
|
||||
bit0= ACL adapter is enabled
|
||||
bit1= xattr adapter is enabled
|
||||
bit2 - bit7= Reserved for future types.
|
||||
bit8 and higher: reserved, do not interpret these
|
||||
*/
|
||||
int aaip_local_attr_support(int flag)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------ Getters --------------------------------- */
|
||||
|
||||
/* Obtain the ACL of the given file in long text form.
|
||||
@ -89,8 +112,12 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||
continue;
|
||||
}
|
||||
/* Extended Attribute */
|
||||
if(!(flag & 4))
|
||||
return(-6);
|
||||
if(flag & 4)
|
||||
continue;
|
||||
if(!(flag & 8))
|
||||
if(strncmp(names[i], "user.", 5))
|
||||
continue;
|
||||
return(-6);
|
||||
}
|
||||
if(flag & 2)
|
||||
return(-6);
|
||||
|
@ -5,9 +5,9 @@
|
||||
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 Thomas Schmitt, libburnia project, GPLv2
|
||||
Copyright (c) 2009 - 2016 Thomas Schmitt, libburnia project, GPLv2+
|
||||
|
||||
*/
|
||||
|
||||
@ -24,15 +24,79 @@
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef Libisofs_with_aaip_acL
|
||||
/* It seems ACL is fixely integrated in FreeBSD libc. There is no libacl. */
|
||||
#define Libisofs_with_aaip_acL yes
|
||||
#endif
|
||||
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
#include <sys/acl.h>
|
||||
#endif
|
||||
|
||||
#ifdef Libisofs_with_freebsd_extattR
|
||||
#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 */
|
||||
|
||||
|
||||
/* ------------------------------ Inquiry --------------------------------- */
|
||||
|
||||
/* See also API iso_local_attr_support().
|
||||
@param flag
|
||||
Bitfield for control purposes
|
||||
bit0= inquire availability of ACL
|
||||
bit1= inquire availability of xattr
|
||||
bit2 - bit7= Reserved for future types.
|
||||
It is permissibile to set them to 1 already now.
|
||||
bit8 and higher: reserved, submit 0
|
||||
@return
|
||||
Bitfield corresponding to flag.
|
||||
bit0= ACL adapter is enabled
|
||||
bit1= xattr adapter is enabled
|
||||
bit2 - bit7= Reserved for future types.
|
||||
bit8 and higher: reserved, do not interpret these
|
||||
*/
|
||||
int aaip_local_attr_support(int flag)
|
||||
{
|
||||
int ret= 0;
|
||||
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
if(flag & 1)
|
||||
ret|= 1;
|
||||
#endif
|
||||
#ifdef Libisofs_with_freebsd_extattR
|
||||
if(flag & 2)
|
||||
ret|= 2;
|
||||
#endif
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
#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 --------------------------------- */
|
||||
|
||||
@ -137,6 +201,359 @@ int aaip_get_acl_text(char *path, char **text, int flag)
|
||||
}
|
||||
|
||||
|
||||
#ifndef Libisofs_old_freebsd_acl_adapteR
|
||||
|
||||
#ifdef Libisofs_with_freebsd_extattR
|
||||
|
||||
/*
|
||||
@param flag Bitfield for control purposes
|
||||
bit5= in case of symbolic link: inquire link target
|
||||
*/
|
||||
static int aaip_extattr_make_list(char *path, int attrnamespace,
|
||||
char **list, ssize_t *list_size, int flag)
|
||||
{
|
||||
*list= NULL;
|
||||
*list_size= 0;
|
||||
|
||||
/* man 2 extattr_list_file:
|
||||
If data is NULL in a call to extattr_get_file() and extattr_list_file()
|
||||
then the size of defined extended attribute data will be returned,
|
||||
*/
|
||||
if(flag & 32) /* follow link */
|
||||
*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(! aaip_extattr_path_supp(path, 0)) {
|
||||
*list_size = 0;
|
||||
return(2);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
if(*list_size == 0)
|
||||
return(2);
|
||||
*list= calloc(*list_size, 1);
|
||||
if(*list == NULL)
|
||||
return(-1);
|
||||
if(flag & 32)
|
||||
*list_size= extattr_list_file(path, attrnamespace, *list,
|
||||
(size_t) *list_size);
|
||||
else
|
||||
*list_size= extattr_list_link(path, attrnamespace, *list,
|
||||
(size_t) *list_size);
|
||||
if(*list_size == -1)
|
||||
return(0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= preserve existing namelist content
|
||||
bit1= ignore names with NUL rather than returning error
|
||||
*/
|
||||
static int aaip_extattr_make_namelist(char *path, char *attrnamespace,
|
||||
char *list, ssize_t list_size,
|
||||
char **namelist, ssize_t *namelist_size,
|
||||
ssize_t *num_names, int flag)
|
||||
{
|
||||
int i, j, len, new_bytes= 0, space_len;
|
||||
char *new_list= NULL, *wpt;
|
||||
|
||||
if(!(flag & 1)) {
|
||||
*namelist= NULL;
|
||||
*namelist_size= 0;
|
||||
*num_names= 0;
|
||||
}
|
||||
if(list_size <= 0)
|
||||
return(1);
|
||||
space_len= strlen(attrnamespace);
|
||||
for(i= 0; i < list_size; i+= len + 1) {
|
||||
len= *((unsigned char *) (list + i));
|
||||
if(len == 0)
|
||||
return ISO_AAIP_BAD_ATTR_NAME; /* empty name is reserved for ACL */
|
||||
for(j= 0; j < len; j++)
|
||||
if(list[i + 1 + j] == 0) {
|
||||
if(flag & 2)
|
||||
continue;
|
||||
return ISO_AAIP_BAD_ATTR_NAME; /* names may not contain 0-bytes */
|
||||
}
|
||||
new_bytes+= space_len + 1 + len + 1;
|
||||
}
|
||||
if((flag & 1) && *namelist_size > 0)
|
||||
new_bytes+= *namelist_size;
|
||||
new_list= calloc(new_bytes, 1);
|
||||
if(new_list == NULL)
|
||||
return(ISO_OUT_OF_MEM);
|
||||
wpt= new_list;
|
||||
if((flag & 1) && *namelist_size > 0) {
|
||||
memcpy(new_list, *namelist, *namelist_size);
|
||||
wpt= new_list + *namelist_size;
|
||||
}
|
||||
for(i= 0; i < list_size; i+= len + 1) {
|
||||
len= *((unsigned char *) (list + i));
|
||||
if(flag & 2) {
|
||||
for(j= 0; j < len; j++)
|
||||
if(list[i + j] == 0)
|
||||
continue;
|
||||
}
|
||||
memcpy(wpt, attrnamespace, space_len);
|
||||
wpt[space_len]= '.';
|
||||
wpt+= space_len + 1;
|
||||
memcpy(wpt, list + i + 1, len);
|
||||
wpt+= len;
|
||||
*(wpt++)= 0;
|
||||
(*num_names)++;
|
||||
}
|
||||
if((flag & 1) && *namelist != NULL)
|
||||
free(*namelist);
|
||||
*namelist= new_list;
|
||||
*namelist_size= new_bytes;
|
||||
return(1);
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_freebsd_extattR */
|
||||
|
||||
|
||||
/* 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 values Will return an array of pointers to 8-bit values
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= obtain ACL (access and eventually default)
|
||||
bit1= use numeric ACL qualifiers rather than names
|
||||
bit2= do not obtain attributes other than ACL
|
||||
bit3= do not ignore eventual non-user attributes
|
||||
I.e. those with a name which does not begin
|
||||
by "user."
|
||||
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
|
||||
<=0 error
|
||||
-1= out of memory
|
||||
-2= program error with prediction of result size
|
||||
-3= error with conversion of name to uid or gid
|
||||
*/
|
||||
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 *a_acl= NULL;
|
||||
char *a_acl_text= NULL;
|
||||
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;
|
||||
ssize_t sys_list_size= 0;
|
||||
int attrnamespace;
|
||||
int acl_names= 0;
|
||||
#endif
|
||||
|
||||
if(flag & (1 << 15)) { /* Free memory */
|
||||
{ret= 1; goto ex;}
|
||||
}
|
||||
|
||||
*num_attrs= 0;
|
||||
*names= NULL;
|
||||
*value_lengths= NULL;
|
||||
*values= NULL;
|
||||
|
||||
/* Set up arrays */
|
||||
|
||||
#ifdef Libisofs_with_freebsd_extattR
|
||||
|
||||
if(!(flag & 4)) { /* Get extattr names */
|
||||
|
||||
/* Linux : Names are encoded as name NUL
|
||||
FreeBSD: Names are encoded as length_byte:chars (no NUL)
|
||||
AAIP demands names not to contain NUL bytes.
|
||||
*/
|
||||
|
||||
/* Obtain lists of names
|
||||
Must be done separately for namespaces. See man 9 extattr :
|
||||
EXTATTR_NAMESPACE_USER , EXTATTR_NAMESPACE_SYSTEM
|
||||
Must then be marked by "user." and "system." for libisofs use.
|
||||
*/
|
||||
ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_USER,
|
||||
&user_list, &user_list_size, flag & 32);
|
||||
if(ret <= 0)
|
||||
{ret= -1; goto ex;}
|
||||
if(flag & 8) {
|
||||
ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_SYSTEM,
|
||||
&sys_list, &sys_list_size, flag & 32);
|
||||
if(ret <= 0)
|
||||
{ret= -1; goto ex;}
|
||||
}
|
||||
|
||||
/* Check for NUL in names, convert into a linuxish list of namespace.name */
|
||||
ret= aaip_extattr_make_namelist(path, "user", user_list, user_list_size,
|
||||
&list, &list_size, &num_names, 0);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
ret= aaip_extattr_make_namelist(path, "system", sys_list, sys_list_size,
|
||||
&list, &list_size, &num_names, 1);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_freebsd_extattR */
|
||||
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
if(flag & 1) {
|
||||
num_names++;
|
||||
|
||||
#ifdef Libisofs_with_freebsd_extattR
|
||||
acl_names= 1;
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
if(num_names == 0)
|
||||
{ret= 1; goto ex;}
|
||||
(*names)= calloc(num_names, sizeof(char *));
|
||||
(*value_lengths)= calloc(num_names, sizeof(size_t));
|
||||
(*values)= calloc(num_names, sizeof(char *));
|
||||
if(*names == NULL || *value_lengths == NULL || *values == NULL)
|
||||
{ret= -1; goto ex;}
|
||||
|
||||
for(i= 0; i < num_names; i++) {
|
||||
(*names)[i]= NULL;
|
||||
(*values)[i]= NULL;
|
||||
(*value_lengths)[i]= 0;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_freebsd_extattR
|
||||
|
||||
if(!(flag & 4)) { /* Get xattr values */
|
||||
for(i= 0; i < list_size && (size_t) num_names - acl_names > *num_attrs;
|
||||
i+= strlen(list + i) + 1) {
|
||||
if(!(flag & 8))
|
||||
if(strncmp(list + i, "user.", 5))
|
||||
continue;
|
||||
(*names)[(*num_attrs)++]= strdup(list + i);
|
||||
if((*names)[(*num_attrs) - 1] == NULL)
|
||||
{ret= -1; goto ex;}
|
||||
}
|
||||
|
||||
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)
|
||||
{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;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_freebsd_extattR */
|
||||
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
|
||||
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 */
|
||||
ret= aaip_encode_acl(a_acl_text, (mode_t) 0, &a_acl_len, &a_acl, flag & 2);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
|
||||
/* Note: There are no default-ACL in FreeBSD */
|
||||
|
||||
/* Set as attribute with empty name */;
|
||||
(*names)[*num_attrs]= strdup("");
|
||||
if((*names)[*num_attrs] == NULL)
|
||||
{ret= -1; goto ex;}
|
||||
(*values)[*num_attrs]= (char *) a_acl;
|
||||
a_acl= NULL;
|
||||
(*value_lengths)[*num_attrs]= a_acl_len;
|
||||
(*num_attrs)++;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_aaip_acL */
|
||||
|
||||
ret= 1;
|
||||
ex:;
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
if(a_acl != NULL)
|
||||
free(a_acl);
|
||||
if(a_acl_text != NULL)
|
||||
aaip_get_acl_text("", &a_acl_text, 1 << 15); /* free */
|
||||
#endif
|
||||
#ifdef Libisofs_with_freebsd_extattR
|
||||
if(list != NULL)
|
||||
free(list);
|
||||
if(user_list != NULL)
|
||||
free(user_list);
|
||||
if(sys_list != NULL)
|
||||
free(sys_list);
|
||||
#endif
|
||||
|
||||
if(ret <= 0 || (flag & (1 << 15))) {
|
||||
if(*names != NULL) {
|
||||
for(i= 0; (size_t) i < *num_attrs; i++)
|
||||
free((*names)[i]);
|
||||
free(*names);
|
||||
}
|
||||
*names= NULL;
|
||||
if(*value_lengths != NULL)
|
||||
free(*value_lengths);
|
||||
*value_lengths= NULL;
|
||||
if(*values != NULL) {
|
||||
for(i= 0; (size_t) i < *num_attrs; i++)
|
||||
free((*values)[i]);
|
||||
free(*values);
|
||||
}
|
||||
*values= NULL;
|
||||
*num_attrs= 0;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
#else /* ! Libisofs_old_freebsd_acl_adapteR */
|
||||
|
||||
/* Obtain the Extended Attributes and/or the ACLs of the given file in a form
|
||||
that is ready for aaip_encode().
|
||||
|
||||
@ -152,20 +569,28 @@ int aaip_get_acl_text(char *path, char **text, int flag)
|
||||
bit0= obtain ACL (access and eventually default)
|
||||
bit1= use numeric ACL qualifiers rather than names
|
||||
bit2= do not encode attributes other than ACL
|
||||
bit3= -reserved-
|
||||
bit3= do not ignore eventual non-user attributes
|
||||
I.e. those which are not from name space
|
||||
EXTATTR_NAMESPACE_USER
|
||||
bit4= do not return trivial ACL that matches st_mode
|
||||
bit15= free memory of names, value_lengths, values
|
||||
@return >0 ok
|
||||
<=0 error
|
||||
-1= out of memory
|
||||
-2= program error with prediction of result size
|
||||
-3= error with conversion of name to uid or gid
|
||||
*/
|
||||
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;
|
||||
size_t a_acl_len= 0, acl_len= 0;
|
||||
unsigned char *a_acl= NULL, *d_acl= NULL, *acl= NULL;
|
||||
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
size_t a_acl_len= 0;
|
||||
unsigned char *a_acl= NULL;
|
||||
char *acl_text= NULL;
|
||||
#endif
|
||||
|
||||
if(flag & (1 << 15)) { /* Free memory */
|
||||
{ret= 1; goto ex;}
|
||||
@ -211,25 +636,26 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
||||
(*names)[*num_attrs]= strdup("");
|
||||
if((*names)[*num_attrs] == NULL)
|
||||
{ret= -1; goto ex;}
|
||||
(*values)[*num_attrs]= (char *) acl;
|
||||
(*value_lengths)[*num_attrs]= acl_len;
|
||||
(*values)[*num_attrs]= (char *) a_acl;
|
||||
a_acl= NULL;
|
||||
(*value_lengths)[*num_attrs]= a_acl_len;
|
||||
(*num_attrs)++;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_aaip_acL */
|
||||
#endif /* ! Libisofs_with_aaip_acL */
|
||||
|
||||
ret= 1;
|
||||
ex:;
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
if(a_acl != NULL)
|
||||
free(a_acl);
|
||||
if(d_acl != NULL)
|
||||
free(d_acl);
|
||||
if(acl_text != NULL)
|
||||
aaip_get_acl_text("", &acl_text, 1 << 15); /* free */
|
||||
#endif /* Libisofs_with_aaip_acL */
|
||||
|
||||
if(ret <= 0 || (flag & (1 << 15))) {
|
||||
if(*names != NULL) {
|
||||
for(i= 0; i < *num_attrs; i++)
|
||||
for(i= 0; i < (ssize_t) *num_attrs; i++)
|
||||
free((*names)[i]);
|
||||
free(*names);
|
||||
}
|
||||
@ -238,18 +664,18 @@ ex:;
|
||||
free(*value_lengths);
|
||||
*value_lengths= NULL;
|
||||
if(*values != NULL) {
|
||||
for(i= 0; i < *num_attrs; i++)
|
||||
for(i= 0; i < (ssize_t) *num_attrs; i++)
|
||||
free((*values)[i]);
|
||||
free(*values);
|
||||
}
|
||||
if(acl != NULL)
|
||||
free(acl);
|
||||
*values= NULL;
|
||||
*num_attrs= 0;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
#endif /* Libisofs_old_freebsd_acl_adapteR */
|
||||
|
||||
|
||||
/* ------------------------------ Setters --------------------------------- */
|
||||
|
||||
@ -259,9 +685,14 @@ ex:;
|
||||
@param text The input text (0 terminated, ACL long text form)
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= set default ACL rather than access ACL
|
||||
bit5= in case of symbolic link: manipulate link target
|
||||
bit6= tolerate inappropriate presence or absence of
|
||||
directory default ACL
|
||||
@return > 0 ok
|
||||
0 no suitable ACL manipulation adapter available
|
||||
-1 failure of system ACL service (see errno)
|
||||
-2 ACL support not enabled at compile time
|
||||
-2 attempt to manipulate ACL of a symbolic link
|
||||
without bit5 or with no suitable link target
|
||||
*/
|
||||
int aaip_set_acl_text(char *path, char *text, int flag)
|
||||
{
|
||||
@ -302,13 +733,200 @@ ex:
|
||||
|
||||
#else /* Libisofs_with_aaip_acL */
|
||||
|
||||
return(-2);
|
||||
return(0);
|
||||
|
||||
#endif /* ! Libisofs_with_aaip_acL */
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifndef Libisofs_old_freebsd_acl_adapteR
|
||||
|
||||
#ifdef Libisofs_with_freebsd_extattR
|
||||
|
||||
/*
|
||||
@param flag Bitfield for control purposes
|
||||
bit5= in case of symbolic link: manipulate link target
|
||||
*/
|
||||
static int aaip_extattr_delete_names(char *path, int attrnamespace,
|
||||
char *list, ssize_t list_size, int flag)
|
||||
{
|
||||
int len;
|
||||
char name[256];
|
||||
ssize_t value_ret, i;
|
||||
|
||||
for(i= 0; i < list_size; i+= len + 1) {
|
||||
len= *((unsigned char *) (list + i));
|
||||
if(len > 0)
|
||||
strncpy(name, list + i + 1, len);
|
||||
name[len]= 0;
|
||||
if(flag & 32)
|
||||
value_ret= extattr_delete_file(path, attrnamespace, name);
|
||||
else
|
||||
value_ret= extattr_delete_file(path, attrnamespace, name);
|
||||
if(value_ret == -1)
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_freebsd_extattR */
|
||||
|
||||
|
||||
/* Bring the given attributes and/or ACLs into effect with the given file.
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= decode and set ACLs
|
||||
bit1= first clear all existing attributes of the file
|
||||
bit2= do not set attributes other than ACLs
|
||||
bit3= do not ignore eventual non-user attributes.
|
||||
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 absence of
|
||||
directory default ACL
|
||||
@return 1 success
|
||||
-1 error memory allocation
|
||||
-2 error with decoding of ACL
|
||||
-3 error with setting ACL
|
||||
-4 error with setting attribute
|
||||
-5 error with deleting attributes
|
||||
-6 support of xattr not enabled at compile time
|
||||
-7 support of ACL not enabled at compile time
|
||||
-8 unsupported xattr namespace
|
||||
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)
|
||||
{
|
||||
int ret, has_default_acl= 0;
|
||||
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;
|
||||
int attrnamespace;
|
||||
#endif
|
||||
|
||||
#ifdef Libisofs_with_freebsd_extattR
|
||||
|
||||
if(flag & 2) { /* Delete all file attributes */
|
||||
ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_USER,
|
||||
&user_list, &user_list_size, flag & 32);
|
||||
if(ret <= 0)
|
||||
{ret= -1; goto ex;}
|
||||
ret= aaip_extattr_delete_names(path, EXTATTR_NAMESPACE_USER,
|
||||
user_list, user_list_size, flag & 32);
|
||||
if(ret <= 0)
|
||||
{ret= -5; goto ex;}
|
||||
if(flag & 8) {
|
||||
ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_SYSTEM,
|
||||
&sys_list, &sys_list_size, flag & 32);
|
||||
if(ret <= 0)
|
||||
{ret= -5; goto ex;}
|
||||
ret= aaip_extattr_delete_names(path, EXTATTR_NAMESPACE_SYSTEM,
|
||||
sys_list, sys_list_size, flag & 32);
|
||||
if(ret <= 0)
|
||||
{ret= -5; goto ex;}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_freebsd_extattR */
|
||||
|
||||
for(i= 0; i < num_attrs; i++) {
|
||||
if(names[i] == NULL || values[i] == NULL)
|
||||
continue;
|
||||
if(names[i][0] == 0) { /* ACLs */
|
||||
if(flag & 1)
|
||||
acl_idx= i + 1;
|
||||
continue;
|
||||
}
|
||||
/* Extended Attribute */
|
||||
if(flag & 4)
|
||||
continue;
|
||||
|
||||
#ifdef Libisofs_with_freebsd_extattR
|
||||
|
||||
if(strncmp(names[i], "user.", 5) == 0) {
|
||||
attrnamespace= EXTATTR_NAMESPACE_USER;
|
||||
namept= names[i] + 5;
|
||||
} else if(strncmp(names[i], "isofs.", 6) == 0 || !(flag & 8)) {
|
||||
continue;
|
||||
} else if(strncmp(names[i], "system.", 7) == 0) {
|
||||
attrnamespace= EXTATTR_NAMESPACE_SYSTEM;
|
||||
namept= names[i] + 7;
|
||||
} else {
|
||||
{ret= -8; goto ex;}
|
||||
}
|
||||
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
|
||||
|
||||
if(strncmp(names[i], "user.", 5) == 0)
|
||||
;
|
||||
else if(strncmp(names[i], "isofs.", 6) == 0 || !(flag & 8))
|
||||
continue;
|
||||
{ret= -6; goto ex;}
|
||||
|
||||
#endif /* Libisofs_with_freebsd_extattR */
|
||||
|
||||
}
|
||||
|
||||
/* Decode ACLs */
|
||||
if(acl_idx == 0)
|
||||
{ret= 1; goto ex;}
|
||||
i= acl_idx - 1;
|
||||
|
||||
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
||||
&consumed, NULL, 0, &acl_text_fill, 1);
|
||||
if(ret < -3)
|
||||
goto ex;
|
||||
if(ret <= 0)
|
||||
{ret= -2; goto ex;}
|
||||
acl_text= calloc(acl_text_fill, 1);
|
||||
if(acl_text == NULL)
|
||||
{ret= -1; goto ex;}
|
||||
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
||||
&consumed, acl_text, acl_text_fill, &acl_text_fill, 0);
|
||||
if(ret < -3)
|
||||
goto ex;
|
||||
if(ret <= 0)
|
||||
{ret= -2; goto ex;}
|
||||
has_default_acl= (ret == 2);
|
||||
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
ret= aaip_set_acl_text(path, acl_text, flag & (32 | 64));
|
||||
if(ret <= 0)
|
||||
{ret= -3; goto ex;}
|
||||
#else
|
||||
{ret= -7; goto ex;}
|
||||
#endif
|
||||
|
||||
if(has_default_acl && !(flag & 64))
|
||||
{ret= -3; goto ex;}
|
||||
|
||||
ret= 1;
|
||||
ex:;
|
||||
if(acl_text != NULL)
|
||||
free(acl_text);
|
||||
#ifdef Libisofs_with_freebsd_extattR
|
||||
if(user_list != NULL)
|
||||
free(user_list);
|
||||
if(sys_list != NULL)
|
||||
free(sys_list);
|
||||
#endif /* Libisofs_with_freebsd_extattR */
|
||||
return(ret);
|
||||
}
|
||||
|
||||
#else /* ! Libisofs_old_freebsd_acl_adapteR */
|
||||
|
||||
|
||||
/* Bring the given attributes and/or ACLs into effect with the given file.
|
||||
|
||||
Note: There are no Extended Attributes in FreeBSD. So only ACL get set.
|
||||
@ -317,6 +935,9 @@ ex:
|
||||
bit0= decode and set ACLs
|
||||
( bit1= first clear all existing attributes of the file )
|
||||
( bit2= do not set attributes other than ACLs )
|
||||
( bit3= do not ignore eventual non-user attributes.
|
||||
I.e. those with a name which does not begin
|
||||
by "user." )
|
||||
@return 1 success
|
||||
-1 error memory allocation
|
||||
-2 error with decoding of ACL
|
||||
@ -338,6 +959,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||
continue;
|
||||
if(names[i][0] == 0) { /* Decode ACLs */
|
||||
/* access ACL */
|
||||
if(!(flag & 1))
|
||||
continue;
|
||||
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
||||
&consumed, NULL, 0, &acl_text_fill, 1);
|
||||
if(ret <= 0)
|
||||
@ -379,8 +1002,14 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||
if(ret <= 0)
|
||||
{ret= -3; goto ex;}
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
if(flag & 4)
|
||||
continue;
|
||||
if(!(flag & 8))
|
||||
if(strncmp(names[i], "user.", 5))
|
||||
continue;
|
||||
was_xattr= 1;
|
||||
}
|
||||
}
|
||||
ret= 1;
|
||||
if(was_xattr)
|
||||
@ -393,4 +1022,5 @@ ex:;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
#endif /* Libisofs_old_freebsd_acl_adapteR */
|
||||
|
||||
|
@ -5,9 +5,9 @@
|
||||
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 Thomas Schmitt, libburnia project, GPLv2+
|
||||
Copyright (c) 2009 - 2016 Thomas Schmitt, libburnia project, GPLv2+
|
||||
|
||||
*/
|
||||
|
||||
@ -34,6 +34,40 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* ------------------------------ Inquiry --------------------------------- */
|
||||
|
||||
/* See also API iso_local_attr_support().
|
||||
@param flag
|
||||
Bitfield for control purposes
|
||||
bit0= inquire availability of ACL
|
||||
bit1= inquire availability of xattr
|
||||
bit2 - bit7= Reserved for future types.
|
||||
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
|
||||
bit0= ACL adapter is enabled
|
||||
bit1= xattr adapter is enabled
|
||||
bit2 - bit7= Reserved for future types.
|
||||
bit8 and higher: reserved, do not interpret these
|
||||
*/
|
||||
int aaip_local_attr_support(int flag)
|
||||
{
|
||||
int ret= 0;
|
||||
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
if(flag & 1)
|
||||
ret|= 1;
|
||||
#endif
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
if(flag & 2)
|
||||
ret|= 2;
|
||||
#endif
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------ Getters --------------------------------- */
|
||||
|
||||
/* Obtain the ACL of the given file in long text form.
|
||||
@ -55,7 +89,7 @@
|
||||
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)
|
||||
{
|
||||
@ -144,21 +178,28 @@ int aaip_get_acl_text(char *path, char **text, int flag)
|
||||
bit15= free memory of names, value_lengths, values
|
||||
@return >0 ok
|
||||
<=0 error
|
||||
-1= out of memory
|
||||
-2= program error with prediction of result size
|
||||
-3= error with conversion of name to uid or gid
|
||||
*/
|
||||
int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
||||
size_t **value_lengths, char ***values, int flag)
|
||||
{
|
||||
int ret;
|
||||
char *list= NULL;
|
||||
ssize_t list_size= 0, i, num_names= 0;
|
||||
unsigned char *acl= NULL;
|
||||
char *a_acl_text= NULL, *d_acl_text= NULL;
|
||||
|
||||
#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
|
||||
ssize_t value_ret, retry= 0;
|
||||
char *list= NULL;
|
||||
ssize_t value_ret, retry= 0, 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 */
|
||||
@ -170,40 +211,51 @@ 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 */
|
||||
if(!(flag & 4)) { /* Get xattr names */
|
||||
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
|
||||
if(!(flag & 4)) { /* Get xattr names */
|
||||
if(flag & 32)
|
||||
list_size= listxattr(path, list, 0);
|
||||
else
|
||||
list_size= llistxattr(path, list, 0);
|
||||
if(list_size == -1)
|
||||
{ret= -1; goto ex;}
|
||||
list= calloc(list_size, 1);
|
||||
if(list == NULL)
|
||||
{ret= -1; goto ex;}
|
||||
if(flag & 32)
|
||||
list_size= listxattr(path, list, list_size);
|
||||
else
|
||||
list_size= llistxattr(path, list, list_size);
|
||||
if(list_size == -1)
|
||||
{ret= -1; goto ex;}
|
||||
|
||||
#else /* Libisofs_with_aaip_xattR */
|
||||
|
||||
list= strdup("");
|
||||
|
||||
#endif /* ! Libisofs_with_aaip_xattR */
|
||||
|
||||
if(list_size == -1) {
|
||||
if(errno == ENOSYS) /* Function not implemented */
|
||||
list_size= 0; /* Handle as if xattr was disabled at compile time */
|
||||
else
|
||||
{ret= -1; goto ex;}
|
||||
}
|
||||
if(list_size > 0) {
|
||||
list= calloc(list_size, 1);
|
||||
if(list == NULL)
|
||||
{ret= -1; goto ex;}
|
||||
if(flag & 32)
|
||||
list_size= listxattr(path, list, list_size);
|
||||
else
|
||||
list_size= llistxattr(path, list, list_size);
|
||||
if(list_size == -1)
|
||||
{ret= -1; goto ex;}
|
||||
}
|
||||
for(i= 0; i < list_size; i+= strlen(list + i) + 1)
|
||||
num_names++;
|
||||
}
|
||||
|
||||
#endif /* ! Libisofs_with_aaip_xattR */
|
||||
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
|
||||
if(flag & 1)
|
||||
num_names++;
|
||||
|
||||
#endif
|
||||
|
||||
if(num_names == 0)
|
||||
@ -219,8 +271,11 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
||||
(*values)[i]= NULL;
|
||||
(*value_lengths)[i]= 0;
|
||||
}
|
||||
if(!(flag & 4)) {
|
||||
for(i= 0; i < list_size && num_names > *num_attrs;
|
||||
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
|
||||
if(!(flag & 4)) { /* Get xattr values */
|
||||
for(i= 0; i < list_size && (size_t) num_names > *num_attrs;
|
||||
i+= strlen(list + i) + 1) {
|
||||
if(!(flag & 8))
|
||||
if(strncmp(list + i, "user.", 5))
|
||||
@ -229,12 +284,7 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
||||
if((*names)[(*num_attrs) - 1] == NULL)
|
||||
{ret= -1; goto ex;}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
|
||||
if(!(flag & 4)) { /* Get xattr values */
|
||||
for(i= 0; i < *num_attrs; i++) {
|
||||
for(i= 0; (size_t) i < *num_attrs; i++) {
|
||||
if(!(flag & 8))
|
||||
if(strncmp((*names)[i], "user.", 5))
|
||||
continue;
|
||||
@ -291,15 +341,22 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
||||
|
||||
ret= 1;
|
||||
ex:;
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
if(a_acl_text != NULL)
|
||||
aaip_get_acl_text("", &a_acl_text, 1 << 15); /* free */
|
||||
if(d_acl_text != NULL)
|
||||
aaip_get_acl_text("", &d_acl_text, 1 << 15); /* free */
|
||||
if(acl != NULL)
|
||||
free(acl);
|
||||
#endif
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
if(list != NULL)
|
||||
free(list);
|
||||
#endif
|
||||
|
||||
if(ret <= 0 || (flag & (1 << 15))) {
|
||||
if(*names != NULL) {
|
||||
for(i= 0; i < *num_attrs; i++)
|
||||
for(i= 0; (size_t) i < *num_attrs; i++)
|
||||
free((*names)[i]);
|
||||
free(*names);
|
||||
}
|
||||
@ -308,16 +365,17 @@ ex:;
|
||||
free(*value_lengths);
|
||||
*value_lengths= NULL;
|
||||
if(*values != NULL) {
|
||||
for(i= 0; i < *num_attrs; i++)
|
||||
for(i= 0; (size_t) i < *num_attrs; i++)
|
||||
free((*values)[i]);
|
||||
free(*values);
|
||||
}
|
||||
if(acl != NULL)
|
||||
free(acl);
|
||||
*values= NULL;
|
||||
*num_attrs= 0;
|
||||
}
|
||||
return(ret);
|
||||
|
||||
#endif /* Libisofs_aaip_get_attr_activE */
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -334,7 +392,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)
|
||||
{
|
||||
@ -384,7 +442,9 @@ ex:
|
||||
bit3= do not ignore eventual non-user attributes.
|
||||
I.e. those with a name which does not begin
|
||||
by "user."
|
||||
bit5= in case of symbolic link: manipulate link target
|
||||
bit5= in case of symbolic link: manipulate link target
|
||||
bit6= tolerate inappropriate presence or absence of
|
||||
directory default ACL
|
||||
@return 1 success
|
||||
-1 error memory allocation
|
||||
-2 error with decoding of ACL
|
||||
@ -393,16 +453,24 @@ ex:
|
||||
-5 error with deleting attributes
|
||||
-6 support of xattr not enabled at compile time
|
||||
-7 support of ACL not enabled at compile time
|
||||
( -8 unsupported xattr namespace )
|
||||
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)
|
||||
{
|
||||
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;
|
||||
size_t i, consumed, acl_text_fill, acl_idx= 0;
|
||||
char *acl_text= NULL;
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
size_t list_size= 0;
|
||||
char *list= NULL;
|
||||
ssize_t list_size= 0;
|
||||
#endif
|
||||
#ifdef Libisofs_with_aaip_acL
|
||||
size_t h_consumed;
|
||||
int has_default_acl= 0;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef Libisofs_with_aaip_xattR
|
||||
|
||||
@ -422,7 +490,7 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||
list_size= llistxattr(path, list, list_size);
|
||||
if(list_size == -1)
|
||||
{ret= -5; goto ex;}
|
||||
for(i= 0; i < list_size; i+= strlen(list + i) + 1) {
|
||||
for(i= 0; i < (size_t) list_size; i+= strlen(list + i) + 1) {
|
||||
if(!(flag & 8))
|
||||
if(strncmp(list + i, "user.", 5))
|
||||
continue;
|
||||
@ -447,7 +515,11 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||
continue;
|
||||
}
|
||||
/* Extended Attribute */
|
||||
if((flag & 1) && !(flag & 8))
|
||||
if(flag & 4)
|
||||
continue;
|
||||
if(strncmp(names[i], "isofs.", 6) == 0)
|
||||
continue;
|
||||
if(!(flag & 8))
|
||||
if(strncmp(names[i], "user.", 5))
|
||||
continue;
|
||||
|
||||
@ -475,6 +547,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||
/* "access" ACL */
|
||||
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
||||
&consumed, NULL, 0, &acl_text_fill, 1);
|
||||
if(ret < -3)
|
||||
goto ex;
|
||||
if(ret <= 0)
|
||||
{ret= -2; goto ex;}
|
||||
acl_text= calloc(acl_text_fill, 1);
|
||||
@ -482,17 +556,18 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||
{ret= -1; goto ex;}
|
||||
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
||||
&consumed, acl_text, acl_text_fill, &acl_text_fill, 0);
|
||||
if(ret < -3)
|
||||
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 <= 0)
|
||||
{ret= -3; goto ex;}
|
||||
#else
|
||||
{ret= -7; goto ex;}
|
||||
#endif
|
||||
/* "default" ACL */
|
||||
if(has_default_acl) {
|
||||
free(acl_text);
|
||||
@ -500,6 +575,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||
ret= aaip_decode_acl((unsigned char *) (values[i] + consumed),
|
||||
value_lengths[i] - consumed, &h_consumed,
|
||||
NULL, 0, &acl_text_fill, 1);
|
||||
if(ret < -3)
|
||||
goto ex;
|
||||
if(ret <= 0)
|
||||
{ret= -2; goto ex;}
|
||||
acl_text= calloc(acl_text_fill, 1);
|
||||
@ -508,18 +585,39 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||
ret= aaip_decode_acl((unsigned char *) (values[i] + consumed),
|
||||
value_lengths[i] - consumed, &h_consumed,
|
||||
acl_text, acl_text_fill, &acl_text_fill, 0);
|
||||
if(ret < -3)
|
||||
goto ex;
|
||||
if(ret <= 0)
|
||||
{ret= -2; goto ex;}
|
||||
ret= aaip_set_acl_text(path, acl_text, 1 | (flag & 32));
|
||||
if(ret <= 0)
|
||||
{ret= -3; goto ex;}
|
||||
} else {
|
||||
if(!(flag & 64)) {
|
||||
|
||||
/* >>> ??? take offense from missing default ACL ?
|
||||
??? does Linux demand a default ACL for directories with access ACL ?
|
||||
*/;
|
||||
|
||||
}
|
||||
}
|
||||
ret= 1;
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
|
@ -4,10 +4,10 @@
|
||||
Arbitrary Attribute Interchange Protocol , AAIP versions 0.2 , 1.0 , 2.0.
|
||||
Implementation of encoding and decoding xattr and ACL.
|
||||
|
||||
See test/aaip_0_2.h
|
||||
See libisofs/aaip_0_2.h
|
||||
http://libburnia-project.org/wiki/AAIP
|
||||
|
||||
Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2+
|
||||
Copyright (c) 2009 - 2016 Thomas Schmitt, libburnia project, GPLv2+
|
||||
|
||||
*/
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "libisofs.h"
|
||||
#include "util.h"
|
||||
|
||||
/*
|
||||
#define Aaip_encode_debuG 1
|
||||
@ -61,12 +62,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 ---------------------------- */
|
||||
|
||||
|
||||
@ -87,27 +88,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;
|
||||
unsigned int number_of_fields, i, num_recs, total_recs= 0, ret;
|
||||
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;
|
||||
total_recs= num_recs;
|
||||
}
|
||||
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 +122,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;
|
||||
}
|
||||
|
||||
@ -158,9 +166,9 @@ size_t aaip_encode(size_t num_attrs, char **names,
|
||||
ret= 0;
|
||||
for(i= 0; i < *result_len; i+= ((unsigned char *) (*result))[i + 2])
|
||||
ret++;
|
||||
if(ret != number_of_fields) {
|
||||
if(ret != (int) number_of_fields) {
|
||||
fprintf(stderr, "aaip_encode(): WRONG NUMBER OF FIELDS %d <> %d\n",
|
||||
number_of_fields, ret);
|
||||
(int) number_of_fields, ret);
|
||||
}
|
||||
#endif /* Aaip_encode_debuG */
|
||||
|
||||
@ -187,7 +195,7 @@ static int aaip_encode_comp(unsigned char *result, size_t *result_fill,
|
||||
aaip_encode_byte(result, result_fill, 0);
|
||||
return(1);
|
||||
}
|
||||
for(rpt= data; rpt - data < l;) {
|
||||
for(rpt= data; rpt - data < (ssize_t) l;) {
|
||||
todo= l - (rpt - data) + (prefix > 0);
|
||||
aaip_encode_byte(result, result_fill, (todo > 255));
|
||||
if(todo > 255)
|
||||
@ -198,7 +206,7 @@ static int aaip_encode_comp(unsigned char *result, size_t *result_fill,
|
||||
todo--;
|
||||
prefix= 0;
|
||||
}
|
||||
for(comp_start= rpt; rpt - comp_start < todo; rpt++)
|
||||
for(comp_start= rpt; rpt - comp_start < (ssize_t) todo; rpt++)
|
||||
aaip_encode_byte(result, result_fill, *((unsigned char *) rpt));
|
||||
}
|
||||
return(1);
|
||||
@ -268,7 +276,11 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
||||
bit3= check for completeness of list and eventually
|
||||
fill up with entries deduced from st_mode
|
||||
@return >0 means ok
|
||||
0 means error
|
||||
<=0 means error
|
||||
-1= out of memory
|
||||
-2= program error with prediction of result size
|
||||
-3= error with conversion of name to uid or gid
|
||||
ISO_AAIP_ACL_MULT_OBJ= multiple entries of user::, group::, other::
|
||||
*/
|
||||
int aaip_encode_acl(char *acl_text, mode_t st_mode,
|
||||
size_t *result_len, unsigned char **result, int flag)
|
||||
@ -279,8 +291,10 @@ int aaip_encode_acl(char *acl_text, mode_t st_mode,
|
||||
*result_len= 0;
|
||||
bytes= aaip_encode_acl_text(acl_text, st_mode,
|
||||
(size_t) 0, NULL, 1 | (flag & (2 | 4 | 8)));
|
||||
if(bytes < -2)
|
||||
return(bytes);
|
||||
if(bytes < 0)
|
||||
return(0);
|
||||
return((int) bytes - 1);
|
||||
if(flag & 1) {
|
||||
*result_len= bytes;
|
||||
return(1);
|
||||
@ -292,9 +306,13 @@ int aaip_encode_acl(char *acl_text, mode_t st_mode,
|
||||
*result_len= bytes;
|
||||
bytes= aaip_encode_acl_text(acl_text, st_mode, *result_len, *result,
|
||||
(flag & (2 | 4 | 8)));
|
||||
if(bytes != *result_len) {
|
||||
if(bytes < -2)
|
||||
return(bytes);
|
||||
if(bytes < 0)
|
||||
return((int) bytes - 1);
|
||||
if((size_t) bytes != *result_len) {
|
||||
*result_len= 0;
|
||||
return(0);
|
||||
return(-2);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
@ -341,26 +359,31 @@ static int aaip_make_aaip_perms(int r, int w, int x)
|
||||
fill up with entries deduced from st_mode
|
||||
@return >=0 number of bytes produced resp. counted
|
||||
<0 means error
|
||||
-1: result size overflow
|
||||
-2: conversion errror 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,
|
||||
size_t result_size, unsigned char *result, int flag)
|
||||
{
|
||||
char *rpt, *npt, *cpt;
|
||||
int qualifier= 0, perms, type, i, qualifier_len= 0, num_recs, needed= 0;
|
||||
int qualifier= 0, perms, type, i, qualifier_len= 0, num_recs, needed= 0, ret;
|
||||
unsigned int has_u= 0, has_g= 0, has_o= 0, has_m= 0, is_trivial= 1;
|
||||
uid_t uid, huid;
|
||||
gid_t gid, hgid;
|
||||
ssize_t count= 0;
|
||||
struct passwd *pwd;
|
||||
struct group *grp;
|
||||
char name[1024];
|
||||
char *name = NULL;
|
||||
int name_size= 1024;
|
||||
double num;
|
||||
|
||||
LIBISO_ALLOC_MEM(name, char, name_size);
|
||||
if(flag & 4) {
|
||||
/* set SWITCH_MARK to indicate a default ACL */;
|
||||
if(!(flag & 1)) {
|
||||
if(count >= result_size)
|
||||
return(-1);
|
||||
if((size_t) count >= result_size)
|
||||
{ret= -1; goto ex;}
|
||||
result[count]= (Aaip_SWITCH_MARK << 4) | Aaip_EXEC;
|
||||
}
|
||||
count++;
|
||||
@ -384,9 +407,17 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
||||
if(strncmp(rpt, "user:", 5) == 0) {
|
||||
if(cpt - rpt == 5) {
|
||||
type= Aaip_ACL_USER_OBJ;
|
||||
if (has_u) {
|
||||
|
||||
/* >>> Duplicate u:: entry. */;
|
||||
/* >>> ??? If it matches the previous one: ignore */
|
||||
|
||||
ret = ISO_AAIP_ACL_MULT_OBJ;
|
||||
goto ex;
|
||||
}
|
||||
has_u++;
|
||||
} else {
|
||||
if(cpt - (rpt + 5) >= sizeof(name))
|
||||
if(cpt - (rpt + 5) >= name_size)
|
||||
continue;
|
||||
is_trivial= 0;
|
||||
strncpy(name, rpt + 5, cpt - (rpt + 5));
|
||||
@ -396,8 +427,10 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
||||
pwd= getpwnam(name);
|
||||
if(pwd == NULL) {
|
||||
num= aaip_numeric_id(name, 0);
|
||||
if(num <= 0)
|
||||
goto user_by_name;
|
||||
if(num <= 0) {
|
||||
/* ACL_USER is not part of AAIP 2.0 */
|
||||
{ret= -2; goto ex;}
|
||||
}
|
||||
uid= huid= num;
|
||||
} else
|
||||
uid= huid= pwd->pw_uid;
|
||||
@ -405,31 +438,45 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
||||
for(i= 0; huid != 0; i++)
|
||||
huid= huid >> 8;
|
||||
qualifier_len= i;
|
||||
if(qualifier_len <= 0)
|
||||
qualifier_len= 1;
|
||||
for(i= 0; i < qualifier_len ; i++)
|
||||
name[i]= uid >> (8 * (qualifier_len - i - 1));
|
||||
} else {
|
||||
user_by_name:;
|
||||
type= Aaip_ACL_USER;
|
||||
qualifier_len= strlen(name);
|
||||
if(qualifier_len <= 0)
|
||||
qualifier_len= 1;
|
||||
}
|
||||
qualifier= 1;
|
||||
}
|
||||
} else if(strncmp(rpt, "group:", 6) == 0) {
|
||||
if(cpt - rpt == 6) {
|
||||
type= Aaip_ACL_GROUP_OBJ;
|
||||
if (has_g) {
|
||||
|
||||
/* >>> Duplicate g:: entry. */;
|
||||
/* >>> ??? If it matches the previous one: ignore */
|
||||
|
||||
ret = ISO_AAIP_ACL_MULT_OBJ;
|
||||
goto ex;
|
||||
}
|
||||
has_g++;
|
||||
} else {
|
||||
if(cpt - (rpt + 6) >= sizeof(name))
|
||||
if(cpt - (rpt + 6) >= name_size)
|
||||
continue;
|
||||
is_trivial= 0;
|
||||
strncpy(name, rpt + 6, cpt - (rpt + 6));
|
||||
name[cpt - (rpt + 6)]= 0;
|
||||
if(flag & 2) {
|
||||
type= Aaip_ACL_GROUP_N;
|
||||
grp= getgrnam(name);
|
||||
if(grp == NULL) {
|
||||
num= aaip_numeric_id(name, 0);
|
||||
if(num <= 0)
|
||||
goto group_by_name;
|
||||
if(num <= 0) {
|
||||
/* ACL_GROUP is not part of AAIP 2.0 */
|
||||
{ret= -2; goto ex;}
|
||||
}
|
||||
gid= hgid= num;
|
||||
} else
|
||||
gid= hgid= grp->gr_gid;
|
||||
@ -437,18 +484,28 @@ user_by_name:;
|
||||
for(i= 0; hgid != 0; i++)
|
||||
hgid= hgid >> 8;
|
||||
qualifier_len= i;
|
||||
if(qualifier_len <= 0)
|
||||
qualifier_len= 1;
|
||||
for(i= 0; i < qualifier_len ; i++)
|
||||
name[i]= gid >> (8 * (qualifier_len - i - 1));
|
||||
|
||||
} else {
|
||||
group_by_name:;
|
||||
type= Aaip_ACL_GROUP;
|
||||
qualifier_len= strlen(name);
|
||||
if(qualifier_len <= 0)
|
||||
qualifier_len= 1;
|
||||
}
|
||||
qualifier= 1;
|
||||
}
|
||||
} else if(strncmp(rpt, "other:", 6) == 0) {
|
||||
type= Aaip_ACL_OTHER;
|
||||
if (has_o) {
|
||||
|
||||
/* >>> Duplicate o:: entry. */;
|
||||
/* >>> ??? If it matches the previous one: ignore */
|
||||
|
||||
ret = ISO_AAIP_ACL_MULT_OBJ;
|
||||
goto ex;
|
||||
}
|
||||
has_o++;
|
||||
} else if(strncmp(rpt, "mask:", 5) == 0) {
|
||||
type= Aaip_ACL_MASK;
|
||||
@ -461,8 +518,8 @@ group_by_name:;
|
||||
perms= aaip_make_aaip_perms(cpt[1] == 'r', cpt[2] == 'w', cpt[3] == 'x');
|
||||
|
||||
if(!(flag & 1)) {
|
||||
if(count >= result_size)
|
||||
return(-1);
|
||||
if((size_t) count >= result_size)
|
||||
{ret= -1; goto ex;}
|
||||
result[count]= perms | ((!!qualifier) << 3) | (type << 4);
|
||||
}
|
||||
count++;
|
||||
@ -470,8 +527,8 @@ group_by_name:;
|
||||
if(qualifier) {
|
||||
num_recs= (qualifier_len / 127) + !!(qualifier_len % 127);
|
||||
if(!(flag & 1)) {
|
||||
if(count + 1 > result_size)
|
||||
return(-1);
|
||||
if((size_t) (count + 1) > result_size)
|
||||
{ret= -1; goto ex;}
|
||||
for(i= 0; i < num_recs; i++) {
|
||||
if(i < num_recs - 1)
|
||||
result[count++]= 255;
|
||||
@ -480,8 +537,8 @@ group_by_name:;
|
||||
if(result[count - 1] == 0)
|
||||
result[count - 1]= 127;
|
||||
}
|
||||
if(count + (result[count - 1] & 127) > result_size)
|
||||
return(-1);
|
||||
if((size_t) (count + (result[count - 1] & 127)) > result_size)
|
||||
{ret= -1; goto ex;}
|
||||
memcpy(result + count, name + i * 127, result[count - 1] & 127);
|
||||
count+= result[count - 1] & 127;
|
||||
}
|
||||
@ -495,8 +552,8 @@ group_by_name:;
|
||||
if(flag & 1)
|
||||
count+= needed;
|
||||
else {
|
||||
if(count + needed > result_size)
|
||||
return(-1);
|
||||
if((size_t) (count + needed) > result_size)
|
||||
{ret= -1; goto ex;}
|
||||
}
|
||||
}
|
||||
if ((flag & 8) && needed > 0 && !(flag & 1)) {
|
||||
@ -521,7 +578,10 @@ group_by_name:;
|
||||
result[count++]= perms | (Aaip_ACL_MASK << 4);
|
||||
}
|
||||
}
|
||||
return(count);
|
||||
ret= count;
|
||||
ex:;
|
||||
LIBISO_FREE_MEM(name);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
@ -588,7 +648,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.
|
||||
@ -1120,9 +1180,9 @@ static int aaip_consume_rec_head(struct aaip_state *aaip,
|
||||
size_t todo;
|
||||
|
||||
todo= *num_data;
|
||||
if(todo > aaip->aa_missing)
|
||||
if(todo > (size_t) aaip->aa_missing)
|
||||
todo= aaip->aa_missing;
|
||||
if(todo >= aaip->rec_head_missing)
|
||||
if(todo >= (size_t) aaip->rec_head_missing)
|
||||
todo= aaip->rec_head_missing;
|
||||
if(!aaip->recs_invalid)
|
||||
aaip_push_to_recs(aaip, *data, todo, 0);
|
||||
@ -1144,9 +1204,9 @@ static int aaip_consume_rec_data(struct aaip_state *aaip,
|
||||
size_t todo;
|
||||
|
||||
todo= *num_data;
|
||||
if(todo > aaip->aa_missing)
|
||||
if(todo > (size_t) aaip->aa_missing)
|
||||
todo= aaip->aa_missing;
|
||||
if(todo > aaip->rec_missing)
|
||||
if(todo > (size_t) aaip->rec_missing)
|
||||
todo= aaip->rec_missing;
|
||||
if(!aaip->recs_invalid)
|
||||
aaip_push_to_recs(aaip, *data, todo, 1);
|
||||
@ -1178,7 +1238,7 @@ static int aaip_consume_aa_head(struct aaip_state *aaip,
|
||||
unsigned char aa_head[5];
|
||||
|
||||
todo= *num_data;
|
||||
if(todo >= aaip->aa_head_missing)
|
||||
if(todo >= (size_t) aaip->aa_head_missing)
|
||||
todo= aaip->aa_head_missing;
|
||||
aaip_push_to_recs(aaip, *data, todo, 0);
|
||||
aaip->aa_head_missing-= todo;
|
||||
@ -1225,7 +1285,7 @@ static int aaip_consume_aa_data(struct aaip_state *aaip,
|
||||
aaip_push_to_recs(aaip, zero_char, 1, 0);
|
||||
} else {
|
||||
/* fill in missing btes */
|
||||
for(i= 0; i < aaip->rec_missing; i++)
|
||||
for(i= 0; (int) i < aaip->rec_missing; i++)
|
||||
aaip_push_to_recs(aaip, zero_char, 1, 1);
|
||||
}
|
||||
aaip->rec_head_missing= 2;
|
||||
@ -1696,7 +1756,7 @@ int aaip_decode_attrs(struct aaip_state **handle,
|
||||
unsigned char *data, size_t num_data, size_t *consumed,
|
||||
int flag)
|
||||
{
|
||||
int ret, was_non_aa= 0;
|
||||
int ret;
|
||||
struct aaip_state *aaip;
|
||||
size_t h_num, *h_lengths, i, new_mem, pair_consumed= 0;
|
||||
char **h_names, **h_values, *hpt;
|
||||
@ -1754,8 +1814,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;
|
||||
@ -1785,7 +1845,6 @@ int aaip_decode_attrs(struct aaip_state **handle,
|
||||
return(ret);
|
||||
|
||||
} else if(ret == -1) { /* non-AAIP field detected */
|
||||
was_non_aa= 1;
|
||||
if(pair_consumed <= 0)
|
||||
return(-4); /* interpretation did not advance */
|
||||
|
||||
@ -1968,14 +2027,16 @@ static int aaip_read_qualifier(unsigned char *data, size_t num_data,
|
||||
char *name, size_t name_size, size_t *name_fill,
|
||||
int flag)
|
||||
{
|
||||
int is_done= 0, rec_len= 0;
|
||||
int is_done= 0;
|
||||
size_t rec_len= 0;
|
||||
unsigned char *rpt;
|
||||
|
||||
*name_fill= 0;
|
||||
for(rpt= data; !is_done; rpt+= rec_len) {
|
||||
rec_len= (*rpt) & 127;
|
||||
is_done= !((*rpt) & 128);
|
||||
if(*name_fill + rec_len >= name_size || rpt + 1 + rec_len - data > num_data)
|
||||
if(*name_fill + rec_len >= name_size ||
|
||||
(size_t) (rpt + 1 + rec_len - data) > num_data)
|
||||
return(-1);
|
||||
memcpy(name + *name_fill, rpt + 1, rec_len);
|
||||
rpt+= 1 + rec_len;
|
||||
@ -2013,20 +2074,21 @@ int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
|
||||
size_t *acl_text_fill, int flag)
|
||||
{
|
||||
unsigned char *rpt;
|
||||
char perm_text[4], *wpt, name[1024];
|
||||
int type, qualifier= 0, perm, ret, i, cnt;
|
||||
size_t w_size, name_fill= 0;
|
||||
char perm_text[4], *wpt, *name= NULL;
|
||||
int type, qualifier= 0, perm, ret, cnt, name_size= 1024;
|
||||
size_t w_size= 0, name_fill= 0, i;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
struct passwd *pwd;
|
||||
struct group *grp;
|
||||
|
||||
LIBISO_ALLOC_MEM(name, char, name_size);
|
||||
cnt= flag & 1;
|
||||
*consumed= 0;
|
||||
wpt= acl_text;
|
||||
w_size= acl_text_size;
|
||||
*acl_text_fill= 0;
|
||||
for(rpt= data; rpt - data < num_data; ) {
|
||||
for(rpt= data; (size_t) (rpt - data) < num_data; ) {
|
||||
perm= *rpt;
|
||||
strcpy(perm_text, "---");
|
||||
if(perm & Aaip_READ)
|
||||
@ -2038,14 +2100,14 @@ int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
|
||||
|
||||
type= (*rpt) >> 4;
|
||||
if(type == Aaip_FUTURE_VERSION) /* indicate to caller: version mismatch */
|
||||
return(-3);
|
||||
{ret = -3; goto ex;}
|
||||
|
||||
qualifier= !!((*rpt) & 8);
|
||||
if(qualifier) {
|
||||
ret= aaip_read_qualifier(rpt + 1, num_data - (rpt + 1 - data),
|
||||
name, sizeof(name), &name_fill, 0);
|
||||
name, name_size, &name_fill, 0);
|
||||
if(ret <= 0)
|
||||
return(-1);
|
||||
{ret = -1; goto ex;}
|
||||
}
|
||||
|
||||
/* Advance read pointer */
|
||||
@ -2086,7 +2148,7 @@ int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
|
||||
pwd= getpwuid(uid);
|
||||
if(pwd == NULL)
|
||||
sprintf(name, "%.f", (double) uid);
|
||||
else if(strlen(pwd->pw_name) >= sizeof(name))
|
||||
else if(strlen(pwd->pw_name) >= (size_t) name_size)
|
||||
sprintf(name, "%.f", (double) uid);
|
||||
else
|
||||
strcpy(name, pwd->pw_name);
|
||||
@ -2100,7 +2162,7 @@ int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
|
||||
grp= getgrgid(gid);
|
||||
if(grp == NULL)
|
||||
sprintf(name, "%.f", (double) gid);
|
||||
else if(strlen(grp->gr_name) >= sizeof(name))
|
||||
else if(strlen(grp->gr_name) >= (size_t) name_size)
|
||||
sprintf(name, "%.f", (double) gid);
|
||||
else
|
||||
strcpy(name, grp->gr_name);
|
||||
@ -2108,15 +2170,17 @@ int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
|
||||
ret= aaip_write_acl_line(&wpt, &w_size, "group", name, perm_text, cnt);
|
||||
} else {
|
||||
/* indicate to caller: unknown type */
|
||||
return(-4);
|
||||
{ret = -4; goto ex;}
|
||||
}
|
||||
if(ret <= 0)
|
||||
return(-2);
|
||||
{ret = -2; goto ex;}
|
||||
}
|
||||
ret= 1;
|
||||
ex:;
|
||||
*acl_text_fill= w_size;
|
||||
if(flag & 1)
|
||||
*acl_text_fill= w_size + 1;
|
||||
(*acl_text_fill)++;
|
||||
LIBISO_FREE_MEM(name);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
@ -2128,15 +2192,51 @@ ex:;
|
||||
|
||||
#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
|
||||
|
||||
#include "aaip-os-linux.c"
|
||||
|
||||
/* August 2011: aaip-os-linux.c would also work for GNU/Hurd : ifdef __GNU__
|
||||
Libraries and headers are present on Debian GNU/Hurd but there is no
|
||||
ACL or xattr support in the filesystems yet.
|
||||
Further, llistxattr() produces ENOSYS "Function not implemented".
|
||||
So it makes few sense to enable it here.
|
||||
*/
|
||||
|
||||
#else
|
||||
|
||||
#include "aaip-os-dummy.c"
|
||||
|
||||
#endif /* ! __linux */
|
||||
#endif /* ! __OpenBSD__ */
|
||||
#endif /* ! __NetBSD__ */
|
||||
#endif /* ! __FreeBSD_kernel__ */
|
||||
#endif /* ! __FreeBSD__ */
|
||||
|
||||
|
@ -9,13 +9,16 @@
|
||||
|
||||
test/aaip_0_2.h - Public declarations
|
||||
|
||||
Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2+
|
||||
Copyright (c) 2009 - 2016 Thomas Schmitt, libburnia project, GPLv2+
|
||||
|
||||
*/
|
||||
|
||||
#ifndef Aaip_h_is_includeD
|
||||
#define Aaip_h_is_includeD yes
|
||||
|
||||
/* For ssize_t */
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
/* --------------------------------- Encoder ---------------------------- */
|
||||
|
||||
@ -30,12 +33,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 ------ */
|
||||
@ -56,7 +59,11 @@ size_t aaip_encode(size_t num_attrs, char **names,
|
||||
bit3= check for completeness of list and eventually
|
||||
fill up with entries deduced from st_mode
|
||||
@return >0 means ok
|
||||
0 means error
|
||||
<=0 means error
|
||||
-1= out of memory
|
||||
-2= program error with prediction of result size
|
||||
-3= error with conversion of name to uid or gid
|
||||
ISO_AAIP_ACL_MULT_OBJ= multiple entries of user::, group::, other::
|
||||
*/
|
||||
int aaip_encode_acl(char *acl_text, mode_t st_mode,
|
||||
size_t *result_len, unsigned char **result, int flag);
|
||||
@ -80,13 +87,13 @@ int aaip_encode_acl(char *acl_text, mode_t st_mode,
|
||||
bit3= check for completeness of list and eventually
|
||||
fill up with entries deduced from st_mode
|
||||
@return >0 means ok
|
||||
0 means error
|
||||
<=0 means error, see aaip_encode_acl
|
||||
*/
|
||||
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.
|
||||
@ -145,6 +152,24 @@ int aaip_add_acl_st_mode(char *acl_text, mode_t st_mode, int flag);
|
||||
|
||||
/* ------ OS interface ------ */
|
||||
|
||||
/* See also API iso_local_attr_support().
|
||||
@param flag
|
||||
Bitfield for control purposes
|
||||
bit0= inquire availability of ACL
|
||||
bit1= inquire availability of xattr
|
||||
bit2 - bit7= Reserved for future types.
|
||||
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
|
||||
bit0= ACL adapter is enabled
|
||||
bit1= xattr adapter is enabled
|
||||
bit2 - bit7= Reserved for future types.
|
||||
bit8 and higher: reserved, do not interpret these
|
||||
*/
|
||||
int aaip_local_attr_support(int flag);
|
||||
|
||||
|
||||
/* Obtain the ACL of the given file in long text form.
|
||||
@param path Path to the file
|
||||
@param text Will hold the result. This is a managed object which
|
||||
@ -478,6 +503,8 @@ int aaip_set_acl_text(char *path, char *text, int flag);
|
||||
-5 error with deleting attributes
|
||||
-6 support of xattr not enabled at compile time
|
||||
-7 support of ACL not enabled at compile time
|
||||
-8 unsupported xattr namespace
|
||||
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);
|
||||
|
@ -150,7 +150,7 @@ void iso_ring_buffer_free(IsoRingBuffer *buf)
|
||||
int iso_ring_buffer_write(IsoRingBuffer *buf, uint8_t *data, size_t count)
|
||||
{
|
||||
size_t len;
|
||||
int bytes_write = 0;
|
||||
size_t bytes_write = 0;
|
||||
|
||||
if (buf == NULL || data == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
@ -206,7 +206,7 @@ int iso_ring_buffer_write(IsoRingBuffer *buf, uint8_t *data, size_t count)
|
||||
int iso_ring_buffer_read(IsoRingBuffer *buf, uint8_t *dest, size_t count)
|
||||
{
|
||||
size_t len;
|
||||
int bytes_read = 0;
|
||||
size_t bytes_read = 0;
|
||||
|
||||
if (buf == NULL || dest == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
|
@ -11,7 +11,14 @@
|
||||
#define LIBISO_BUFFER_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define BLOCK_SIZE 2048
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 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
|
||||
@ -20,16 +20,14 @@
|
||||
#include "fsource.h"
|
||||
#include "image.h"
|
||||
#include "aaip_0_2.h"
|
||||
#include "util.h"
|
||||
#include "messages.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX Libisofs_default_path_maX
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void iso_node_builder_ref(IsoNodeBuilder *builder)
|
||||
@ -75,6 +73,15 @@ int default_create_file(IsoNodeBuilder *builder, IsoImage *image,
|
||||
iso_file_source_ref(src);
|
||||
|
||||
name = iso_file_source_get_name(src);
|
||||
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);
|
||||
@ -97,18 +104,20 @@ 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;
|
||||
IsoSymlink *link;
|
||||
|
||||
if (builder == NULL || src == NULL || node == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
{ret = ISO_NULL_POINTER; goto ex;}
|
||||
}
|
||||
|
||||
/* get info about source */
|
||||
@ -118,10 +127,24 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
ret = iso_file_source_lstat(src, &info);
|
||||
}
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
name = iso_file_source_get_name(src);
|
||||
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;
|
||||
|
||||
@ -157,10 +180,8 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
case S_IFLNK:
|
||||
{
|
||||
/* source is a symbolic link */
|
||||
char dest[PATH_MAX];
|
||||
IsoSymlink *link;
|
||||
|
||||
ret = iso_file_source_readlink(src, dest, PATH_MAX);
|
||||
LIBISO_ALLOC_MEM(dest, char, LIBISOFS_NODE_PATH_MAX);
|
||||
ret = iso_file_source_readlink(src, dest, LIBISOFS_NODE_PATH_MAX);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
@ -194,12 +215,14 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = ISO_BAD_FSRC_FILETYPE;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
free(name);
|
||||
return ret;
|
||||
}
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
name_is_attached = 1;
|
||||
|
||||
/* fill fields */
|
||||
iso_node_set_perms_internal(new, info.st_mode, 1);
|
||||
@ -213,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);
|
||||
}
|
||||
@ -233,19 +256,27 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
if (ret == 1 && aa_string != NULL) {
|
||||
ret = iso_node_add_xinfo(new, aaip_xinfo_func, aa_string);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto ex;
|
||||
} else if(aa_string != NULL) {
|
||||
free(aa_string);
|
||||
}
|
||||
|
||||
*node = new;
|
||||
|
||||
return ISO_SUCCESS;
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
if (name != NULL && !name_is_attached)
|
||||
free(name);
|
||||
LIBISO_FREE_MEM(dest);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
void default_free(IsoNodeBuilder *builder)
|
||||
{
|
||||
/* The .free() method of IsoNodeBuilder shall free private data but not
|
||||
the builder itself. The latter is done in iso_node_builder_unref().
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
@ -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.
|
||||
|
@ -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
|
||||
|
2274
libisofs/ecma119.c
2274
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 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
|
||||
@ -15,7 +15,14 @@
|
||||
#include "util.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#define BLOCK_SIZE 2048
|
||||
@ -52,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)
|
||||
*/
|
||||
@ -63,6 +70,29 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* The theoretical maximum number of Apple Partition Map entries in the
|
||||
System Area of an ISO image:
|
||||
Block0 plus 63 entries with block size 512
|
||||
*/
|
||||
#define ISO_APM_ENTRIES_MAX 63
|
||||
|
||||
/* The maximum number of MBR partition table entries.
|
||||
*/
|
||||
#define ISO_MBR_ENTRIES_MAX 4
|
||||
|
||||
/* The theoretical maximum number of GPT entries in the System Area of an
|
||||
ISO image:
|
||||
MBR plus GPT header block plus 248 GPT entries of 128 bytes each.
|
||||
*/
|
||||
#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 defaultet to '_'.
|
||||
*/
|
||||
#define ISO_JOLIET_UCS2_WARN_MAX 3
|
||||
|
||||
|
||||
/**
|
||||
* Holds the options for the image generation.
|
||||
*/
|
||||
@ -70,12 +100,14 @@ 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;
|
||||
unsigned int joliet :1;
|
||||
unsigned int iso1999 :1;
|
||||
unsigned int hfsplus :1;
|
||||
unsigned int fat :1;
|
||||
|
||||
unsigned int aaip :1; /* whether to write eventual ACL and EAs */
|
||||
|
||||
@ -142,6 +174,13 @@ struct iso_write_opts {
|
||||
*/
|
||||
unsigned int allow_full_ascii :1;
|
||||
|
||||
/**
|
||||
* If not allow_full_ascii is set: allow all 7 bit characters that would
|
||||
* be allowed by allow_full_ascii. But still map lowercase to uppercase if
|
||||
* not allow_lowercase is set to 1.
|
||||
*/
|
||||
unsigned int allow_7bit_ascii :1;
|
||||
|
||||
/**
|
||||
* Allow all characters to be part of Volume and Volset identifiers on
|
||||
* the Primary Volume Descriptor. This breaks ISO-9660 contraints, but
|
||||
@ -154,6 +193,16 @@ struct iso_write_opts {
|
||||
*/
|
||||
unsigned int joliet_longer_paths :1;
|
||||
|
||||
/**
|
||||
* Allow Joliet names up to 103 characters rather than 64.
|
||||
*/
|
||||
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",
|
||||
@ -174,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
|
||||
@ -190,8 +239,27 @@ struct iso_write_opts {
|
||||
* to expect that we do have a creation timestamp with the source.
|
||||
* mkisofs writes mtimes and the result seems more suitable if mounted
|
||||
* without Rock Ridge support.)
|
||||
* bit0= ECMA-119, bit1= Joliet, bit2= ISO 9660:1999
|
||||
*/
|
||||
unsigned int dir_rec_mtime :1;
|
||||
unsigned int dir_rec_mtime :3;
|
||||
|
||||
/**
|
||||
* This describes the directory where to store Rock Ridge relocated
|
||||
* directories.
|
||||
* If not relaxation "allow_deep_paths" is in effect, it is necessary to
|
||||
* relocate directories so that no ECMA-119 file path has more than
|
||||
* 8 components. For Rock Ridge the relocated directories are linked forth
|
||||
* and back to a placeholder at their original position in path level 8
|
||||
* (entries CL and PL). Directories marked by entry RE are to be considered
|
||||
* artefacts of relocation and shall not be read into a Rock Ridge tree.
|
||||
* For plain ECMA-119, the relocation directory is just a normal directory
|
||||
* which contains normal files and directories.
|
||||
*/
|
||||
char *rr_reloc_dir; /* IsoNode name in root directory */
|
||||
int rr_reloc_flags; /* bit0= mark auto-created rr_reloc_dir by RE
|
||||
bit1= directory was auto-created
|
||||
(cannot be set via API)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Compute MD5 checksum for the whole session and record it as index 0 of
|
||||
@ -232,6 +300,16 @@ struct iso_write_opts {
|
||||
unsigned int replace_uid :2;
|
||||
unsigned int replace_gid :2;
|
||||
|
||||
mode_t dir_mode; /** Mode to use on dirs when replace_dir_mode == 2. */
|
||||
mode_t file_mode; /** Mode to use on files when replace_file_mode == 2. */
|
||||
uid_t uid; /** uid to use when replace_uid == 2. */
|
||||
gid_t gid; /** gid to use when replace_gid == 2. */
|
||||
|
||||
/**
|
||||
* See API call iso_write_opts_set_old_empty().
|
||||
*/
|
||||
unsigned int old_empty :1;
|
||||
|
||||
/**
|
||||
* Extra Caution: This option breaks any assumptions about names that
|
||||
* are supported by ECMA-119 specifications.
|
||||
@ -247,11 +325,6 @@ struct iso_write_opts {
|
||||
*/
|
||||
unsigned int untranslated_name_len;
|
||||
|
||||
mode_t dir_mode; /** Mode to use on dirs when replace_dir_mode == 2. */
|
||||
mode_t file_mode; /** Mode to use on files when replace_file_mode == 2. */
|
||||
uid_t uid; /** uid to use when replace_uid == 2. */
|
||||
gid_t gid; /** gid to use when replace_gid == 2. */
|
||||
|
||||
/**
|
||||
* 0 to use IsoNode timestamps, 1 to use recording time, 2 to use
|
||||
* values from timestamp field. This has only meaning if RR extensions
|
||||
@ -358,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 */
|
||||
@ -390,21 +464,69 @@ struct iso_write_opts {
|
||||
*/
|
||||
uint32_t tail_blocks;
|
||||
|
||||
/* Eventual disk file path of a PreP partition which shall be prepended
|
||||
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
|
||||
*/
|
||||
char *appended_partitions[ISO_MAX_PARTITIONS];
|
||||
uint8_t appended_part_types[ISO_MAX_PARTITIONS];
|
||||
int appended_part_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;
|
||||
|
||||
/* Eventual name of the non-ISO aspect of the image. E.g. SUN ASCII label.
|
||||
*/
|
||||
char ascii_disc_label[ISO_DISC_LABEL_SIZE];
|
||||
|
||||
/* HFS+ image serial number.
|
||||
* 00...00 means that it shall be generated by libisofs.
|
||||
*/
|
||||
uint8_t hfsp_serial_number[8];
|
||||
|
||||
/* Allocation block size of HFS+ : 0= auto , 512, or 2048
|
||||
*/
|
||||
int hfsp_block_size;
|
||||
|
||||
/* Block size of and in APM : 0= auto , 512, or 2048
|
||||
*/
|
||||
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;
|
||||
};
|
||||
|
||||
typedef struct ecma119_image Ecma119Image;
|
||||
typedef struct ecma119_node Ecma119Node;
|
||||
typedef struct joliet_node JolietNode;
|
||||
typedef struct iso1999_node Iso1999Node;
|
||||
typedef struct hfsplus_node HFSPlusNode;
|
||||
typedef struct Iso_File_Src IsoFileSrc;
|
||||
typedef struct Iso_Image_Writer IsoImageWriter;
|
||||
|
||||
@ -415,56 +537,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 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 relaxed_vol_atts : 1;
|
||||
|
||||
/** Allow paths on Joliet tree to be larger than 240 bytes */
|
||||
unsigned int joliet_longer_paths :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 timestamp mtime of source */
|
||||
unsigned int dir_rec_mtime :1;
|
||||
|
||||
unsigned int md5_session_checksum :1;
|
||||
unsigned int md5_file_checksums :2;
|
||||
/* The ECMA-119 directory node where to store Rock Ridge relocated
|
||||
directories. (Path is in IsoWriteOpts.rr_reloc_dir)
|
||||
*/
|
||||
Ecma119Node *rr_reloc_node; /* Directory node in ecma119_image */
|
||||
|
||||
/*
|
||||
* 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;
|
||||
@ -472,30 +557,32 @@ struct ecma119_image
|
||||
unsigned int replace_dir_mode :1;
|
||||
unsigned int replace_timestamps :1;
|
||||
|
||||
unsigned int untranslated_name_len;
|
||||
|
||||
/* Mode replacement values. */
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
mode_t file_mode;
|
||||
mode_t dir_mode;
|
||||
time_t timestamp;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
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 */
|
||||
@ -512,6 +599,12 @@ struct ecma119_image
|
||||
*/
|
||||
uint32_t empty_file_block;
|
||||
|
||||
/*
|
||||
* The calculated block address after ECMA-119 tree and eventual
|
||||
* tree checksum tag.
|
||||
*/
|
||||
uint32_t tree_end_block;
|
||||
|
||||
/*
|
||||
* number of dirs in ECMA-119 tree, computed together with dir position,
|
||||
* and needed for path table computation in a efficient way
|
||||
@ -529,6 +622,30 @@ 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
|
||||
* (by Vladimir Serbinenko, see libisofs/hfsplus.c)
|
||||
*/
|
||||
HFSPlusNode *hfsp_leafs;
|
||||
struct hfsplus_btree_level *hfsp_levels;
|
||||
uint32_t hfsp_nlevels;
|
||||
uint32_t hfsp_part_start;
|
||||
uint32_t hfsp_nfiles;
|
||||
uint32_t hfsp_ndirs;
|
||||
uint32_t hfsp_cat_id;
|
||||
uint32_t hfsp_allocation_blocks;
|
||||
uint32_t hfsp_allocation_file_start;
|
||||
uint32_t hfsp_extent_file_start;
|
||||
uint32_t hfsp_catalog_file_start;
|
||||
uint32_t hfsp_total_blocks;
|
||||
uint32_t hfsp_allocation_size;
|
||||
uint32_t hfsp_nleafs;
|
||||
uint32_t hfsp_curleaf;
|
||||
uint32_t hfsp_nnodes;
|
||||
uint32_t hfsp_bless_id[ISO_HFSPLUS_BLESS_MAX];
|
||||
uint32_t hfsp_collision_count;
|
||||
|
||||
/*
|
||||
* ISO 9660:1999 related information
|
||||
@ -548,6 +665,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
|
||||
*/
|
||||
@ -556,19 +678,36 @@ struct ecma119_image
|
||||
*/
|
||||
char *system_area_data;
|
||||
/*
|
||||
* bit0= Only with PC-BIOS DOS MBR
|
||||
* bit0= Only with DOS MBR
|
||||
* Make bytes 446 - 512 of the system area a partition
|
||||
* table which reserves partition 1 from byte 63*512 to the
|
||||
* end of the ISO image. Assumed are 63 secs/hed, 255 head/cyl.
|
||||
* (GRUB protective msdos label.)
|
||||
* This works with and without system_area_data.
|
||||
* bit1= Only with PC-BIOS DOS MBR
|
||||
* bit1= Only with DOS MBR
|
||||
* Apply isohybrid MBR patching to the system area.
|
||||
* This works only with system_area_data plus ISOLINUX boot image
|
||||
* and only if not bit0 is set.
|
||||
* bit2-7= System area type
|
||||
* 0= DOS MBR
|
||||
* 1= MIPS Big Endian Volume Header
|
||||
* 2= DEC Boot Block for MIPS Little Endian
|
||||
* 3= SUN Disk Label for SUN SPARC
|
||||
* bit8-9= Only with DOS MBR
|
||||
* Cylinder alignment mode eventually pads the image to make it
|
||||
* end at a cylinder boundary.
|
||||
* 0 = auto (align if bit1)
|
||||
* 1 = always align to cylinder boundary
|
||||
* 2 = never align to cylinder boundary
|
||||
* 3 = always align, additionally pad up and align partitions
|
||||
* which were appended by iso_write_opts_set_partition_img()
|
||||
* bit10-13= System area sub type
|
||||
* With type 0 = MBR:
|
||||
* Gets overridden by bit0 and bit1.
|
||||
* 0 = no particular sub type
|
||||
* 1 = CHRP: A single MBR partition of type 0x96 covers the
|
||||
* ISO image. Not compatible with any other feature
|
||||
* which needs to have own MBR partition entries.
|
||||
*/
|
||||
int system_area_options;
|
||||
|
||||
@ -593,6 +732,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;
|
||||
@ -610,14 +751,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;
|
||||
|
||||
@ -626,20 +759,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;
|
||||
@ -660,26 +780,110 @@ 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;
|
||||
uint32_t mipsel_p_vaddr;
|
||||
uint32_t mipsel_p_filesz;
|
||||
|
||||
char *appended_partitions[ISO_MAX_PARTITIONS];
|
||||
uint8_t appended_part_types[ISO_MAX_PARTITIONS];
|
||||
/* A data file of which the position and size shall be written after
|
||||
a SUN Disk Label.
|
||||
*/
|
||||
IsoFileSrc *sparc_core_src;
|
||||
|
||||
/* 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];
|
||||
int have_appended_partitions;
|
||||
|
||||
char ascii_disc_label[ISO_DISC_LABEL_SIZE];
|
||||
/* See IsoImage and libisofs.h */
|
||||
IsoNode *hfsplus_blessed[ISO_HFSPLUS_BLESS_MAX];
|
||||
|
||||
/* Block sizes come from write options.
|
||||
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.
|
||||
*/
|
||||
|
||||
/* Allocation block size of HFS+
|
||||
May be defined to 512 or 2048 before hfsplus_writer_create().
|
||||
*/
|
||||
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().
|
||||
Make sure that the composing writers get registered before the
|
||||
gpt_tail_writer.
|
||||
*/
|
||||
struct iso_apm_partition_request *apm_req[ISO_APM_ENTRIES_MAX];
|
||||
int apm_req_count;
|
||||
/* bit1= Do not fill gaps in Apple Partition Map
|
||||
bit2= apm_req entries use apm_block_size in start_block and block_count.
|
||||
Normally these two parameters are counted in 2 KiB blocks.
|
||||
*/
|
||||
int apm_req_flags;
|
||||
|
||||
/* MBR partition table description. To be composed during IsoImageWriter
|
||||
method ->compute_data_blocks() by calling iso_register_mbr_entry().
|
||||
*/
|
||||
struct iso_mbr_partition_request *mbr_req[ISO_MBR_ENTRIES_MAX];
|
||||
int mbr_req_count;
|
||||
|
||||
/* 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
|
||||
method ->compute_data_blocks() by calling iso_register_gpt_entry().
|
||||
Make sure that the composing writers get registered before the
|
||||
gpt_tail_writer.
|
||||
*/
|
||||
struct iso_gpt_partition_request *gpt_req[ISO_GPT_ENTRIES_MAX];
|
||||
int gpt_req_count;
|
||||
/* bit0= GPT partitions may overlap */
|
||||
int gpt_req_flags;
|
||||
|
||||
/* 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 */
|
||||
uint32_t gpt_backup_end;
|
||||
uint32_t gpt_backup_size;
|
||||
uint32_t gpt_max_entries;
|
||||
int gpt_is_computed;
|
||||
|
||||
/* Message from write_head_part1()/iso_write_system_area() to the
|
||||
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()
|
||||
is called.
|
||||
*/
|
||||
uint32_t filesrc_start;
|
||||
uint32_t filesrc_blocks;
|
||||
|
||||
};
|
||||
|
||||
@ -811,5 +1015,14 @@ struct ecma119_vol_desc_terminator
|
||||
uint8_t reserved BP(8, 2048);
|
||||
};
|
||||
|
||||
void ecma119_set_voldescr_times(IsoImageWriter *writer,
|
||||
struct ecma119_pri_vol_desc *vol);
|
||||
|
||||
/* Copies a data file into the ISO image output stream */
|
||||
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);
|
||||
|
||||
|
||||
#endif /*LIBISO_ECMA119_H_*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 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,55 +29,73 @@
|
||||
#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, max_len;
|
||||
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 (iso->type == LIBISO_DIR && !(img->allow_dir_id_ext)) {
|
||||
if (img->untranslated_name_len > 0) {
|
||||
if (strlen(ascii_name) > img->untranslated_name_len) {
|
||||
if (opts->allow_7bit_ascii)
|
||||
relaxed |= 4;
|
||||
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
|
||||
|
||||
if (relaxed) {
|
||||
isoname = iso_r_dirid(ascii_name, 8, relaxed);
|
||||
} else {
|
||||
isoname = iso_1_dirid(ascii_name);
|
||||
isoname = iso_1_dirid(ascii_name, 0);
|
||||
}
|
||||
|
||||
#else /* Libisofs_old_ecma119_nameS */
|
||||
|
||||
isoname = iso_1_dirid(ascii_name, relaxed);
|
||||
|
||||
#endif /* ! Libisofs_old_ecma119_nameS */
|
||||
|
||||
|
||||
} else {
|
||||
if (relaxed) {
|
||||
isoname = iso_r_dirid(ascii_name, 31, relaxed);
|
||||
@ -86,15 +104,21 @@ 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) {
|
||||
if (relaxed || !force_dots) {
|
||||
} else if (opts->iso_level == 1) {
|
||||
|
||||
#ifdef Libisofs_old_ecma119_nameS
|
||||
|
||||
int max_len;
|
||||
|
||||
if (relaxed) {
|
||||
if (strchr(ascii_name, '.') == NULL)
|
||||
max_len = 8;
|
||||
else
|
||||
@ -102,8 +126,15 @@ needs_transl:;
|
||||
isoname = iso_r_fileid(ascii_name, max_len, relaxed,
|
||||
force_dots);
|
||||
} else {
|
||||
isoname = iso_1_fileid(ascii_name);
|
||||
isoname = iso_1_fileid(ascii_name, 0, force_dots);
|
||||
}
|
||||
|
||||
#else /* Libisofs_old_ecma119_nameS */
|
||||
|
||||
isoname = iso_1_fileid(ascii_name, relaxed, force_dots);
|
||||
|
||||
#endif /* ! Libisofs_old_ecma119_nameS */
|
||||
|
||||
} else {
|
||||
if (relaxed || !force_dots) {
|
||||
isoname = iso_r_fileid(ascii_name, 30, relaxed, force_dots);
|
||||
@ -126,6 +157,25 @@ 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->opts->rr_reloc_flags & 2))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int create_ecma119_node(Ecma119Image *img, IsoNode *iso, Ecma119Node **node)
|
||||
{
|
||||
@ -151,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;
|
||||
}
|
||||
@ -186,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) {
|
||||
@ -299,11 +352,12 @@ void ecma119_node_free(Ecma119Node *node)
|
||||
return;
|
||||
}
|
||||
if (node->type == ECMA119_DIR) {
|
||||
int i;
|
||||
size_t i;
|
||||
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);
|
||||
@ -311,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.
|
||||
@ -327,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;
|
||||
@ -351,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, "
|
||||
@ -375,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);
|
||||
}
|
||||
@ -384,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 */
|
||||
@ -400,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 */
|
||||
@ -415,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);
|
||||
}
|
||||
@ -434,6 +525,15 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree,
|
||||
if (ret < 0) {
|
||||
goto ex;
|
||||
}
|
||||
if (depth == 1) { /* root is default */
|
||||
image->rr_reloc_node = node;
|
||||
} else if (depth == 2) {
|
||||
/* Directories in root may be used as relocation dir */
|
||||
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;
|
||||
}
|
||||
}
|
||||
ret = ISO_SUCCESS;
|
||||
pos = dir->children;
|
||||
@ -497,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++) {
|
||||
@ -532,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);
|
||||
@ -549,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 */
|
||||
@ -563,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.
|
||||
@ -587,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
|
||||
@ -643,7 +751,7 @@ int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
|
||||
max = max_file_len - digits;
|
||||
}
|
||||
name = full_name;
|
||||
if (max < strlen(name)) {
|
||||
if ((size_t) max < strlen(name)) {
|
||||
name[max] = '\0';
|
||||
}
|
||||
/* let ext be an empty string */
|
||||
@ -678,8 +786,11 @@ int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
goto mangle_cleanup;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_extra_verbose_debuG
|
||||
iso_msg_debug(img->image->id, "\"%s\" renamed to \"%s\"",
|
||||
children[k]->iso_name, new);
|
||||
#endif
|
||||
|
||||
iso_htable_remove_ptr(table, children[k]->iso_name, NULL);
|
||||
free(children[k]->iso_name);
|
||||
@ -750,22 +861,24 @@ int mangle_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
|
||||
}
|
||||
|
||||
static
|
||||
int mangle_tree(Ecma119Image *img, int recurse)
|
||||
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 {
|
||||
max_file = max_dir = 31;
|
||||
}
|
||||
if (img->eff_partition_offset > 0) {
|
||||
if (dir != NULL) {
|
||||
root = dir;
|
||||
} else if (img->eff_partition_offset > 0) {
|
||||
root = img->partition_root;
|
||||
} else {
|
||||
root = img->root;
|
||||
@ -887,41 +1000,61 @@ int reparent(Ecma119Node *child, Ecma119Node *parent)
|
||||
* 1 success, < 0 error
|
||||
*/
|
||||
static
|
||||
int reorder_tree(Ecma119Image *img, Ecma119Node *dir, int level, int pathlen)
|
||||
int reorder_tree(Ecma119Image *img, Ecma119Node *dir,
|
||||
int dir_level, int dir_pathlen)
|
||||
{
|
||||
int ret;
|
||||
size_t max_path;
|
||||
Ecma119Node *root;
|
||||
int ret, level, pathlen, newpathlen;
|
||||
size_t max_path, i;
|
||||
Ecma119Node *reloc, *child;
|
||||
|
||||
/* might change by relocation */
|
||||
level = dir_level;
|
||||
pathlen = dir_pathlen;
|
||||
|
||||
max_path = pathlen + 1 + max_child_name_len(dir);
|
||||
|
||||
if (level > 8 || max_path > 255) {
|
||||
if (img->eff_partition_offset > 0) {
|
||||
root = img->partition_root;
|
||||
} else {
|
||||
root = img->root;
|
||||
reloc = img->rr_reloc_node;
|
||||
if (reloc == NULL) {
|
||||
if (img->eff_partition_offset > 0) {
|
||||
reloc = img->partition_root;
|
||||
} else {
|
||||
reloc = img->root;
|
||||
}
|
||||
}
|
||||
ret = reparent(dir, root);
|
||||
ret = reparent(dir, reloc);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* we are appended to the root's children now, so there is no
|
||||
* need to recurse (the root will hit us again)
|
||||
*/
|
||||
} else {
|
||||
size_t i;
|
||||
if (reloc == img->root || reloc == img->partition_root) {
|
||||
/*
|
||||
* we are appended to the root's children now, so there is no
|
||||
* need to recurse (the root will hit us again)
|
||||
*/
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
for (i = 0; i < dir->info.dir->nchildren; i++) {
|
||||
Ecma119Node *child = dir->info.dir->children[i];
|
||||
if (child->type == ECMA119_DIR) {
|
||||
int newpathlen = pathlen + 1 + strlen(child->iso_name);
|
||||
ret = reorder_tree(img, child, level + 1, newpathlen);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/* dir is now the relocated Ecma119Node */
|
||||
pathlen = 37 + 1; /* The dir name might get longer by mangling */
|
||||
level = 2;
|
||||
if (img->opts->rr_reloc_dir != NULL) {
|
||||
pathlen += strlen(img->rr_reloc_node->iso_name) + 1;
|
||||
if(img->opts->rr_reloc_dir[0] != 0)
|
||||
level = 3;
|
||||
}
|
||||
}
|
||||
|
||||
if (ecma119_is_dedicated_reloc_dir(img, (Ecma119Node *) dir))
|
||||
return ISO_SUCCESS;
|
||||
|
||||
for (i = 0; i < dir->info.dir->nchildren; i++) {
|
||||
child = dir->info.dir->children[i];
|
||||
if (child->type == ECMA119_DIR) {
|
||||
newpathlen = pathlen + 1 + strlen(child->iso_name);
|
||||
ret = reorder_tree(img, child, level + 1, newpathlen);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return ISO_SUCCESS;
|
||||
@ -1027,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);
|
||||
@ -1060,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 *),
|
||||
@ -1074,11 +1212,12 @@ int match_hardlinks(Ecma119Image *img, Ecma119Node *dir, int flag)
|
||||
iso_node_get_id(nodes[0]->node, &fs_id, &dev_id, &img_ino, 1);
|
||||
family_start = 0;
|
||||
for (i = 1; i < node_count; i++) {
|
||||
if (ecma119_node_cmp_hard(nodes + (i - 1), nodes + i) == 0) {
|
||||
if (nodes[i]->type != ECMA119_DIR &&
|
||||
ecma119_node_cmp_hard(nodes + (i - 1), nodes + i) == 0) {
|
||||
/* Still in same ino family */
|
||||
if (img_ino == 0) { /* Just in case any member knows its img_ino */
|
||||
iso_node_get_id(nodes[0]->node, &fs_id, &dev_id, &img_ino, 1);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
family_set_ino(img, nodes, family_start, i, img_ino, prev_ino, 0);
|
||||
@ -1124,14 +1263,14 @@ int ecma119_tree_create(Ecma119Image *img)
|
||||
sort_tree(root);
|
||||
|
||||
iso_msg_debug(img->image->id, "Mangling names...");
|
||||
ret = mangle_tree(img, 1);
|
||||
ret = mangle_tree(img, NULL, 1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (img->rockridge && !img->allow_deep_paths) {
|
||||
if (img->opts->rockridge && !img->opts->allow_deep_paths) {
|
||||
|
||||
/* reorder the tree, 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;
|
||||
@ -1139,10 +1278,10 @@ int ecma119_tree_create(Ecma119Image *img)
|
||||
|
||||
/*
|
||||
* and we need to remangle the root directory, as the function
|
||||
* above could insert new directories into the root.
|
||||
* above could insert new directories into the relocation directory.
|
||||
* Note that recurse = 0, as we don't need to recurse.
|
||||
*/
|
||||
ret = mangle_tree(img, 0);
|
||||
ret = mangle_tree(img, img->rr_reloc_node, 0);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* 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
|
||||
@ -63,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;
|
||||
|
||||
@ -80,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);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -96,5 +106,19 @@ void ecma119_node_free(Ecma119Node *node);
|
||||
*/
|
||||
Ecma119Node *ecma119_search_iso_node(Ecma119Image *img, IsoNode *node);
|
||||
|
||||
/**
|
||||
* Tell whether node is a dedicated relocation directory which only contains
|
||||
* relocated directories.
|
||||
*/
|
||||
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 Thomas Schmitt
|
||||
* Copyright (c) 2010 - 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
|
||||
@ -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,15 +104,16 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -160,7 +163,13 @@ int el_torito_get_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20])
|
||||
/* API */
|
||||
int el_torito_seems_boot_info_table(ElToritoBootImage *bootimg, int flag)
|
||||
{
|
||||
return bootimg->seems_boot_info_table;
|
||||
switch (flag & 15) {
|
||||
case 0:
|
||||
return bootimg->seems_boot_info_table;
|
||||
case 1:
|
||||
return bootimg->seems_grub2_boot_info;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -197,14 +206,16 @@ void el_torito_patch_isolinux_image(ElToritoBootImage *bootimg)
|
||||
*/
|
||||
int el_torito_set_isolinux_options(ElToritoBootImage *bootimg, int options, int flag)
|
||||
{
|
||||
bootimg->isolinux_options = (options & 0x03);
|
||||
bootimg->isolinux_options = (options & 0x03ff);
|
||||
bootimg->seems_boot_info_table = !!(options & 1);
|
||||
bootimg->seems_grub2_boot_info = !!(options & (1 << 9));
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
/* API */
|
||||
int el_torito_get_isolinux_options(ElToritoBootImage *bootimg, int flag)
|
||||
{
|
||||
return bootimg->isolinux_options & 0x03;
|
||||
return bootimg->isolinux_options & 0x03ff;
|
||||
}
|
||||
|
||||
/* API */
|
||||
@ -239,6 +250,7 @@ int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot)
|
||||
IsoBoot *node;
|
||||
IsoNode **pos;
|
||||
time_t now;
|
||||
int ret;
|
||||
|
||||
if (parent == NULL || name == NULL || boot == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
@ -248,9 +260,9 @@ int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot)
|
||||
}
|
||||
|
||||
/* check if the name is valid */
|
||||
if (!iso_node_is_valid_name(name)) {
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
ret = iso_node_is_valid_name(name);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* find place where to insert */
|
||||
pos = &(parent->children);
|
||||
@ -274,8 +286,11 @@ int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot)
|
||||
free(node);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
node->lba = 0;
|
||||
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;
|
||||
@ -298,44 +313,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");
|
||||
@ -383,14 +458,14 @@ int create_image(IsoImage *image, const char *image_path,
|
||||
if (ret != sizeof(mbr)) {
|
||||
iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
|
||||
"Can't read MBR from image file.");
|
||||
return ret < 0 ? ret : ISO_FILE_READ_ERROR;
|
||||
return ret < 0 ? ret : (int) ISO_FILE_READ_ERROR;
|
||||
}
|
||||
|
||||
/* check valid MBR signature */
|
||||
if ( mbr.sign1 != 0x55 || mbr.sign2 != 0xAA ) {
|
||||
iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
|
||||
"Invalid MBR. Wrong signature.");
|
||||
return ISO_BOOT_IMAGE_NOT_VALID;
|
||||
return (int) ISO_BOOT_IMAGE_NOT_VALID;
|
||||
}
|
||||
|
||||
/* ensure single partition */
|
||||
@ -424,9 +499,15 @@ 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;
|
||||
@ -435,9 +516,7 @@ int create_image(IsoImage *image, const char *image_path,
|
||||
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;
|
||||
}
|
||||
@ -451,6 +530,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;
|
||||
@ -486,7 +566,7 @@ int iso_image_set_boot_image(IsoImage *image, const char *image_path,
|
||||
"Cannot find directory for El Torito boot catalog in ISO image: '%s'",
|
||||
catdir);
|
||||
free(catdir);
|
||||
return ret < 0 ? ret : ISO_NODE_DOESNT_EXIST;
|
||||
return ret < 0 ? ret : (int) ISO_NODE_DOESNT_EXIST;
|
||||
}
|
||||
if (p->type != LIBISO_DIR) {
|
||||
free(catdir);
|
||||
@ -503,7 +583,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;
|
||||
}
|
||||
@ -519,7 +599,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;
|
||||
|
||||
@ -535,7 +618,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;
|
||||
@ -597,6 +681,30 @@ int iso_image_get_boot_image(IsoImage *image, ElToritoBootImage **boot,
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_image_get_bootcat(IsoImage *image, IsoBoot **catnode, uint32_t *lba,
|
||||
char **content, off_t *size)
|
||||
{
|
||||
IsoBoot *bootcat;
|
||||
|
||||
*catnode = NULL;
|
||||
*lba = 0;
|
||||
*content = NULL;
|
||||
*size = 0;
|
||||
bootcat = image->bootcat->node;
|
||||
if (bootcat == NULL)
|
||||
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);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int iso_image_get_all_boot_imgs(IsoImage *image, int *num_boots,
|
||||
ElToritoBootImage ***boots, IsoFile ***bootnodes, int flag)
|
||||
{
|
||||
@ -666,14 +774,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)
|
||||
@ -759,15 +871,15 @@ write_validation_entry(uint8_t *buf, uint8_t platform_id,
|
||||
static void
|
||||
write_section_header(uint8_t *buf, Ecma119Image *t, int idx, int num_entries)
|
||||
{
|
||||
int pi;
|
||||
char *id_string;
|
||||
|
||||
struct el_torito_section_header *e =
|
||||
(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);
|
||||
pi= e->platform_id[0] = t->catalog->bootimages[idx]->platform_id;
|
||||
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;;
|
||||
id_string = (char *) e->id_string;
|
||||
@ -780,12 +892,13 @@ write_section_header(uint8_t *buf, Ecma119Image *t, int idx, int num_entries)
|
||||
* 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];
|
||||
|
||||
@ -793,16 +906,69 @@ 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;
|
||||
}
|
||||
|
||||
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];
|
||||
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 {
|
||||
iso_lsb(se->sec_count, img->load_size, 2);
|
||||
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;
|
||||
@ -826,7 +992,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;
|
||||
@ -836,10 +1004,10 @@ int catalog_open(IsoStream *stream)
|
||||
for (j = i + 1; j < cat->num_bootimages; j++) {
|
||||
if (boots[i]->platform_id != boots[j]->platform_id)
|
||||
break;
|
||||
for (k = 0; k < sizeof(boots[i]->id_string); k++)
|
||||
for (k = 0; k < (int) sizeof(boots[i]->id_string); k++)
|
||||
if (boots[i]->id_string[k] != boots[j]->id_string[k])
|
||||
break;
|
||||
if (k < sizeof(boots[i]->id_string))
|
||||
if (k < (int) sizeof(boots[i]->id_string))
|
||||
break;
|
||||
}
|
||||
num_entries = j - i;
|
||||
@ -847,7 +1015,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++;
|
||||
}
|
||||
@ -895,7 +1065,7 @@ int catalog_read(IsoStream *stream, void *buf, size_t count)
|
||||
return ISO_FILE_NOT_OPENED;
|
||||
}
|
||||
|
||||
len = MIN(count, BLOCK_SIZE - data->offset);
|
||||
len = MIN(count, (size_t) (BLOCK_SIZE - data->offset));
|
||||
memcpy(buf, data->buffer + data->offset, len);
|
||||
return len;
|
||||
}
|
||||
@ -909,7 +1079,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,
|
||||
@ -935,7 +1106,11 @@ IsoStreamIface catalog_stream_class = {
|
||||
catalog_read,
|
||||
catalog_is_repeatable,
|
||||
catalog_get_id,
|
||||
catalog_free
|
||||
catalog_free,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1001,7 +1176,7 @@ int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src)
|
||||
}
|
||||
|
||||
/* fill fields */
|
||||
file->prev_img = 0; /* TODO allow copy of old img catalog???? */
|
||||
file->no_write = 0; /* TODO allow copy of old img catalog???? */
|
||||
file->checksum_index = 0;
|
||||
file->nsections = 1;
|
||||
file->sections = calloc(1, sizeof(struct iso_file_section));
|
||||
@ -1065,13 +1240,14 @@ int make_boot_info_table(uint8_t *buf, uint32_t pvd_lba,
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch an isolinux boot image.
|
||||
* Patch an El Torito boot image by a boot info table.
|
||||
*
|
||||
* @return
|
||||
* 1 on success, 0 error (but continue), < 0 error
|
||||
*/
|
||||
static
|
||||
int patch_boot_image(uint8_t *buf, Ecma119Image *t, size_t imgsize, int idx)
|
||||
int patch_boot_info_table(uint8_t *buf, Ecma119Image *t,
|
||||
size_t imgsize, int idx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -1079,42 +1255,64 @@ int patch_boot_image(uint8_t *buf, Ecma119Image *t, size_t imgsize, int idx)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Patch a GRUB2 El Torito boot image.
|
||||
*/
|
||||
static
|
||||
int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
int patch_grub2_boot_image(uint8_t *buf, Ecma119Image *t,
|
||||
size_t imgsize, int idx,
|
||||
size_t pos, int offst)
|
||||
{
|
||||
uint64_t blk;
|
||||
|
||||
if (imgsize < pos + 8)
|
||||
return iso_msg_submit(t->image->id, ISO_ISOLINUX_CANT_PATCH, 0,
|
||||
"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);
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Patch the boot images if indicated */
|
||||
int iso_patch_eltoritos(Ecma119Image *t)
|
||||
{
|
||||
/*
|
||||
* We have nothing to write, but if we need to patch an isolinux image,
|
||||
* this is a good place to do so.
|
||||
*/
|
||||
Ecma119Image *t;
|
||||
int ret, idx;
|
||||
size_t size;
|
||||
uint8_t *buf;
|
||||
IsoStream *new = NULL;
|
||||
IsoStream *original = NULL;
|
||||
|
||||
if (writer == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
if (t->catalog == NULL)
|
||||
return ISO_SUCCESS;
|
||||
|
||||
t = writer->target;
|
||||
|
||||
/* Patch the boot image info tables if indicated */
|
||||
for (idx = 0; idx < t->catalog->num_bootimages; idx++) {
|
||||
if (!(t->catalog->bootimages[idx]->isolinux_options & 0x01))
|
||||
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;
|
||||
@ -1126,14 +1324,28 @@ int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
}
|
||||
ret = iso_stream_read(original, buf, size);
|
||||
iso_stream_close(original);
|
||||
if (ret != size) {
|
||||
return (ret < 0) ? ret : ISO_FILE_READ_ERROR;
|
||||
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;
|
||||
}
|
||||
|
||||
/* ok, patch the read buffer */
|
||||
ret = patch_boot_image(buf, t, size, idx);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
if (t->catalog->bootimages[idx]->isolinux_options & 0x200) {
|
||||
/* GRUB2 boot provisions */
|
||||
ret = patch_grub2_boot_image(buf, t, size, idx,
|
||||
Libisofs_grub2_elto_patch_poS,
|
||||
Libisofs_grub2_elto_patch_offsT);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
/* Must be done as last patching */
|
||||
if (t->catalog->bootimages[idx]->isolinux_options & 0x01) {
|
||||
/* Boot Info Table */
|
||||
ret = patch_boot_info_table(buf, t, size, idx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* replace the original stream with a memory stream that reads from
|
||||
@ -1148,6 +1360,16 @@ int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
{
|
||||
/*
|
||||
* We have nothing to write.
|
||||
*/
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write the Boot Record Volume Descriptor (ECMA-119, 8.2)
|
||||
*/
|
||||
@ -1155,7 +1377,6 @@ static
|
||||
int eltorito_writer_write_vol_desc(IsoImageWriter *writer)
|
||||
{
|
||||
Ecma119Image *t;
|
||||
struct el_torito_boot_catalog *cat;
|
||||
struct ecma119_boot_rec_vol_desc vol;
|
||||
|
||||
if (writer == NULL) {
|
||||
@ -1163,7 +1384,6 @@ int eltorito_writer_write_vol_desc(IsoImageWriter *writer)
|
||||
}
|
||||
|
||||
t = writer->target;
|
||||
cat = t->catalog;
|
||||
iso_msg_debug(t->image->id, "Write El-Torito boot record");
|
||||
|
||||
memset(&vol, 0, sizeof(struct ecma119_boot_rec_vol_desc));
|
||||
@ -1192,10 +1412,10 @@ int eltorito_writer_free_data(IsoImageWriter *writer)
|
||||
|
||||
int eltorito_writer_create(Ecma119Image *target)
|
||||
{
|
||||
int ret, idx;
|
||||
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) {
|
||||
@ -1224,7 +1444,27 @@ int eltorito_writer_create(Ecma119Image *target)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
if (((target->system_area_options >> 2) & 0x3f) == 0 &&
|
||||
(target->system_area_options & 3) == 1) {
|
||||
/* ISO will not be a partition. It can span the whole image. */
|
||||
target->pvd_size_is_total_size = 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
bootimg = target->catalog->bootimages[idx]->image;
|
||||
ret = iso_file_src_create(target, bootimg, &src);
|
||||
if (ret < 0) {
|
||||
@ -1234,12 +1474,35 @@ int eltorito_writer_create(Ecma119Image *target)
|
||||
|
||||
/* For patching an image, it needs to be copied always */
|
||||
if (target->catalog->bootimages[idx]->isolinux_options & 0x01) {
|
||||
src->prev_img = 0;
|
||||
src->no_write = 0;
|
||||
}
|
||||
|
||||
/* If desired: Recognize first EFI boot image that will be newly
|
||||
written, and mark it as claimed for being a partition.
|
||||
*/
|
||||
if (outsource_efi &&
|
||||
target->catalog->bootimages[idx]->platform_id == 0xef &&
|
||||
src->no_write == 0) {
|
||||
target->efi_boot_part_filesrc = src;
|
||||
src->sections[0].block = 0xfffffffe;
|
||||
((IsoNode *) bootimg)->hidden |=
|
||||
LIBISO_HIDE_ON_HFSPLUS | LIBISO_HIDE_ON_FAT;
|
||||
outsource_efi = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* we need the bootable volume descriptor */
|
||||
target->curblock++;
|
||||
|
||||
if (outsource_efi) {
|
||||
/* Disable EFI Boot partition and complain */
|
||||
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;
|
||||
}
|
||||
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2010 Thomas Schmitt
|
||||
* Copyright (c) 2010 - 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
|
||||
@ -26,6 +26,14 @@
|
||||
struct Iso_Boot
|
||||
{
|
||||
IsoNode node;
|
||||
|
||||
/* Want to get content of loaded boot catalog.
|
||||
Vreixo took care not to make it an IsoFile at load time.
|
||||
So this is implemented independently of IsoStream.
|
||||
*/
|
||||
uint32_t lba;
|
||||
off_t size;
|
||||
char *content;
|
||||
};
|
||||
|
||||
/* Not more than 32 so that all entries fit into 2048 bytes */
|
||||
@ -45,28 +53,45 @@ struct el_torito_boot_catalog {
|
||||
struct el_torito_boot_image {
|
||||
IsoFile *image;
|
||||
|
||||
/* 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
|
||||
* bit 1 -> whether to put built-in isolinux 3.72 isohybrid-MBR into image
|
||||
* System Area (deprecated)
|
||||
*
|
||||
* bit2-7= Mentioning in isohybrid GPT
|
||||
* 0= do not mention in GPT
|
||||
* 1= mention as EFI partition
|
||||
* 2= Mention as HFS+ partition
|
||||
* bit8= Mention in isohybrid Apple partition map
|
||||
*/
|
||||
unsigned int isolinux_options:2;
|
||||
unsigned int isolinux_options;
|
||||
unsigned char type; /**< The type of image */
|
||||
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. */
|
||||
uint16_t load_seg; /**< Load segment for the initial boot image. */
|
||||
uint16_t load_size; /**< Number of sectors to load. */
|
||||
|
||||
/* Byte 1 of Validation Entry or Section Header Entry:
|
||||
0= 80x86, 1= PowerPC, 2= Mac, 0xef= EFI */
|
||||
uint8_t platform_id;
|
||||
uint8_t id_string[28];
|
||||
uint8_t selection_crit[20];
|
||||
|
||||
};
|
||||
|
||||
/** El-Torito, 2.1 */
|
||||
@ -136,5 +161,23 @@ int eltorito_writer_create(Ecma119Image *target);
|
||||
int make_boot_info_table(uint8_t *buf, uint32_t pvd_lba,
|
||||
uint32_t boot_lba, uint32_t imgsize);
|
||||
|
||||
/* Patch the boot images if indicated.
|
||||
*/
|
||||
int iso_patch_eltoritos(Ecma119Image *t);
|
||||
|
||||
|
||||
/* Parameters for patch_grub2_boot_image()
|
||||
Might later become variables in struct el_torito_boot_image.
|
||||
*/
|
||||
#define Libisofs_grub2_elto_patch_poS (512 * 5 - 12)
|
||||
#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 */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* 2010 Thomas Schmitt
|
||||
* 2010 - 2012 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
|
||||
@ -26,6 +26,8 @@
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* <<< */
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef Xorriso_standalonE
|
||||
|
||||
@ -66,7 +68,7 @@ int iso_file_src_cmp(const void *n1, const void *n2)
|
||||
|
||||
int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
|
||||
{
|
||||
int ret;
|
||||
int ret, i;
|
||||
IsoFileSrc *fsrc;
|
||||
unsigned int fs_id;
|
||||
dev_t dev_id;
|
||||
@ -86,8 +88,8 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
|
||||
}
|
||||
|
||||
/* fill key and other atts */
|
||||
fsrc->prev_img = file->from_old_session;
|
||||
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.
|
||||
*/
|
||||
@ -110,7 +112,14 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
|
||||
} else {
|
||||
fsrc->nsections = 1;
|
||||
}
|
||||
fsrc->sections = calloc(fsrc->nsections, sizeof(struct iso_file_section));
|
||||
fsrc->sections = calloc(fsrc->nsections,
|
||||
sizeof(struct iso_file_section));
|
||||
if (fsrc->sections == NULL) {
|
||||
free(fsrc);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
for (i = 0; i < fsrc->nsections; i++)
|
||||
fsrc->sections[i].block = 0;
|
||||
}
|
||||
fsrc->sort_weight = file->sort_weight;
|
||||
fsrc->stream = file->stream;
|
||||
@ -118,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) {
|
||||
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);
|
||||
@ -131,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)
|
||||
@ -143,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) {
|
||||
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)
|
||||
@ -212,41 +223,67 @@ static int cmp_by_weight(const void *f1, const void *f2)
|
||||
}
|
||||
|
||||
static
|
||||
int is_ms_file(void *arg)
|
||||
int shall_be_written(void *arg)
|
||||
{
|
||||
IsoFileSrc *f = (IsoFileSrc *)arg;
|
||||
return f->prev_img ? 0 : 1;
|
||||
return f->no_write ? 0 : 1;
|
||||
}
|
||||
|
||||
static
|
||||
int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
int shall_be_written_if_not_taken(void *arg)
|
||||
{
|
||||
size_t i, size;
|
||||
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;
|
||||
}
|
||||
|
||||
t = writer->target;
|
||||
t->filesrc_blocks = 0;
|
||||
|
||||
/* Normally reserve a single zeroed block for all files which have
|
||||
no block address: symbolic links, device files, empty data files.
|
||||
*/
|
||||
if (! t->opts->old_empty)
|
||||
t->filesrc_blocks++;
|
||||
|
||||
/* on appendable images, ms files shouldn't be included */
|
||||
if (t->appendable) {
|
||||
inc_item = is_ms_file;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -254,10 +291,18 @@ int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
for (i = 0; i < size; ++i) {
|
||||
int extent = 0;
|
||||
IsoFileSrc *file = filelist[i];
|
||||
off_t section_size;
|
||||
|
||||
off_t section_size = iso_stream_get_size(file->stream);
|
||||
/* 0xfffffffe in emerging image means that this is an external
|
||||
partition. Only assess extent sizes but do not count as part
|
||||
of filesrc_writer output.
|
||||
*/
|
||||
is_external = (file->no_write == 0 &&
|
||||
file->sections[0].block == 0xfffffffe);
|
||||
|
||||
section_size = iso_stream_get_size(file->stream);
|
||||
for (extent = 0; extent < file->nsections - 1; ++extent) {
|
||||
file->sections[extent].block = t->curblock + extent *
|
||||
file->sections[extent].block = t->filesrc_blocks + extent *
|
||||
(ISO_EXTENT_SIZE / BLOCK_SIZE);
|
||||
file->sections[extent].size = ISO_EXTENT_SIZE;
|
||||
section_size -= (off_t) ISO_EXTENT_SIZE;
|
||||
@ -267,14 +312,29 @@ int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
* final section
|
||||
*/
|
||||
if (section_size <= 0) {
|
||||
file->sections[extent].block = t->empty_file_block;
|
||||
/* Will become t->empty_file_block
|
||||
in filesrc_writer_compute_data_blocks()
|
||||
Special use of 0xffffffe0 to 0xffffffff is covered by
|
||||
mspad_writer which enforces a minimum start of filesrc at
|
||||
block 0x00000020.
|
||||
*/
|
||||
file->sections[extent].block = 0xffffffff;
|
||||
} else {
|
||||
file->sections[extent].block =
|
||||
t->curblock + extent * (ISO_EXTENT_SIZE / BLOCK_SIZE);
|
||||
t->filesrc_blocks + extent * (ISO_EXTENT_SIZE / BLOCK_SIZE);
|
||||
}
|
||||
file->sections[extent].size = (uint32_t)section_size;
|
||||
|
||||
t->curblock += DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE);
|
||||
/* 0xfffffffe in emerging image means that this is an external
|
||||
partition. Others will take care of the content data.
|
||||
*/
|
||||
if (is_external) {
|
||||
file->sections[0].block = 0xfffffffe;
|
||||
file->no_write = 1; /* Ban for filesrc_writer */
|
||||
continue;
|
||||
}
|
||||
|
||||
t->filesrc_blocks += DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE);
|
||||
}
|
||||
|
||||
/* the list is only needed by this writer, store locally */
|
||||
@ -282,6 +342,46 @@ int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
{
|
||||
Ecma119Image *t;
|
||||
int extent = 0;
|
||||
size_t i;
|
||||
IsoFileSrc *file;
|
||||
IsoFileSrc **filelist;
|
||||
|
||||
if (writer == NULL) {
|
||||
return ISO_ASSERT_FAILURE;
|
||||
}
|
||||
t = writer->target;
|
||||
filelist = (IsoFileSrc **) writer->data;
|
||||
|
||||
/* >>> HFS: need to align to allocation block size */;
|
||||
/* >>> HFS: ??? how to handle multi-extent files ? */;
|
||||
|
||||
t->filesrc_start = t->curblock;
|
||||
|
||||
/* Give all extent addresses their final absolute value */
|
||||
i = 0;
|
||||
while ((file = filelist[i++]) != NULL) {
|
||||
|
||||
/* Skip external partitions */
|
||||
if (file->no_write)
|
||||
continue;
|
||||
|
||||
for (extent = 0; extent < file->nsections; ++extent) {
|
||||
if (file->sections[extent].block == 0xffffffff)
|
||||
file->sections[extent].block = t->empty_file_block;
|
||||
else
|
||||
file->sections[extent].block += t->curblock;
|
||||
}
|
||||
}
|
||||
|
||||
t->curblock += t->filesrc_blocks;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
int filesrc_writer_write_vol_desc(IsoImageWriter *writer)
|
||||
{
|
||||
@ -324,123 +424,177 @@ int filesrc_make_md5(Ecma119Image *t, IsoFileSrc *file, char md5[16], int flag)
|
||||
return iso_stream_make_md5(file->stream, md5, 0);
|
||||
}
|
||||
|
||||
static
|
||||
int filesrc_writer_write_data(IsoImageWriter *writer)
|
||||
/* name must be NULL or offer at least PATH_MAX characters.
|
||||
buffer must be NULL or offer at least BLOCK_SIZE characters.
|
||||
*/
|
||||
int iso_filesrc_write_data(Ecma119Image *t, IsoFileSrc *file,
|
||||
char *name, char *buffer, int flag)
|
||||
{
|
||||
int res, ret, was_error;
|
||||
size_t i, b;
|
||||
Ecma119Image *t;
|
||||
IsoFileSrc *file;
|
||||
IsoFileSrc **filelist;
|
||||
char name[PATH_MAX];
|
||||
char buffer[BLOCK_SIZE];
|
||||
char *name_data = NULL;
|
||||
char *buffer_data = NULL;
|
||||
size_t b;
|
||||
off_t file_size;
|
||||
uint32_t nblocks;
|
||||
void *ctx= NULL;
|
||||
char md5[16], pre_md5[16];
|
||||
int pre_md5_valid = 0;
|
||||
IsoStream *stream, *inp;
|
||||
|
||||
#ifdef Libisofs_with_libjtE
|
||||
int jte_begun = 0;
|
||||
#endif
|
||||
|
||||
if (writer == NULL) {
|
||||
return ISO_ASSERT_FAILURE;
|
||||
if (name == NULL) {
|
||||
LIBISO_ALLOC_MEM(name_data, char, PATH_MAX);
|
||||
name = name_data;
|
||||
}
|
||||
if (buffer == NULL) {
|
||||
LIBISO_ALLOC_MEM(buffer_data, char, BLOCK_SIZE);
|
||||
buffer = buffer_data;
|
||||
}
|
||||
|
||||
t = writer->target;
|
||||
filelist = writer->data;
|
||||
was_error = 0;
|
||||
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->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);
|
||||
}
|
||||
res = filesrc_open(file);
|
||||
|
||||
iso_msg_debug(t->image->id, "Writing Files...");
|
||||
|
||||
i = 0;
|
||||
while ((file = filelist[i++]) != NULL) {
|
||||
was_error = 0;
|
||||
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)) {
|
||||
/* Obtain an MD5 of content by a first read pass */
|
||||
pre_md5_valid = filesrc_make_md5(t, file, pre_md5, 0);
|
||||
}
|
||||
res = filesrc_open(file);
|
||||
iso_stream_get_file_name(file->stream, name);
|
||||
/* Get file name from end of filter chain */
|
||||
for (stream = file->stream; ; stream = inp) {
|
||||
inp = iso_stream_get_input_stream(stream, 0);
|
||||
if (inp == NULL)
|
||||
break;
|
||||
}
|
||||
iso_stream_get_file_name(stream, name);
|
||||
if (res < 0) {
|
||||
/*
|
||||
* UPS, very ugly error, the best we can do is just to write
|
||||
* 0's to image
|
||||
*/
|
||||
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
|
||||
was_error = 1;
|
||||
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
|
||||
"File \"%s\" can't be opened. Filling with 0s.", name);
|
||||
if (res < 0) {
|
||||
/*
|
||||
* UPS, very ugly error, the best we can do is just to write
|
||||
* 0's to image
|
||||
*/
|
||||
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
|
||||
was_error = 1;
|
||||
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
|
||||
"File \"%s\" can't be opened. Filling with 0s.", name);
|
||||
ret = res; /* aborted due to error severity */
|
||||
goto ex;
|
||||
}
|
||||
memset(buffer, 0, BLOCK_SIZE);
|
||||
for (b = 0; b < nblocks; ++b) {
|
||||
res = iso_write(t, buffer, BLOCK_SIZE);
|
||||
if (res < 0) {
|
||||
ret = res; /* aborted due to error severity */
|
||||
goto ex;
|
||||
}
|
||||
memset(buffer, 0, BLOCK_SIZE);
|
||||
for (b = 0; b < nblocks; ++b) {
|
||||
res = iso_write(t, buffer, BLOCK_SIZE);
|
||||
if (res < 0) {
|
||||
/* ko, writer error, we need to go out! */
|
||||
ret = res;
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
} else if (res > 1) {
|
||||
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
|
||||
was_error = 1;
|
||||
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
|
||||
"Size of file \"%s\" has changed. It will be %s", name,
|
||||
(res == 2 ? "truncated" : "padded with 0's"));
|
||||
if (res < 0) {
|
||||
filesrc_close(file);
|
||||
ret = res; /* aborted due to error severity */
|
||||
/* ko, writer error, we need to go out! */
|
||||
ret = res;
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
ret = ISO_SUCCESS;
|
||||
goto ex;
|
||||
} else if (res > 1) {
|
||||
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
|
||||
was_error = 1;
|
||||
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
|
||||
"Size of file \"%s\" has changed. It will be %s", name,
|
||||
(res == 2 ? "truncated" : "padded with 0's"));
|
||||
if (res < 0) {
|
||||
filesrc_close(file);
|
||||
ret = res; /* aborted due to error severity */
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
#ifdef LIBISOFS_VERBOSE_DEBUG
|
||||
else {
|
||||
iso_msg_debug(t->image->id, "Writing file %s", name);
|
||||
}
|
||||
else {
|
||||
iso_msg_debug(t->image->id, "Writing file %s", name);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* >>> 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,
|
||||
BLOCK_SIZE, file_size);
|
||||
if (res <= 0) {
|
||||
res = iso_libjte_forward_msgs(t->libjte_handle, t->image->id,
|
||||
ISO_LIBJTE_FILE_FAILED, 0);
|
||||
if (res < 0) {
|
||||
filesrc_close(file);
|
||||
ret = ISO_LIBJTE_FILE_FAILED;
|
||||
goto ex;
|
||||
}
|
||||
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->opts->libjte_handle, t->image->id,
|
||||
ISO_LIBJTE_FILE_FAILED, 0);
|
||||
if (res < 0) {
|
||||
filesrc_close(file);
|
||||
ret = ISO_LIBJTE_FILE_FAILED;
|
||||
goto ex;
|
||||
}
|
||||
jte_begun = 1;
|
||||
}
|
||||
jte_begun = 1;
|
||||
}
|
||||
#endif /* Libisofs_with_libjtE */
|
||||
|
||||
if (file->checksum_index > 0) {
|
||||
/* initialize file checksum */
|
||||
res = iso_md5_start(&ctx);
|
||||
if (res <= 0)
|
||||
file->checksum_index = 0;
|
||||
}
|
||||
/* write file contents to image */
|
||||
for (b = 0; b < nblocks; ++b) {
|
||||
int wres;
|
||||
res = filesrc_read(file, buffer, BLOCK_SIZE);
|
||||
if (res < 0) {
|
||||
/* read error */
|
||||
break;
|
||||
}
|
||||
wres = iso_write(t, buffer, BLOCK_SIZE);
|
||||
if (wres < 0) {
|
||||
/* ko, writer error, we need to go out! */
|
||||
filesrc_close(file);
|
||||
ret = wres;
|
||||
goto ex;
|
||||
}
|
||||
if (file->checksum_index > 0) {
|
||||
/* initialize file checksum */
|
||||
res = iso_md5_start(&ctx);
|
||||
/* Add to file checksum */
|
||||
if (file_size - b * BLOCK_SIZE > BLOCK_SIZE)
|
||||
res = BLOCK_SIZE;
|
||||
else
|
||||
res = file_size - b * BLOCK_SIZE;
|
||||
res = iso_md5_compute(ctx, buffer, res);
|
||||
if (res <= 0)
|
||||
file->checksum_index = 0;
|
||||
}
|
||||
/* write file contents to image */
|
||||
for (b = 0; b < nblocks; ++b) {
|
||||
int wres;
|
||||
res = filesrc_read(file, buffer, BLOCK_SIZE);
|
||||
}
|
||||
|
||||
filesrc_close(file);
|
||||
|
||||
if (b < nblocks) {
|
||||
/* premature end of file, due to error or eof */
|
||||
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
|
||||
was_error = 1;
|
||||
if (res < 0) {
|
||||
/* error */
|
||||
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
|
||||
"Read error in file %s.", name);
|
||||
} else {
|
||||
/* eof */
|
||||
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
|
||||
"Premature end of file %s.", name);
|
||||
}
|
||||
|
||||
if (res < 0) {
|
||||
ret = res; /* aborted due error severity */
|
||||
goto ex;
|
||||
}
|
||||
|
||||
/* fill with 0s */
|
||||
iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
|
||||
"Filling with 0");
|
||||
memset(buffer, 0, BLOCK_SIZE);
|
||||
while (b++ < nblocks) {
|
||||
res = iso_write(t, buffer, BLOCK_SIZE);
|
||||
if (res < 0) {
|
||||
/* read error */
|
||||
break;
|
||||
}
|
||||
wres = iso_write(t, buffer, BLOCK_SIZE);
|
||||
if (wres < 0) {
|
||||
/* ko, writer error, we need to go out! */
|
||||
filesrc_close(file);
|
||||
ret = wres;
|
||||
ret = res;
|
||||
goto ex;
|
||||
}
|
||||
if (file->checksum_index > 0) {
|
||||
@ -454,89 +608,30 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
||||
file->checksum_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
filesrc_close(file);
|
||||
|
||||
if (b < nblocks) {
|
||||
/* premature end of file, due to error or eof */
|
||||
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
|
||||
was_error = 1;
|
||||
if (res < 0) {
|
||||
/* error */
|
||||
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
|
||||
"Read error in file %s.", name);
|
||||
} else {
|
||||
/* eof */
|
||||
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
|
||||
"Premature end of file %s.", name);
|
||||
}
|
||||
|
||||
if (res < 0) {
|
||||
ret = res; /* aborted due error severity */
|
||||
goto ex;
|
||||
}
|
||||
|
||||
/* fill with 0s */
|
||||
iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
|
||||
"Filling with 0");
|
||||
memset(buffer, 0, BLOCK_SIZE);
|
||||
while (b++ < nblocks) {
|
||||
res = iso_write(t, buffer, BLOCK_SIZE);
|
||||
}
|
||||
if (file->checksum_index > 0 &&
|
||||
file->checksum_index <= t->checksum_idx_counter) {
|
||||
/* Obtain checksum and dispose checksum context */
|
||||
res = iso_md5_end(&ctx, md5);
|
||||
if (res <= 0)
|
||||
file->checksum_index = 0;
|
||||
if ((t->opts->md5_file_checksums & 2) && pre_md5_valid > 0 &&
|
||||
!was_error) {
|
||||
if (! iso_md5_match(md5, pre_md5)) {
|
||||
/* Issue MISHAP event */
|
||||
iso_report_errfile(name, ISO_MD5_STREAM_CHANGE, 0, 0);
|
||||
was_error = 1;
|
||||
res = iso_msg_submit(t->image->id, ISO_MD5_STREAM_CHANGE,0,
|
||||
"Content of file '%s' changed while it was written into the image.",
|
||||
name);
|
||||
if (res < 0) {
|
||||
/* ko, writer error, we need to go out! */
|
||||
ret = res;
|
||||
ret = res; /* aborted due to error severity */
|
||||
goto ex;
|
||||
}
|
||||
if (file->checksum_index > 0) {
|
||||
/* Add to file checksum */
|
||||
if (file_size - b * BLOCK_SIZE > BLOCK_SIZE)
|
||||
res = BLOCK_SIZE;
|
||||
else
|
||||
res = file_size - b * BLOCK_SIZE;
|
||||
res = iso_md5_compute(ctx, buffer, res);
|
||||
if (res <= 0)
|
||||
file->checksum_index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (file->checksum_index > 0 &&
|
||||
file->checksum_index <= t->checksum_idx_counter) {
|
||||
/* Obtain checksum and dispose checksum context */
|
||||
res = iso_md5_end(&ctx, md5);
|
||||
if (res <= 0)
|
||||
file->checksum_index = 0;
|
||||
if ((t->md5_file_checksums & 2) && pre_md5_valid > 0 &&
|
||||
!was_error) {
|
||||
if (! iso_md5_match(md5, pre_md5)) {
|
||||
/* Issue MISHAP event */
|
||||
iso_report_errfile(name, ISO_MD5_STREAM_CHANGE, 0, 0);
|
||||
was_error = 1;
|
||||
res = iso_msg_submit(t->image->id, ISO_MD5_STREAM_CHANGE,0,
|
||||
"Content of file '%s' changed while it was written into the image.",
|
||||
name);
|
||||
if (res < 0) {
|
||||
ret = res; /* aborted due to error severity */
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Write md5 into checksum buffer at file->checksum_index */
|
||||
memcpy(t->checksum_buffer + 16 * file->checksum_index, md5, 16);
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_libjtE
|
||||
if (t->libjte_handle != NULL) {
|
||||
res = libjte_end_data_file(t->libjte_handle);
|
||||
if (res <= 0) {
|
||||
iso_libjte_forward_msgs(t->libjte_handle, t->image->id,
|
||||
ISO_LIBJTE_FILE_FAILED, 0);
|
||||
ret = ISO_LIBJTE_FILE_FAILED;
|
||||
goto ex;
|
||||
}
|
||||
jte_begun = 0;
|
||||
}
|
||||
#endif /* Libisofs_with_libjtE */
|
||||
|
||||
/* Write md5 into checksum buffer at file->checksum_index */
|
||||
memcpy(t->checksum_buffer + 16 * file->checksum_index, md5, 16);
|
||||
}
|
||||
|
||||
ret = ISO_SUCCESS;
|
||||
@ -546,15 +641,75 @@ ex:;
|
||||
|
||||
#ifdef Libisofs_with_libjtE
|
||||
if (jte_begun) {
|
||||
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;
|
||||
}
|
||||
#endif /* Libisofs_with_libjtE */
|
||||
|
||||
LIBISO_FREE_MEM(buffer_data);
|
||||
LIBISO_FREE_MEM(name_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int filesrc_writer_write_data(IsoImageWriter *writer)
|
||||
{
|
||||
int ret;
|
||||
size_t i;
|
||||
Ecma119Image *t = NULL;
|
||||
IsoFileSrc *file;
|
||||
IsoFileSrc **filelist;
|
||||
char *name = NULL;
|
||||
char *buffer = NULL;
|
||||
|
||||
if (writer == NULL) {
|
||||
ret = ISO_ASSERT_FAILURE; goto ex;
|
||||
}
|
||||
|
||||
LIBISO_ALLOC_MEM(name, char, PATH_MAX);
|
||||
LIBISO_ALLOC_MEM(buffer, char, BLOCK_SIZE);
|
||||
t = writer->target;
|
||||
filelist = writer->data;
|
||||
|
||||
iso_msg_debug(t->image->id, "Writing Files...");
|
||||
|
||||
/* Normally write a single zeroed block as block address target for all
|
||||
files which have no block address:
|
||||
symbolic links, device files, empty data files.
|
||||
*/
|
||||
if (! t->opts->old_empty) {
|
||||
ret = iso_write(t, buffer, BLOCK_SIZE);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while ((file = filelist[i++]) != NULL) {
|
||||
if (file->no_write) {
|
||||
/* Do not write external partitions */
|
||||
iso_msg_debug(t->image->id,
|
||||
"filesrc_writer: Skipping no_write-src [%.f , %.f]",
|
||||
(double) file->sections[0].block,
|
||||
(double) (file->sections[0].block - 1 +
|
||||
(file->sections[0].size + 2047) / BLOCK_SIZE));
|
||||
continue;
|
||||
}
|
||||
ret = iso_filesrc_write_data(t, file, name, buffer, 0);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
LIBISO_FREE_MEM(buffer);
|
||||
LIBISO_FREE_MEM(name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int filesrc_writer_free_data(IsoImageWriter *writer)
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* 2012 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
|
||||
@ -13,14 +14,45 @@
|
||||
#include "stream.h"
|
||||
#include "ecma119.h"
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Abstraction of data file content in the emerging image.
|
||||
*/
|
||||
struct Iso_File_Src
|
||||
{
|
||||
unsigned int prev_img :1; /**< if the file comes from a previous image */
|
||||
/* This marks an IsoFileSrc which shall only expose its extent addresses
|
||||
and sizes but shall not be counted or written by filesrc_writer.
|
||||
*/
|
||||
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 */
|
||||
/* Special sections[0].block values while they are relative
|
||||
before filesrc_writer_compute_data_blocks().
|
||||
Valid only with .no_write == 0:
|
||||
0xfffffffe This Iso_File_Src is claimed as external partition.
|
||||
Others will take care of the content data.
|
||||
filesrc_writer shall neither count nor write it.
|
||||
At write_data time it is already converted to
|
||||
a fileadress between Ecma119Image.ms_block and
|
||||
Ecma119Image.filesrc_start - 1.
|
||||
0xffffffff This is the block to which empty files shall point.
|
||||
Normal data files have relative addresses from 0 to 0xffffffdf.
|
||||
They cannot be higher, because mspad_writer forces the absolute
|
||||
filesrc addresses to start at least at 0x20.
|
||||
*/
|
||||
struct iso_file_section *sections;
|
||||
int nsections;
|
||||
|
||||
@ -87,4 +119,21 @@ off_t iso_file_src_get_size(IsoFileSrc *file);
|
||||
*/
|
||||
int iso_file_src_writer_create(Ecma119Image *target);
|
||||
|
||||
/**
|
||||
* Determine number of filesrc blocks in the image and compute extent addresses
|
||||
* relative to start of the file source writer area.
|
||||
* filesrc_writer_compute_data_blocks() later makes them absolute.
|
||||
*/
|
||||
int filesrc_writer_pre_compute(IsoImageWriter *writer);
|
||||
|
||||
/**
|
||||
* Write the content of file into the output stream of t.
|
||||
* name must be NULL or offer at least PATH_MAX characters of storage.
|
||||
* buffer must be NULL or offer at least BLOCK_SIZE characters of storage.
|
||||
* flag is not used yet, submit 0.
|
||||
*/
|
||||
int iso_filesrc_write_data(Ecma119Image *t, IsoFileSrc *file,
|
||||
char *name, char *buffer, int flag);
|
||||
|
||||
|
||||
#endif /*LIBISO_FILESRC_H_*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
* 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
|
||||
@ -20,6 +20,7 @@
|
||||
#include "../libisofs.h"
|
||||
#include "../filter.h"
|
||||
#include "../fsource.h"
|
||||
#include "../stream.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
@ -40,7 +41,7 @@
|
||||
* for classical pipe filtering.
|
||||
*/
|
||||
|
||||
|
||||
/* IMPORTANT: Any change must be reflected by extf_clone_stream() */
|
||||
/*
|
||||
* Individual runtime properties exist only as long as the stream is opened.
|
||||
*/
|
||||
@ -598,6 +599,36 @@ IsoStream *extf_get_input_stream(IsoStream *stream, int flag)
|
||||
return data->orig;
|
||||
}
|
||||
|
||||
static
|
||||
int extf_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag)
|
||||
{
|
||||
int ret;
|
||||
IsoStream *new_input_stream, *stream;
|
||||
ExternalFilterStreamData *stream_data, *old_stream_data;
|
||||
|
||||
if (flag)
|
||||
return ISO_STREAM_NO_CLONE; /* unknown option required */
|
||||
|
||||
stream_data = calloc(1, sizeof(ExternalFilterStreamData));
|
||||
if (stream_data == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
ret = iso_stream_clone_filter_common(old_stream, &stream,
|
||||
&new_input_stream, 0);
|
||||
if (ret < 0) {
|
||||
free((char *) stream_data);
|
||||
return ret;
|
||||
}
|
||||
old_stream_data = (ExternalFilterStreamData *) old_stream->data;
|
||||
stream_data->id = ++extf_ino_id;
|
||||
stream_data->orig = new_input_stream;
|
||||
stream_data->cmd = old_stream_data->cmd;
|
||||
stream_data->cmd->refcount++;
|
||||
stream_data->size = old_stream_data->size;
|
||||
stream_data->running = NULL;
|
||||
stream->data = stream_data;
|
||||
*new_stream = stream;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
int extf_cmp_ino(IsoStream *s1, IsoStream *s2);
|
||||
@ -605,7 +636,7 @@ int extf_cmp_ino(IsoStream *s1, IsoStream *s2);
|
||||
|
||||
|
||||
IsoStreamIface extf_stream_class = {
|
||||
3,
|
||||
4,
|
||||
"extf",
|
||||
extf_stream_open,
|
||||
extf_stream_close,
|
||||
@ -616,21 +647,49 @@ IsoStreamIface extf_stream_class = {
|
||||
extf_stream_free,
|
||||
extf_update_size,
|
||||
extf_get_input_stream,
|
||||
extf_cmp_ino
|
||||
extf_cmp_ino,
|
||||
extf_clone_stream
|
||||
};
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
* 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
|
||||
@ -25,6 +25,7 @@
|
||||
#include "../filter.h"
|
||||
#include "../fsource.h"
|
||||
#include "../util.h"
|
||||
#include "../stream.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
@ -153,6 +154,7 @@ static int gzip_compression_level = 6;
|
||||
/*
|
||||
* The data payload of an individual Gzip Filter IsoStream
|
||||
*/
|
||||
/* IMPORTANT: Any change must be reflected by gzip_clone_stream() */
|
||||
typedef struct
|
||||
{
|
||||
IsoStream *orig;
|
||||
@ -392,7 +394,7 @@ int gzip_stream_convert(IsoStream *stream, void *buf, size_t desired, int flag)
|
||||
if (cnv_ret == Z_STREAM_ERROR || cnv_ret == Z_BUF_ERROR) {
|
||||
return (rng->error_ret = ISO_ZLIB_COMPR_ERR);
|
||||
}
|
||||
if (strm->avail_out < rng->out_buffer_size)
|
||||
if ((int) strm->avail_out < rng->out_buffer_size)
|
||||
break; /* output is available */
|
||||
if (strm->avail_in == 0) /* all pending input consumed */
|
||||
break;
|
||||
@ -529,12 +531,54 @@ IsoStream *gzip_get_input_stream(IsoStream *stream, int flag)
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int gzip_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag)
|
||||
{
|
||||
|
||||
#ifdef Libisofs_with_zliB
|
||||
|
||||
int ret;
|
||||
IsoStream *new_input_stream, *stream;
|
||||
GzipFilterStreamData *stream_data, *old_stream_data;
|
||||
|
||||
if (flag)
|
||||
return ISO_STREAM_NO_CLONE; /* unknown option required */
|
||||
|
||||
stream_data = calloc(1, sizeof(GzipFilterStreamData));
|
||||
if (stream_data == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
ret = iso_stream_clone_filter_common(old_stream, &stream,
|
||||
&new_input_stream, 0);
|
||||
if (ret < 0) {
|
||||
free((char *) stream_data);
|
||||
return ret;
|
||||
}
|
||||
old_stream_data = (GzipFilterStreamData *) old_stream->data;
|
||||
stream_data->orig = new_input_stream;
|
||||
stream_data->size = old_stream_data->size;
|
||||
stream_data->running = NULL;
|
||||
stream_data->id = ++gzip_ino_id;
|
||||
stream->data = stream_data;
|
||||
*new_stream = stream;
|
||||
return ISO_SUCCESS;
|
||||
|
||||
#else /* Libisofs_with_zliB */
|
||||
|
||||
return ISO_STREAM_NO_CLONE;
|
||||
|
||||
#endif /* ! Libisofs_with_zliB */
|
||||
|
||||
}
|
||||
|
||||
static
|
||||
int gzip_cmp_ino(IsoStream *s1, IsoStream *s2);
|
||||
|
||||
static
|
||||
int gzip_uncompress_cmp_ino(IsoStream *s1, IsoStream *s2);
|
||||
|
||||
|
||||
IsoStreamIface gzip_stream_compress_class = {
|
||||
3,
|
||||
4,
|
||||
"gzip",
|
||||
gzip_stream_open,
|
||||
gzip_stream_close,
|
||||
@ -545,12 +589,13 @@ IsoStreamIface gzip_stream_compress_class = {
|
||||
gzip_stream_free,
|
||||
gzip_update_size,
|
||||
gzip_get_input_stream,
|
||||
gzip_cmp_ino
|
||||
gzip_cmp_ino,
|
||||
gzip_clone_stream
|
||||
};
|
||||
|
||||
|
||||
IsoStreamIface gzip_stream_uncompress_class = {
|
||||
3,
|
||||
4,
|
||||
"pizg",
|
||||
gzip_stream_open,
|
||||
gzip_stream_close,
|
||||
@ -561,16 +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);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
* 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
|
||||
@ -22,6 +22,7 @@
|
||||
#include "../filter.h"
|
||||
#include "../fsource.h"
|
||||
#include "../util.h"
|
||||
#include "../stream.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
@ -129,9 +130,9 @@ int ziso_running_new(ZisofsFilterRuntime **running, int flag)
|
||||
|
||||
o->block_size = ziso_block_size;
|
||||
#ifdef Libisofs_with_zliB
|
||||
o->buffer_size= compressBound((uLong) ziso_block_size);
|
||||
o->buffer_size = compressBound((uLong) ziso_block_size);
|
||||
#else
|
||||
o->buffer_size= 2 * ziso_block_size;
|
||||
o->buffer_size = 2 * ziso_block_size;
|
||||
#endif
|
||||
o->read_buffer = calloc(o->block_size, 1);
|
||||
o->block_buffer = calloc(o->buffer_size, 1);
|
||||
@ -167,6 +168,7 @@ static int ziso_compression_level = 6;
|
||||
|
||||
/*
|
||||
* The common data payload of an individual Zisofs Filter IsoStream
|
||||
* IMPORTANT: Any change must be reflected by ziso_clone_stream().
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
@ -183,6 +185,7 @@ typedef struct
|
||||
|
||||
/*
|
||||
* The data payload of an individual Zisofs Filter Compressor IsoStream
|
||||
* IMPORTANT: Any change must be reflected by ziso_clone_stream().
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
@ -198,6 +201,7 @@ typedef struct
|
||||
|
||||
/*
|
||||
* The data payload of an individual Zisofs Filter Uncompressor IsoStream
|
||||
* IMPORTANT: Any change must be reflected by ziso_clone_stream().
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
@ -377,7 +381,7 @@ int ziso_stream_compress(IsoStream *stream, void *buf, size_t desired)
|
||||
if (todo * 4 > rng->buffer_size)
|
||||
todo = rng->buffer_size / 4;
|
||||
memcpy(rng->block_buffer,
|
||||
data->block_pointers + 4 * rng->block_pointer_rpos,
|
||||
data->block_pointers + rng->block_pointer_rpos,
|
||||
todo * 4);
|
||||
rng->buffer_rpos = 0;
|
||||
rng->buffer_fill = todo * 4;
|
||||
@ -572,7 +576,8 @@ int ziso_stream_uncompress(IsoStream *stream, void *buf, size_t desired)
|
||||
rng->block_pointers[i] =
|
||||
iso_read_lsb((uint8_t *) (rng->block_pointers + i), 4);
|
||||
if (i > 0)
|
||||
if (rng->block_pointers[i] - rng->block_pointers[i - 1]
|
||||
if ((int) (rng->block_pointers[i] -
|
||||
rng->block_pointers[i - 1])
|
||||
> block_max)
|
||||
block_max = rng->block_pointers[i]
|
||||
- rng->block_pointers[i - 1];
|
||||
@ -615,7 +620,7 @@ int ziso_stream_uncompress(IsoStream *stream, void *buf, size_t desired)
|
||||
if (ret != Z_OK)
|
||||
return (rng->error_ret = ISO_ZLIB_COMPR_ERR);
|
||||
rng->buffer_fill = buf_len;
|
||||
if (buf_len < rng->block_size &&
|
||||
if ((int) buf_len < rng->block_size &&
|
||||
i != rng->block_pointer_fill - 1)
|
||||
return (rng->error_ret = ISO_ZISOFS_WRONG_INPUT);
|
||||
} else if(ret == 0) {
|
||||
@ -779,13 +784,66 @@ IsoStream *ziso_get_input_stream(IsoStream *stream, int flag)
|
||||
return data->orig;
|
||||
}
|
||||
|
||||
static
|
||||
int ziso_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag)
|
||||
{
|
||||
int ret;
|
||||
IsoStream *new_input_stream = NULL, *stream = NULL;
|
||||
ZisofsFilterStreamData *stream_data, *old_stream_data;
|
||||
ZisofsUncomprStreamData *uncompr, *old_uncompr;
|
||||
ZisofsComprStreamData *compr, *old_compr;
|
||||
|
||||
if (flag)
|
||||
return ISO_STREAM_NO_CLONE; /* unknown option required */
|
||||
|
||||
ret = iso_stream_clone_filter_common(old_stream, &stream,
|
||||
&new_input_stream, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (old_stream->class->read == &ziso_stream_uncompress) {
|
||||
uncompr = calloc(1, sizeof(ZisofsUncomprStreamData));
|
||||
if (uncompr == NULL)
|
||||
goto no_mem;
|
||||
stream_data = (ZisofsFilterStreamData *) uncompr;
|
||||
old_uncompr = (ZisofsUncomprStreamData *) old_stream->data;
|
||||
uncompr->header_size_div4 = old_uncompr->header_size_div4;
|
||||
uncompr->block_size_log2 = old_uncompr->block_size_log2;
|
||||
} else {
|
||||
compr = calloc(1, sizeof(ZisofsComprStreamData));
|
||||
if (compr == NULL)
|
||||
goto no_mem;
|
||||
stream_data = (ZisofsFilterStreamData *) compr;
|
||||
old_compr = (ZisofsComprStreamData *) old_stream->data;
|
||||
compr->orig_size = old_compr->orig_size;
|
||||
compr->block_pointers = NULL;
|
||||
}
|
||||
old_stream_data = (ZisofsFilterStreamData *) old_stream->data;
|
||||
stream_data->orig = new_input_stream;
|
||||
stream_data->size = old_stream_data->size;
|
||||
stream_data->running = NULL;
|
||||
stream_data->id = ++ziso_ino_id;
|
||||
stream->data = stream_data;
|
||||
*new_stream = stream;
|
||||
return ISO_SUCCESS;
|
||||
no_mem:
|
||||
if (new_input_stream != NULL)
|
||||
iso_stream_unref(new_input_stream);
|
||||
if (stream != NULL)
|
||||
iso_stream_unref(stream);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int ziso_cmp_ino(IsoStream *s1, IsoStream *s2);
|
||||
|
||||
static
|
||||
int ziso_uncompress_cmp_ino(IsoStream *s1, IsoStream *s2);
|
||||
|
||||
|
||||
IsoStreamIface ziso_stream_compress_class = {
|
||||
3,
|
||||
4,
|
||||
"ziso",
|
||||
ziso_stream_open,
|
||||
ziso_stream_close,
|
||||
@ -796,12 +854,13 @@ IsoStreamIface ziso_stream_compress_class = {
|
||||
ziso_stream_free,
|
||||
ziso_update_size,
|
||||
ziso_get_input_stream,
|
||||
ziso_cmp_ino
|
||||
ziso_cmp_ino,
|
||||
ziso_clone_stream
|
||||
};
|
||||
|
||||
|
||||
IsoStreamIface ziso_stream_uncompress_class = {
|
||||
3,
|
||||
4,
|
||||
"osiz",
|
||||
ziso_stream_open,
|
||||
ziso_stream_close,
|
||||
@ -812,16 +871,44 @@ IsoStreamIface ziso_stream_uncompress_class = {
|
||||
ziso_stream_free,
|
||||
ziso_update_size,
|
||||
ziso_get_input_stream,
|
||||
ziso_cmp_ino
|
||||
ziso_uncompress_cmp_ino,
|
||||
ziso_clone_stream
|
||||
};
|
||||
|
||||
|
||||
static
|
||||
int ziso_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
|
||||
ziso_stream_compress_class point to ziso_cmp_ino().
|
||||
*/
|
||||
if (s1->class != s2->class || (s1->class != &ziso_stream_compress_class &&
|
||||
s2->class != &ziso_stream_uncompress_class))
|
||||
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 ziso_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
|
||||
ziso_stream_uncompress_class point to ziso_uncompress_cmp_ino().
|
||||
This fallback endangers transitivity of iso_stream_cmp_ino().
|
||||
*/
|
||||
if (s1->class != s2->class ||
|
||||
(s1->class != &ziso_stream_uncompress_class &&
|
||||
s2->class != &ziso_stream_uncompress_class))
|
||||
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);
|
||||
}
|
||||
|
@ -141,11 +141,12 @@ void update_next(IsoDirIter *iter)
|
||||
static
|
||||
int find_iter_next(IsoDirIter *iter, IsoNode **node)
|
||||
{
|
||||
struct find_iter_data *data = iter->data;
|
||||
struct find_iter_data *data;
|
||||
|
||||
if (iter == NULL || node == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
data = iter->data;
|
||||
|
||||
if (data->err < 0) {
|
||||
return data->err;
|
||||
|
3265
libisofs/fs_image.c
3265
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 Thomas Schmitt
|
||||
* 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
|
||||
@ -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);
|
||||
@ -39,7 +44,7 @@ int iso_file_source_new_lfs(IsoFileSource *parent, const char *name,
|
||||
*/
|
||||
IsoFilesystem *lfs= NULL;
|
||||
|
||||
|
||||
/* IMPORTANT: Any change must be reflected by lfs_clone_src() */
|
||||
typedef struct
|
||||
{
|
||||
/** reference to the parent (if root it points to itself) */
|
||||
@ -95,14 +100,14 @@ char* lfs_get_name(IsoFileSource *src)
|
||||
static
|
||||
int lfs_lstat(IsoFileSource *src, struct stat *info)
|
||||
{
|
||||
_LocalFsFileSource *data;
|
||||
char *path;
|
||||
|
||||
if (src == NULL || info == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
data = src->data;
|
||||
path = lfs_get_path(src);
|
||||
if (path == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
|
||||
if (lstat(path, info) != 0) {
|
||||
int err;
|
||||
@ -128,6 +133,7 @@ int lfs_lstat(IsoFileSource *src, struct stat *info)
|
||||
err = ISO_FILE_ERROR;
|
||||
break;
|
||||
}
|
||||
free(path);
|
||||
return err;
|
||||
}
|
||||
free(path);
|
||||
@ -137,14 +143,14 @@ int lfs_lstat(IsoFileSource *src, struct stat *info)
|
||||
static
|
||||
int lfs_stat(IsoFileSource *src, struct stat *info)
|
||||
{
|
||||
_LocalFsFileSource *data;
|
||||
char *path;
|
||||
|
||||
if (src == NULL || info == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
data = src->data;
|
||||
path = lfs_get_path(src);
|
||||
if (path == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
|
||||
if (stat(path, info) != 0) {
|
||||
int err;
|
||||
@ -170,6 +176,7 @@ int lfs_stat(IsoFileSource *src, struct stat *info)
|
||||
err = ISO_FILE_ERROR;
|
||||
break;
|
||||
}
|
||||
free(path);
|
||||
return err;
|
||||
}
|
||||
free(path);
|
||||
@ -180,13 +187,11 @@ static
|
||||
int lfs_access(IsoFileSource *src)
|
||||
{
|
||||
int ret;
|
||||
_LocalFsFileSource *data;
|
||||
char *path;
|
||||
|
||||
if (src == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
data = src->data;
|
||||
path = lfs_get_path(src);
|
||||
|
||||
ret = iso_eaccess(path);
|
||||
@ -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:
|
||||
@ -412,8 +420,7 @@ int lfs_readdir(IsoFileSource *src, IsoFileSource **child)
|
||||
static
|
||||
int lfs_readlink(IsoFileSource *src, char *buf, size_t bufsiz)
|
||||
{
|
||||
int size;
|
||||
_LocalFsFileSource *data;
|
||||
int size, ret;
|
||||
char *path;
|
||||
|
||||
if (src == NULL || buf == NULL) {
|
||||
@ -424,14 +431,13 @@ int lfs_readlink(IsoFileSource *src, char *buf, size_t bufsiz)
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
|
||||
data = src->data;
|
||||
path = lfs_get_path(src);
|
||||
|
||||
/*
|
||||
* invoke readlink, with bufsiz -1 to reserve an space for
|
||||
* the NULL character
|
||||
*/
|
||||
size = readlink(path, buf, bufsiz - 1);
|
||||
size = readlink(path, buf, bufsiz);
|
||||
free(path);
|
||||
if (size < 0) {
|
||||
/* error */
|
||||
@ -455,8 +461,13 @@ int lfs_readlink(IsoFileSource *src, char *buf, size_t bufsiz)
|
||||
}
|
||||
|
||||
/* NULL-terminate the buf */
|
||||
ret = ISO_SUCCESS;
|
||||
if ((size_t) size >= bufsiz) {
|
||||
ret = ISO_RR_PATH_TOO_LONG;
|
||||
size = bufsiz - 1;
|
||||
}
|
||||
buf[size] = '\0';
|
||||
return ISO_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
@ -489,12 +500,10 @@ 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;
|
||||
size_t num_attrs = 0, *value_lengths = NULL, result_len;
|
||||
ssize_t sret;
|
||||
char *path = NULL, **names = NULL, **values = NULL;
|
||||
unsigned char *result = NULL;
|
||||
_LocalFsFileSource *data;
|
||||
|
||||
data = src->data;
|
||||
|
||||
*aa_string = NULL;
|
||||
|
||||
@ -506,11 +515,18 @@ int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag)
|
||||
to AAIP ACL representation. Clean out st_mode ACL entries.
|
||||
*/
|
||||
path = iso_file_source_get_path(src);
|
||||
if (path == NULL) {
|
||||
ret = ISO_NULL_POINTER;
|
||||
goto ex;
|
||||
}
|
||||
ret = aaip_get_attr_list(path, &num_attrs, &names,
|
||||
&value_lengths, &values,
|
||||
(!(flag & 2)) | 2 | (flag & 4) | 16);
|
||||
if (ret <= 0) {
|
||||
ret = ISO_FILE_ERROR;
|
||||
if (ret == -2)
|
||||
ret = ISO_AAIP_NO_GET_LOCAL;
|
||||
else
|
||||
ret = ISO_FILE_ERROR;
|
||||
goto ex;
|
||||
}
|
||||
if (num_attrs == 0)
|
||||
@ -518,10 +534,10 @@ int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag)
|
||||
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;
|
||||
@ -529,15 +545,61 @@ 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;
|
||||
}
|
||||
|
||||
static
|
||||
int lfs_clone_src(IsoFileSource *old_source,
|
||||
IsoFileSource **new_source, int flag)
|
||||
{
|
||||
IsoFileSource *src = NULL;
|
||||
char *new_name = NULL;
|
||||
_LocalFsFileSource *old_data, *new_data = NULL;
|
||||
|
||||
if (flag)
|
||||
return ISO_STREAM_NO_CLONE; /* unknown option required */
|
||||
|
||||
old_data = (_LocalFsFileSource *) old_source->data;
|
||||
*new_source = NULL;
|
||||
src = calloc(1, sizeof(IsoFileSource));
|
||||
if (src == NULL)
|
||||
goto no_mem;
|
||||
new_name = strdup(old_data->name);
|
||||
if (new_name == NULL)
|
||||
goto no_mem;
|
||||
|
||||
new_data = calloc(1, sizeof(_LocalFsFileSource));
|
||||
if (new_data == NULL)
|
||||
goto no_mem;
|
||||
new_data->openned = 0;
|
||||
new_data->info.fd = -1; /* the value does not matter with (openned == 0) */
|
||||
new_data->name = new_name;
|
||||
new_data->parent = old_data->parent;
|
||||
|
||||
src->class = old_source->class;
|
||||
src->refcount = 1;
|
||||
src->data = new_data;
|
||||
*new_source = src;
|
||||
|
||||
iso_file_source_ref(new_data->parent);
|
||||
iso_filesystem_ref(lfs);
|
||||
return ISO_SUCCESS;
|
||||
no_mem:;
|
||||
if (src != NULL)
|
||||
free((char *) src);
|
||||
if (new_data != NULL)
|
||||
free((char *) new_data);
|
||||
if (new_name != NULL)
|
||||
free(new_name);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
|
||||
|
||||
IsoFileSourceIface lfs_class = {
|
||||
|
||||
1, /* version */
|
||||
2, /* version */
|
||||
lfs_get_path,
|
||||
lfs_get_name,
|
||||
lfs_lstat,
|
||||
@ -551,7 +613,8 @@ IsoFileSourceIface lfs_class = {
|
||||
lfs_get_filesystem,
|
||||
lfs_free,
|
||||
lfs_lseek,
|
||||
lfs_get_aa_string
|
||||
lfs_get_aa_string,
|
||||
lfs_clone_src
|
||||
|
||||
};
|
||||
|
||||
@ -765,6 +828,15 @@ int iso_local_filesystem_new(IsoFilesystem **fs)
|
||||
}
|
||||
|
||||
|
||||
int iso_local_attr_support(int flag)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret= aaip_local_attr_support(flag & 255);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int iso_local_get_acl_text(char *disk_path, char **text, int flag)
|
||||
{
|
||||
int ret;
|
||||
@ -805,13 +877,19 @@ int iso_local_set_attrs(char *disk_path, size_t num_attrs, char **names,
|
||||
int ret;
|
||||
|
||||
ret = aaip_set_attr_list(disk_path, num_attrs, names, value_lengths,
|
||||
values, (flag & (8 | 32)) | !(flag & 1));
|
||||
values, (flag & (8 | 32 | 64)) | !(flag & 1));
|
||||
if (ret <= 0) {
|
||||
if (ret == -1)
|
||||
return ISO_OUT_OF_MEM;
|
||||
if (ret == -2)
|
||||
return ISO_AAIP_BAD_AASTRING;
|
||||
return ISO_AAIP_NO_SET_LOCAL;
|
||||
if (ret >= -5)
|
||||
return ISO_AAIP_NO_SET_LOCAL;
|
||||
if (ret == -6 || ret == -7)
|
||||
return ISO_AAIP_NOT_ENABLED;
|
||||
if (ret == -8)
|
||||
return ISO_AAIP_BAD_ATTR_NAME;
|
||||
return ret;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 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
|
||||
@ -28,14 +28,25 @@
|
||||
* 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 by their eventual old image LBAs.
|
||||
Other IsoFileSource classes will be ranked only roughly.
|
||||
/* Rank two IsoFileSource of ifs_class by their eventual old image LBAs.
|
||||
* @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.
|
||||
*/
|
||||
int iso_ifs_source_clone(IsoFileSource *old_source, IsoFileSource **new_source,
|
||||
int flag);
|
||||
|
||||
|
||||
#endif /*LIBISO_FSOURCE_H_*/
|
||||
|
1870
libisofs/hfsplus.c
Normal file
1870
libisofs/hfsplus.c
Normal file
File diff suppressed because it is too large
Load Diff
201
libisofs/hfsplus.h
Normal file
201
libisofs/hfsplus.h
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Vladimir Serbinenko
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Declare HFS+ related structures.
|
||||
*/
|
||||
|
||||
#ifndef LIBISO_HFSPLUS_H
|
||||
#define LIBISO_HFSPLUS_H
|
||||
|
||||
#include "libisofs.h"
|
||||
#include "ecma119.h"
|
||||
|
||||
#define LIBISO_HFSPLUS_NAME_MAX 255
|
||||
|
||||
|
||||
enum hfsplus_node_type {
|
||||
HFSPLUS_DIR = 1,
|
||||
HFSPLUS_FILE = 2,
|
||||
HFSPLUS_DIR_THREAD = 3,
|
||||
HFSPLUS_FILE_THREAD = 4
|
||||
};
|
||||
|
||||
struct hfsplus_btree_node
|
||||
{
|
||||
uint32_t start;
|
||||
uint32_t cnt;
|
||||
uint32_t strlen;
|
||||
uint16_t *str;
|
||||
uint32_t parent_id;
|
||||
};
|
||||
|
||||
struct hfsplus_btree_level
|
||||
{
|
||||
uint32_t level_size;
|
||||
struct hfsplus_btree_node *nodes;
|
||||
};
|
||||
|
||||
struct hfsplus_node
|
||||
{
|
||||
/* Note: .type HFSPLUS_DIR_THREAD and HFSPLUS_FILE_THREAD do not own their
|
||||
.name and .cmp_name. They have copies of others, if ever.
|
||||
*/
|
||||
uint16_t *name; /* Name in UTF-16BE, decomposed. */
|
||||
uint16_t *cmp_name; /* Name used for comparing. */
|
||||
|
||||
IsoNode *node; /*< reference to the iso node */
|
||||
|
||||
enum { UNIX_NONE, UNIX_SYMLINK, UNIX_SPECIAL } unix_type;
|
||||
uint32_t symlink_block;
|
||||
char *symlink_dest;
|
||||
|
||||
enum hfsplus_node_type type;
|
||||
IsoFileSrc *file;
|
||||
uint32_t cat_id;
|
||||
uint32_t parent_id;
|
||||
uint32_t nchildren;
|
||||
|
||||
uint32_t strlen;
|
||||
uint32_t used_size;
|
||||
};
|
||||
|
||||
int hfsplus_writer_create(Ecma119Image *target);
|
||||
int hfsplus_tail_writer_create(Ecma119Image *target);
|
||||
|
||||
struct hfsplus_extent
|
||||
{
|
||||
/* The first block of a file on disk. */
|
||||
uint32_t start;
|
||||
/* The amount of blocks described by this extent. */
|
||||
uint32_t count;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct hfsplus_forkdata
|
||||
{
|
||||
uint64_t size;
|
||||
uint32_t clumpsize;
|
||||
uint32_t blocks;
|
||||
struct hfsplus_extent extents[8];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct hfsplus_volheader
|
||||
{
|
||||
uint16_t magic;
|
||||
uint16_t version;
|
||||
uint32_t attributes;
|
||||
uint32_t last_mounted_version;
|
||||
uint32_t journal;
|
||||
uint32_t ctime;
|
||||
uint32_t utime;
|
||||
uint32_t backup_time;
|
||||
uint32_t fsck_time;
|
||||
uint32_t file_count;
|
||||
uint32_t folder_count;
|
||||
uint32_t blksize;
|
||||
uint32_t total_blocks;
|
||||
uint32_t free_blocks;
|
||||
uint32_t next_allocation;
|
||||
uint32_t rsrc_clumpsize;
|
||||
uint32_t data_clumpsize;
|
||||
uint32_t catalog_node_id;
|
||||
uint32_t write_count;
|
||||
uint64_t encodings_bitmap;
|
||||
uint32_t ppc_bootdir;
|
||||
uint32_t intel_bootfile;
|
||||
/* Folder opened when disk is mounted. */
|
||||
uint32_t showfolder;
|
||||
uint32_t os9folder;
|
||||
uint32_t unused;
|
||||
uint32_t osxfolder;
|
||||
uint64_t num_serial;
|
||||
struct hfsplus_forkdata allocations_file;
|
||||
struct hfsplus_forkdata extents_file;
|
||||
struct hfsplus_forkdata catalog_file;
|
||||
struct hfsplus_forkdata attrib_file;
|
||||
struct hfsplus_forkdata startup_file;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct hfsplus_btnode
|
||||
{
|
||||
uint32_t next;
|
||||
uint32_t prev;
|
||||
int8_t type;
|
||||
uint8_t height;
|
||||
uint16_t count;
|
||||
uint16_t unused;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* The header of a HFS+ B+ Tree. */
|
||||
struct hfsplus_btheader
|
||||
{
|
||||
uint16_t depth;
|
||||
uint32_t root;
|
||||
uint32_t leaf_records;
|
||||
uint32_t first_leaf_node;
|
||||
uint32_t last_leaf_node;
|
||||
uint16_t nodesize;
|
||||
uint16_t keysize;
|
||||
uint32_t total_nodes;
|
||||
uint32_t free_nodes;
|
||||
uint16_t reserved1;
|
||||
uint32_t clump_size;
|
||||
uint8_t btree_type;
|
||||
uint8_t key_compare;
|
||||
uint32_t attributes;
|
||||
uint32_t reserved[16];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct hfsplus_catfile_thread
|
||||
{
|
||||
uint16_t type;
|
||||
uint16_t reserved;
|
||||
uint32_t parentid;
|
||||
uint16_t namelen;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct hfsplus_catfile_common
|
||||
{
|
||||
uint16_t type;
|
||||
uint16_t flags;
|
||||
uint32_t valence; /* for files: reserved. */
|
||||
uint32_t fileid;
|
||||
uint32_t ctime;
|
||||
uint32_t mtime;
|
||||
uint32_t attr_mtime;
|
||||
uint32_t atime;
|
||||
uint32_t backup_time;
|
||||
uint32_t uid;
|
||||
uint32_t gid;
|
||||
uint8_t user_flags;
|
||||
uint8_t group_flags;
|
||||
uint16_t mode;
|
||||
uint32_t special;
|
||||
uint8_t file_type[4]; /* For folders: window size */
|
||||
uint8_t file_creator[4]; /* For folders: window size */
|
||||
uint8_t finder_info[24];
|
||||
uint32_t text_encoding;
|
||||
uint32_t reserved;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define HFSPLUS_MAX_DECOMPOSE_LEN 4
|
||||
|
||||
extern uint16_t (*hfsplus_decompose_pages[256])[HFSPLUS_MAX_DECOMPOSE_LEN + 1];
|
||||
void make_hfsplus_decompose_pages();
|
||||
|
||||
extern uint16_t *hfsplus_class_pages[256];
|
||||
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);
|
||||
|
||||
|
||||
#endif /* LIBISO_HFSPLUS_H */
|
472
libisofs/hfsplus_case.c
Normal file
472
libisofs/hfsplus_case.c
Normal file
@ -0,0 +1,472 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Maps UTF-16BE double-byte characters to the representative of their
|
||||
* equivalence class under the relation of HFS+ case-insensitivity.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include "libisofs.h"
|
||||
|
||||
|
||||
/* The translation list utf16be_transl was generated by a program which
|
||||
compared input and output of existing example code by Apple Inc.
|
||||
found published on
|
||||
http://developer.apple.com/legacy/mac/library/#technotes/tn/tn1150.html
|
||||
|
||||
Each deviation was recorded as pair of byte pairs. The first pair gives
|
||||
the input, the second pair gives the output. If a byte pair is not mentioned
|
||||
in this list as input, then it gets mapped to itself.
|
||||
Pairs which get mapped to pair 0,0 shall be ignored with HFS+ comparisons.
|
||||
|
||||
Another comparison run verified that both implementations yield the same
|
||||
character translation with all 65536 possible input bit patterns.
|
||||
*/
|
||||
static uint8_t utf16be_transl[] = {
|
||||
0x00, 0x00, 0xff, 0xff,
|
||||
0x00, 0x41, 0x00, 0x61,
|
||||
0x00, 0x42, 0x00, 0x62,
|
||||
0x00, 0x43, 0x00, 0x63,
|
||||
0x00, 0x44, 0x00, 0x64,
|
||||
0x00, 0x45, 0x00, 0x65,
|
||||
0x00, 0x46, 0x00, 0x66,
|
||||
0x00, 0x47, 0x00, 0x67,
|
||||
0x00, 0x48, 0x00, 0x68,
|
||||
0x00, 0x49, 0x00, 0x69,
|
||||
0x00, 0x4a, 0x00, 0x6a,
|
||||
0x00, 0x4b, 0x00, 0x6b,
|
||||
0x00, 0x4c, 0x00, 0x6c,
|
||||
0x00, 0x4d, 0x00, 0x6d,
|
||||
0x00, 0x4e, 0x00, 0x6e,
|
||||
0x00, 0x4f, 0x00, 0x6f,
|
||||
0x00, 0x50, 0x00, 0x70,
|
||||
0x00, 0x51, 0x00, 0x71,
|
||||
0x00, 0x52, 0x00, 0x72,
|
||||
0x00, 0x53, 0x00, 0x73,
|
||||
0x00, 0x54, 0x00, 0x74,
|
||||
0x00, 0x55, 0x00, 0x75,
|
||||
0x00, 0x56, 0x00, 0x76,
|
||||
0x00, 0x57, 0x00, 0x77,
|
||||
0x00, 0x58, 0x00, 0x78,
|
||||
0x00, 0x59, 0x00, 0x79,
|
||||
0x00, 0x5a, 0x00, 0x7a,
|
||||
0x00, 0xc6, 0x00, 0xe6,
|
||||
0x00, 0xd0, 0x00, 0xf0,
|
||||
0x00, 0xd8, 0x00, 0xf8,
|
||||
0x00, 0xde, 0x00, 0xfe,
|
||||
0x01, 0x10, 0x01, 0x11,
|
||||
0x01, 0x26, 0x01, 0x27,
|
||||
0x01, 0x32, 0x01, 0x33,
|
||||
0x01, 0x3f, 0x01, 0x40,
|
||||
0x01, 0x41, 0x01, 0x42,
|
||||
0x01, 0x4a, 0x01, 0x4b,
|
||||
0x01, 0x52, 0x01, 0x53,
|
||||
0x01, 0x66, 0x01, 0x67,
|
||||
0x01, 0x81, 0x02, 0x53,
|
||||
0x01, 0x82, 0x01, 0x83,
|
||||
0x01, 0x84, 0x01, 0x85,
|
||||
0x01, 0x86, 0x02, 0x54,
|
||||
0x01, 0x87, 0x01, 0x88,
|
||||
0x01, 0x89, 0x02, 0x56,
|
||||
0x01, 0x8a, 0x02, 0x57,
|
||||
0x01, 0x8b, 0x01, 0x8c,
|
||||
0x01, 0x8e, 0x01, 0xdd,
|
||||
0x01, 0x8f, 0x02, 0x59,
|
||||
0x01, 0x90, 0x02, 0x5b,
|
||||
0x01, 0x91, 0x01, 0x92,
|
||||
0x01, 0x93, 0x02, 0x60,
|
||||
0x01, 0x94, 0x02, 0x63,
|
||||
0x01, 0x96, 0x02, 0x69,
|
||||
0x01, 0x97, 0x02, 0x68,
|
||||
0x01, 0x98, 0x01, 0x99,
|
||||
0x01, 0x9c, 0x02, 0x6f,
|
||||
0x01, 0x9d, 0x02, 0x72,
|
||||
0x01, 0x9f, 0x02, 0x75,
|
||||
0x01, 0xa2, 0x01, 0xa3,
|
||||
0x01, 0xa4, 0x01, 0xa5,
|
||||
0x01, 0xa7, 0x01, 0xa8,
|
||||
0x01, 0xa9, 0x02, 0x83,
|
||||
0x01, 0xac, 0x01, 0xad,
|
||||
0x01, 0xae, 0x02, 0x88,
|
||||
0x01, 0xb1, 0x02, 0x8a,
|
||||
0x01, 0xb2, 0x02, 0x8b,
|
||||
0x01, 0xb3, 0x01, 0xb4,
|
||||
0x01, 0xb5, 0x01, 0xb6,
|
||||
0x01, 0xb7, 0x02, 0x92,
|
||||
0x01, 0xb8, 0x01, 0xb9,
|
||||
0x01, 0xbc, 0x01, 0xbd,
|
||||
0x01, 0xc4, 0x01, 0xc6,
|
||||
0x01, 0xc5, 0x01, 0xc6,
|
||||
0x01, 0xc7, 0x01, 0xc9,
|
||||
0x01, 0xc8, 0x01, 0xc9,
|
||||
0x01, 0xca, 0x01, 0xcc,
|
||||
0x01, 0xcb, 0x01, 0xcc,
|
||||
0x01, 0xe4, 0x01, 0xe5,
|
||||
0x01, 0xf1, 0x01, 0xf3,
|
||||
0x01, 0xf2, 0x01, 0xf3,
|
||||
0x03, 0x91, 0x03, 0xb1,
|
||||
0x03, 0x92, 0x03, 0xb2,
|
||||
0x03, 0x93, 0x03, 0xb3,
|
||||
0x03, 0x94, 0x03, 0xb4,
|
||||
0x03, 0x95, 0x03, 0xb5,
|
||||
0x03, 0x96, 0x03, 0xb6,
|
||||
0x03, 0x97, 0x03, 0xb7,
|
||||
0x03, 0x98, 0x03, 0xb8,
|
||||
0x03, 0x99, 0x03, 0xb9,
|
||||
0x03, 0x9a, 0x03, 0xba,
|
||||
0x03, 0x9b, 0x03, 0xbb,
|
||||
0x03, 0x9c, 0x03, 0xbc,
|
||||
0x03, 0x9d, 0x03, 0xbd,
|
||||
0x03, 0x9e, 0x03, 0xbe,
|
||||
0x03, 0x9f, 0x03, 0xbf,
|
||||
0x03, 0xa0, 0x03, 0xc0,
|
||||
0x03, 0xa1, 0x03, 0xc1,
|
||||
0x03, 0xa3, 0x03, 0xc3,
|
||||
0x03, 0xa4, 0x03, 0xc4,
|
||||
0x03, 0xa5, 0x03, 0xc5,
|
||||
0x03, 0xa6, 0x03, 0xc6,
|
||||
0x03, 0xa7, 0x03, 0xc7,
|
||||
0x03, 0xa8, 0x03, 0xc8,
|
||||
0x03, 0xa9, 0x03, 0xc9,
|
||||
0x03, 0xe2, 0x03, 0xe3,
|
||||
0x03, 0xe4, 0x03, 0xe5,
|
||||
0x03, 0xe6, 0x03, 0xe7,
|
||||
0x03, 0xe8, 0x03, 0xe9,
|
||||
0x03, 0xea, 0x03, 0xeb,
|
||||
0x03, 0xec, 0x03, 0xed,
|
||||
0x03, 0xee, 0x03, 0xef,
|
||||
0x04, 0x02, 0x04, 0x52,
|
||||
0x04, 0x04, 0x04, 0x54,
|
||||
0x04, 0x05, 0x04, 0x55,
|
||||
0x04, 0x06, 0x04, 0x56,
|
||||
0x04, 0x08, 0x04, 0x58,
|
||||
0x04, 0x09, 0x04, 0x59,
|
||||
0x04, 0x0a, 0x04, 0x5a,
|
||||
0x04, 0x0b, 0x04, 0x5b,
|
||||
0x04, 0x0f, 0x04, 0x5f,
|
||||
0x04, 0x10, 0x04, 0x30,
|
||||
0x04, 0x11, 0x04, 0x31,
|
||||
0x04, 0x12, 0x04, 0x32,
|
||||
0x04, 0x13, 0x04, 0x33,
|
||||
0x04, 0x14, 0x04, 0x34,
|
||||
0x04, 0x15, 0x04, 0x35,
|
||||
0x04, 0x16, 0x04, 0x36,
|
||||
0x04, 0x17, 0x04, 0x37,
|
||||
0x04, 0x18, 0x04, 0x38,
|
||||
0x04, 0x1a, 0x04, 0x3a,
|
||||
0x04, 0x1b, 0x04, 0x3b,
|
||||
0x04, 0x1c, 0x04, 0x3c,
|
||||
0x04, 0x1d, 0x04, 0x3d,
|
||||
0x04, 0x1e, 0x04, 0x3e,
|
||||
0x04, 0x1f, 0x04, 0x3f,
|
||||
0x04, 0x20, 0x04, 0x40,
|
||||
0x04, 0x21, 0x04, 0x41,
|
||||
0x04, 0x22, 0x04, 0x42,
|
||||
0x04, 0x23, 0x04, 0x43,
|
||||
0x04, 0x24, 0x04, 0x44,
|
||||
0x04, 0x25, 0x04, 0x45,
|
||||
0x04, 0x26, 0x04, 0x46,
|
||||
0x04, 0x27, 0x04, 0x47,
|
||||
0x04, 0x28, 0x04, 0x48,
|
||||
0x04, 0x29, 0x04, 0x49,
|
||||
0x04, 0x2a, 0x04, 0x4a,
|
||||
0x04, 0x2b, 0x04, 0x4b,
|
||||
0x04, 0x2c, 0x04, 0x4c,
|
||||
0x04, 0x2d, 0x04, 0x4d,
|
||||
0x04, 0x2e, 0x04, 0x4e,
|
||||
0x04, 0x2f, 0x04, 0x4f,
|
||||
0x04, 0x60, 0x04, 0x61,
|
||||
0x04, 0x62, 0x04, 0x63,
|
||||
0x04, 0x64, 0x04, 0x65,
|
||||
0x04, 0x66, 0x04, 0x67,
|
||||
0x04, 0x68, 0x04, 0x69,
|
||||
0x04, 0x6a, 0x04, 0x6b,
|
||||
0x04, 0x6c, 0x04, 0x6d,
|
||||
0x04, 0x6e, 0x04, 0x6f,
|
||||
0x04, 0x70, 0x04, 0x71,
|
||||
0x04, 0x72, 0x04, 0x73,
|
||||
0x04, 0x74, 0x04, 0x75,
|
||||
0x04, 0x78, 0x04, 0x79,
|
||||
0x04, 0x7a, 0x04, 0x7b,
|
||||
0x04, 0x7c, 0x04, 0x7d,
|
||||
0x04, 0x7e, 0x04, 0x7f,
|
||||
0x04, 0x80, 0x04, 0x81,
|
||||
0x04, 0x90, 0x04, 0x91,
|
||||
0x04, 0x92, 0x04, 0x93,
|
||||
0x04, 0x94, 0x04, 0x95,
|
||||
0x04, 0x96, 0x04, 0x97,
|
||||
0x04, 0x98, 0x04, 0x99,
|
||||
0x04, 0x9a, 0x04, 0x9b,
|
||||
0x04, 0x9c, 0x04, 0x9d,
|
||||
0x04, 0x9e, 0x04, 0x9f,
|
||||
0x04, 0xa0, 0x04, 0xa1,
|
||||
0x04, 0xa2, 0x04, 0xa3,
|
||||
0x04, 0xa4, 0x04, 0xa5,
|
||||
0x04, 0xa6, 0x04, 0xa7,
|
||||
0x04, 0xa8, 0x04, 0xa9,
|
||||
0x04, 0xaa, 0x04, 0xab,
|
||||
0x04, 0xac, 0x04, 0xad,
|
||||
0x04, 0xae, 0x04, 0xaf,
|
||||
0x04, 0xb0, 0x04, 0xb1,
|
||||
0x04, 0xb2, 0x04, 0xb3,
|
||||
0x04, 0xb4, 0x04, 0xb5,
|
||||
0x04, 0xb6, 0x04, 0xb7,
|
||||
0x04, 0xb8, 0x04, 0xb9,
|
||||
0x04, 0xba, 0x04, 0xbb,
|
||||
0x04, 0xbc, 0x04, 0xbd,
|
||||
0x04, 0xbe, 0x04, 0xbf,
|
||||
0x04, 0xc3, 0x04, 0xc4,
|
||||
0x04, 0xc7, 0x04, 0xc8,
|
||||
0x04, 0xcb, 0x04, 0xcc,
|
||||
0x05, 0x31, 0x05, 0x61,
|
||||
0x05, 0x32, 0x05, 0x62,
|
||||
0x05, 0x33, 0x05, 0x63,
|
||||
0x05, 0x34, 0x05, 0x64,
|
||||
0x05, 0x35, 0x05, 0x65,
|
||||
0x05, 0x36, 0x05, 0x66,
|
||||
0x05, 0x37, 0x05, 0x67,
|
||||
0x05, 0x38, 0x05, 0x68,
|
||||
0x05, 0x39, 0x05, 0x69,
|
||||
0x05, 0x3a, 0x05, 0x6a,
|
||||
0x05, 0x3b, 0x05, 0x6b,
|
||||
0x05, 0x3c, 0x05, 0x6c,
|
||||
0x05, 0x3d, 0x05, 0x6d,
|
||||
0x05, 0x3e, 0x05, 0x6e,
|
||||
0x05, 0x3f, 0x05, 0x6f,
|
||||
0x05, 0x40, 0x05, 0x70,
|
||||
0x05, 0x41, 0x05, 0x71,
|
||||
0x05, 0x42, 0x05, 0x72,
|
||||
0x05, 0x43, 0x05, 0x73,
|
||||
0x05, 0x44, 0x05, 0x74,
|
||||
0x05, 0x45, 0x05, 0x75,
|
||||
0x05, 0x46, 0x05, 0x76,
|
||||
0x05, 0x47, 0x05, 0x77,
|
||||
0x05, 0x48, 0x05, 0x78,
|
||||
0x05, 0x49, 0x05, 0x79,
|
||||
0x05, 0x4a, 0x05, 0x7a,
|
||||
0x05, 0x4b, 0x05, 0x7b,
|
||||
0x05, 0x4c, 0x05, 0x7c,
|
||||
0x05, 0x4d, 0x05, 0x7d,
|
||||
0x05, 0x4e, 0x05, 0x7e,
|
||||
0x05, 0x4f, 0x05, 0x7f,
|
||||
0x05, 0x50, 0x05, 0x80,
|
||||
0x05, 0x51, 0x05, 0x81,
|
||||
0x05, 0x52, 0x05, 0x82,
|
||||
0x05, 0x53, 0x05, 0x83,
|
||||
0x05, 0x54, 0x05, 0x84,
|
||||
0x05, 0x55, 0x05, 0x85,
|
||||
0x05, 0x56, 0x05, 0x86,
|
||||
0x10, 0xa0, 0x10, 0xd0,
|
||||
0x10, 0xa1, 0x10, 0xd1,
|
||||
0x10, 0xa2, 0x10, 0xd2,
|
||||
0x10, 0xa3, 0x10, 0xd3,
|
||||
0x10, 0xa4, 0x10, 0xd4,
|
||||
0x10, 0xa5, 0x10, 0xd5,
|
||||
0x10, 0xa6, 0x10, 0xd6,
|
||||
0x10, 0xa7, 0x10, 0xd7,
|
||||
0x10, 0xa8, 0x10, 0xd8,
|
||||
0x10, 0xa9, 0x10, 0xd9,
|
||||
0x10, 0xaa, 0x10, 0xda,
|
||||
0x10, 0xab, 0x10, 0xdb,
|
||||
0x10, 0xac, 0x10, 0xdc,
|
||||
0x10, 0xad, 0x10, 0xdd,
|
||||
0x10, 0xae, 0x10, 0xde,
|
||||
0x10, 0xaf, 0x10, 0xdf,
|
||||
0x10, 0xb0, 0x10, 0xe0,
|
||||
0x10, 0xb1, 0x10, 0xe1,
|
||||
0x10, 0xb2, 0x10, 0xe2,
|
||||
0x10, 0xb3, 0x10, 0xe3,
|
||||
0x10, 0xb4, 0x10, 0xe4,
|
||||
0x10, 0xb5, 0x10, 0xe5,
|
||||
0x10, 0xb6, 0x10, 0xe6,
|
||||
0x10, 0xb7, 0x10, 0xe7,
|
||||
0x10, 0xb8, 0x10, 0xe8,
|
||||
0x10, 0xb9, 0x10, 0xe9,
|
||||
0x10, 0xba, 0x10, 0xea,
|
||||
0x10, 0xbb, 0x10, 0xeb,
|
||||
0x10, 0xbc, 0x10, 0xec,
|
||||
0x10, 0xbd, 0x10, 0xed,
|
||||
0x10, 0xbe, 0x10, 0xee,
|
||||
0x10, 0xbf, 0x10, 0xef,
|
||||
0x10, 0xc0, 0x10, 0xf0,
|
||||
0x10, 0xc1, 0x10, 0xf1,
|
||||
0x10, 0xc2, 0x10, 0xf2,
|
||||
0x10, 0xc3, 0x10, 0xf3,
|
||||
0x10, 0xc4, 0x10, 0xf4,
|
||||
0x10, 0xc5, 0x10, 0xf5,
|
||||
0x20, 0x0c, 0x00, 0x00,
|
||||
0x20, 0x0d, 0x00, 0x00,
|
||||
0x20, 0x0e, 0x00, 0x00,
|
||||
0x20, 0x0f, 0x00, 0x00,
|
||||
0x20, 0x2a, 0x00, 0x00,
|
||||
0x20, 0x2b, 0x00, 0x00,
|
||||
0x20, 0x2c, 0x00, 0x00,
|
||||
0x20, 0x2d, 0x00, 0x00,
|
||||
0x20, 0x2e, 0x00, 0x00,
|
||||
0x20, 0x6a, 0x00, 0x00,
|
||||
0x20, 0x6b, 0x00, 0x00,
|
||||
0x20, 0x6c, 0x00, 0x00,
|
||||
0x20, 0x6d, 0x00, 0x00,
|
||||
0x20, 0x6e, 0x00, 0x00,
|
||||
0x20, 0x6f, 0x00, 0x00,
|
||||
0x21, 0x60, 0x21, 0x70,
|
||||
0x21, 0x61, 0x21, 0x71,
|
||||
0x21, 0x62, 0x21, 0x72,
|
||||
0x21, 0x63, 0x21, 0x73,
|
||||
0x21, 0x64, 0x21, 0x74,
|
||||
0x21, 0x65, 0x21, 0x75,
|
||||
0x21, 0x66, 0x21, 0x76,
|
||||
0x21, 0x67, 0x21, 0x77,
|
||||
0x21, 0x68, 0x21, 0x78,
|
||||
0x21, 0x69, 0x21, 0x79,
|
||||
0x21, 0x6a, 0x21, 0x7a,
|
||||
0x21, 0x6b, 0x21, 0x7b,
|
||||
0x21, 0x6c, 0x21, 0x7c,
|
||||
0x21, 0x6d, 0x21, 0x7d,
|
||||
0x21, 0x6e, 0x21, 0x7e,
|
||||
0x21, 0x6f, 0x21, 0x7f,
|
||||
0xfe, 0xff, 0x00, 0x00,
|
||||
0xff, 0x21, 0xff, 0x41,
|
||||
0xff, 0x22, 0xff, 0x42,
|
||||
0xff, 0x23, 0xff, 0x43,
|
||||
0xff, 0x24, 0xff, 0x44,
|
||||
0xff, 0x25, 0xff, 0x45,
|
||||
0xff, 0x26, 0xff, 0x46,
|
||||
0xff, 0x27, 0xff, 0x47,
|
||||
0xff, 0x28, 0xff, 0x48,
|
||||
0xff, 0x29, 0xff, 0x49,
|
||||
0xff, 0x2a, 0xff, 0x4a,
|
||||
0xff, 0x2b, 0xff, 0x4b,
|
||||
0xff, 0x2c, 0xff, 0x4c,
|
||||
0xff, 0x2d, 0xff, 0x4d,
|
||||
0xff, 0x2e, 0xff, 0x4e,
|
||||
0xff, 0x2f, 0xff, 0x4f,
|
||||
0xff, 0x30, 0xff, 0x50,
|
||||
0xff, 0x31, 0xff, 0x51,
|
||||
0xff, 0x32, 0xff, 0x52,
|
||||
0xff, 0x33, 0xff, 0x53,
|
||||
0xff, 0x34, 0xff, 0x54,
|
||||
0xff, 0x35, 0xff, 0x55,
|
||||
0xff, 0x36, 0xff, 0x56,
|
||||
0xff, 0x37, 0xff, 0x57,
|
||||
0xff, 0x38, 0xff, 0x58,
|
||||
0xff, 0x39, 0xff, 0x59,
|
||||
0xff, 0x3a, 0xff, 0x5a,
|
||||
0x00
|
||||
};
|
||||
static int utf16be_transl_count = 329;
|
||||
|
||||
/* These are the start indice in utf16be_transl[] for the page numbers 0 to 9
|
||||
as classified by function what_page().
|
||||
As soon as the first byte of the input pair in utf16be_transl[] changes,
|
||||
the search can be ended and output is equal to input.
|
||||
If page -1 is returned by what_page(), then input is equal to output.
|
||||
*/
|
||||
static int utf16be_transl_starts[] = {
|
||||
0, 31, 81, 112, 195, 233, 271, 286, 302, 303
|
||||
};
|
||||
|
||||
|
||||
static int what_page(uint16_t x)
|
||||
{
|
||||
switch(((uint8_t *) &x)[0]) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return 1;
|
||||
case 3:
|
||||
return 2;
|
||||
case 4:
|
||||
return 3;
|
||||
case 5:
|
||||
return 4;
|
||||
case 16:
|
||||
return 5;
|
||||
case 32:
|
||||
return 6;
|
||||
case 33:
|
||||
return 7;
|
||||
case 254:
|
||||
return 8;
|
||||
case 255:
|
||||
return 9;
|
||||
default:
|
||||
return -1; /* no mapping */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Accelerator for the ASCII subset which is expected to be the most
|
||||
frequently used one.
|
||||
*/
|
||||
static uint16_t cmp_name_page0(uint16_t x)
|
||||
{
|
||||
uint8_t *low;
|
||||
|
||||
low = ((uint8_t *) &x) + 1;
|
||||
|
||||
if (x == 0)
|
||||
return 0xffff;
|
||||
if (*low <= 0x40)
|
||||
;
|
||||
else if (*low <= 0x5a)
|
||||
*low = *low + 0x20;
|
||||
else if (*low < 0xc6)
|
||||
;
|
||||
else if (*low == 0xc6)
|
||||
*low = 0xe6;
|
||||
else if (*low == 0xd0)
|
||||
*low = 0xf0;
|
||||
else if (*low == 0xd8)
|
||||
*low = 0xf8;
|
||||
else if (*low == 0xde)
|
||||
*low = 0xfe;
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
/* Converts a character into the representative of its HFS+ equivalence
|
||||
class.
|
||||
@param x The UTF-16BE character to be converted.
|
||||
@return 0 = ignore character with comparisons
|
||||
else the case-insensitive character.
|
||||
*/
|
||||
uint16_t iso_hfsplus_cichar(uint16_t x)
|
||||
{
|
||||
int page, i;
|
||||
uint16_t ret;
|
||||
uint8_t low, high;
|
||||
|
||||
high = ((uint8_t *) &x)[0];
|
||||
low = ((uint8_t *) &x)[1];
|
||||
|
||||
page = what_page(x);
|
||||
if (page < 0)
|
||||
return x; /* No translation needed */
|
||||
if (page == 0)
|
||||
return cmp_name_page0(x); /* Accelerator for ASCII subset */
|
||||
|
||||
for (i = utf16be_transl_starts[page] * 4; i < utf16be_transl_count * 4;
|
||||
i += 4) {
|
||||
if (utf16be_transl[i] != high)
|
||||
break;
|
||||
if (utf16be_transl[i + 1] == low) {
|
||||
((uint8_t *) &ret)[0] = utf16be_transl[i + 2];
|
||||
((uint8_t *) &ret)[1] = utf16be_transl[i + 3];
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
460
libisofs/hfsplus_classes.c
Normal file
460
libisofs/hfsplus_classes.c
Normal file
@ -0,0 +1,460 @@
|
||||
/*
|
||||
*
|
||||
* Based on Unicode 3.2.0.
|
||||
* See http://www.unicode.org/copyright.html
|
||||
* Quote from there:
|
||||
* "Copyright (c) 1991-2012 Unicode, Inc. All rights reserved.
|
||||
* [...]
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of the Unicode data files and any associated documentation
|
||||
* (the "Data Files") or Unicode software and any associated documentation
|
||||
* (the "Software") to deal in the Data Files or Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Data Files or Software, and to permit
|
||||
* persons to whom the Data Files or Software are furnished to do so, provided
|
||||
* that (a) the above copyright notice(s) and this permission notice appear
|
||||
* with all copies of the Data Files or Software, (b) both the above copyright
|
||||
* notice(s) and this permission notice appear in associated documentation,
|
||||
* and (c) there is clear notice in each modified Data File or in the Software
|
||||
* as well as in the documentation associated with the Data File(s) or
|
||||
* Software that the data or software has been modified."
|
||||
*
|
||||
*
|
||||
* For this particular implementation:
|
||||
*
|
||||
* Copyright (c) 2012 Vladimir Serbinenko
|
||||
* Copyright (c) 2012 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "hfsplus.h"
|
||||
|
||||
|
||||
/* This encodes a matrix of page and character, with 16-bit words as elements.
|
||||
Initially the matrix is filled with zeros.
|
||||
1: The first element is the page number.
|
||||
If it is equal or lower than the previous one, then the matrix is done.
|
||||
2: The next element is the character number
|
||||
If it is equal or lower than the previous one, the page is done. Goto 1.
|
||||
3: The next element is the byte value. Goto 2.
|
||||
*/
|
||||
|
||||
static uint16_t class_page_data[] = {
|
||||
|
||||
/* page 03 */
|
||||
0x03,
|
||||
0x00, 0x230,
|
||||
0x01, 0x230,
|
||||
0x02, 0x230,
|
||||
0x03, 0x230,
|
||||
0x04, 0x230,
|
||||
0x05, 0x230,
|
||||
0x06, 0x230,
|
||||
0x07, 0x230,
|
||||
0x08, 0x230,
|
||||
0x09, 0x230,
|
||||
0x0a, 0x230,
|
||||
0x0b, 0x230,
|
||||
0x0c, 0x230,
|
||||
0x0d, 0x230,
|
||||
0x0e, 0x230,
|
||||
0x0f, 0x230,
|
||||
0x10, 0x230,
|
||||
0x11, 0x230,
|
||||
0x12, 0x230,
|
||||
0x13, 0x230,
|
||||
0x14, 0x230,
|
||||
0x15, 0x232,
|
||||
0x16, 0x220,
|
||||
0x17, 0x220,
|
||||
0x18, 0x220,
|
||||
0x19, 0x220,
|
||||
0x1a, 0x232,
|
||||
0x1b, 0x216,
|
||||
0x1c, 0x220,
|
||||
0x1d, 0x220,
|
||||
0x1e, 0x220,
|
||||
0x1f, 0x220,
|
||||
0x20, 0x220,
|
||||
0x21, 0x202,
|
||||
0x22, 0x202,
|
||||
0x23, 0x220,
|
||||
0x24, 0x220,
|
||||
0x25, 0x220,
|
||||
0x26, 0x220,
|
||||
0x27, 0x202,
|
||||
0x28, 0x202,
|
||||
0x29, 0x220,
|
||||
0x2a, 0x220,
|
||||
0x2b, 0x220,
|
||||
0x2c, 0x220,
|
||||
0x2d, 0x220,
|
||||
0x2e, 0x220,
|
||||
0x2f, 0x220,
|
||||
0x30, 0x220,
|
||||
0x31, 0x220,
|
||||
0x32, 0x220,
|
||||
0x33, 0x220,
|
||||
0x34, 0x1,
|
||||
0x35, 0x1,
|
||||
0x36, 0x1,
|
||||
0x37, 0x1,
|
||||
0x38, 0x1,
|
||||
0x39, 0x220,
|
||||
0x3a, 0x220,
|
||||
0x3b, 0x220,
|
||||
0x3c, 0x220,
|
||||
0x3d, 0x230,
|
||||
0x3e, 0x230,
|
||||
0x3f, 0x230,
|
||||
0x40, 0x230,
|
||||
0x41, 0x230,
|
||||
0x42, 0x230,
|
||||
0x43, 0x230,
|
||||
0x44, 0x230,
|
||||
0x45, 0x240,
|
||||
0x46, 0x230,
|
||||
0x47, 0x220,
|
||||
0x48, 0x220,
|
||||
0x49, 0x220,
|
||||
0x4a, 0x230,
|
||||
0x4b, 0x230,
|
||||
0x4c, 0x230,
|
||||
0x4d, 0x220,
|
||||
0x4e, 0x220,
|
||||
0x60, 0x234,
|
||||
0x61, 0x234,
|
||||
0x62, 0x233,
|
||||
0x63, 0x230,
|
||||
0x64, 0x230,
|
||||
0x65, 0x230,
|
||||
0x66, 0x230,
|
||||
0x67, 0x230,
|
||||
0x68, 0x230,
|
||||
0x69, 0x230,
|
||||
0x6a, 0x230,
|
||||
0x6b, 0x230,
|
||||
0x6c, 0x230,
|
||||
0x6d, 0x230,
|
||||
0x6e, 0x230,
|
||||
0x6f, 0x230,
|
||||
0x00,
|
||||
|
||||
/* page04 */
|
||||
0x04,
|
||||
0x83, 0x230,
|
||||
0x84, 0x230,
|
||||
0x85, 0x230,
|
||||
0x86, 0x230,
|
||||
0x00,
|
||||
|
||||
/* page05 */
|
||||
0x05,
|
||||
0x91, 0x220,
|
||||
0x92, 0x230,
|
||||
0x93, 0x230,
|
||||
0x94, 0x230,
|
||||
0x95, 0x230,
|
||||
0x96, 0x220,
|
||||
0x97, 0x230,
|
||||
0x98, 0x230,
|
||||
0x99, 0x230,
|
||||
0x9a, 0x222,
|
||||
0x9b, 0x220,
|
||||
0x9c, 0x230,
|
||||
0x9d, 0x230,
|
||||
0x9e, 0x230,
|
||||
0x9f, 0x230,
|
||||
0xa0, 0x230,
|
||||
0xa1, 0x230,
|
||||
0xa3, 0x220,
|
||||
0xa4, 0x220,
|
||||
0xa5, 0x220,
|
||||
0xa6, 0x220,
|
||||
0xa7, 0x220,
|
||||
0xa8, 0x230,
|
||||
0xa9, 0x230,
|
||||
0xaa, 0x220,
|
||||
0xab, 0x230,
|
||||
0xac, 0x230,
|
||||
0xad, 0x222,
|
||||
0xae, 0x228,
|
||||
0xaf, 0x230,
|
||||
0xb0, 0x10,
|
||||
0xb1, 0x11,
|
||||
0xb2, 0x12,
|
||||
0xb3, 0x13,
|
||||
0xb4, 0x14,
|
||||
0xb5, 0x15,
|
||||
0xb6, 0x16,
|
||||
0xb7, 0x17,
|
||||
0xb8, 0x18,
|
||||
0xb9, 0x19,
|
||||
0xbb, 0x20,
|
||||
0xbc, 0x21,
|
||||
0xbd, 0x22,
|
||||
0xbf, 0x23,
|
||||
0xc1, 0x24,
|
||||
0xc2, 0x25,
|
||||
0xc4, 0x230,
|
||||
0x00,
|
||||
|
||||
/* page06 */
|
||||
0x06,
|
||||
0x4b, 0x27,
|
||||
0x4c, 0x28,
|
||||
0x4d, 0x29,
|
||||
0x4e, 0x30,
|
||||
0x4f, 0x31,
|
||||
0x50, 0x32,
|
||||
0x51, 0x33,
|
||||
0x52, 0x34,
|
||||
0x53, 0x230,
|
||||
0x54, 0x230,
|
||||
0x55, 0x220,
|
||||
0x70, 0x35,
|
||||
0xd6, 0x230,
|
||||
0xd7, 0x230,
|
||||
0xd8, 0x230,
|
||||
0xd9, 0x230,
|
||||
0xda, 0x230,
|
||||
0xdb, 0x230,
|
||||
0xdc, 0x230,
|
||||
0xdf, 0x230,
|
||||
0xe0, 0x230,
|
||||
0xe1, 0x230,
|
||||
0xe2, 0x230,
|
||||
0xe3, 0x220,
|
||||
0xe4, 0x230,
|
||||
0xe7, 0x230,
|
||||
0xe8, 0x230,
|
||||
0xea, 0x220,
|
||||
0xeb, 0x230,
|
||||
0xec, 0x230,
|
||||
0xed, 0x220,
|
||||
0x00,
|
||||
|
||||
/* page07 */
|
||||
0x07,
|
||||
0x11, 0x36,
|
||||
0x30, 0x230,
|
||||
0x31, 0x220,
|
||||
0x32, 0x230,
|
||||
0x33, 0x230,
|
||||
0x34, 0x220,
|
||||
0x35, 0x230,
|
||||
0x36, 0x230,
|
||||
0x37, 0x220,
|
||||
0x38, 0x220,
|
||||
0x39, 0x220,
|
||||
0x3a, 0x230,
|
||||
0x3b, 0x220,
|
||||
0x3c, 0x220,
|
||||
0x3d, 0x230,
|
||||
0x3e, 0x220,
|
||||
0x3f, 0x230,
|
||||
0x40, 0x230,
|
||||
0x41, 0x230,
|
||||
0x42, 0x220,
|
||||
0x43, 0x230,
|
||||
0x44, 0x220,
|
||||
0x45, 0x230,
|
||||
0x46, 0x220,
|
||||
0x47, 0x230,
|
||||
0x48, 0x220,
|
||||
0x49, 0x230,
|
||||
0x4a, 0x230,
|
||||
0x00,
|
||||
|
||||
/* page09 */
|
||||
0x09,
|
||||
0x3c, 0x7,
|
||||
0x4d, 0x9,
|
||||
0x51, 0x230,
|
||||
0x52, 0x220,
|
||||
0x53, 0x230,
|
||||
0x54, 0x230,
|
||||
0xbc, 0x7,
|
||||
0xcd, 0x9,
|
||||
0x00,
|
||||
|
||||
/* page0a */
|
||||
0x0a,
|
||||
0x3c, 0x7,
|
||||
0x4d, 0x9,
|
||||
0xbc, 0x7,
|
||||
0xcd, 0x9,
|
||||
0x00,
|
||||
|
||||
/* page0b */
|
||||
0x0b,
|
||||
0x3c, 0x7,
|
||||
0x4d, 0x9,
|
||||
0xcd, 0x9,
|
||||
0x00,
|
||||
|
||||
/* page0c */
|
||||
0x0c,
|
||||
0x4d, 0x9,
|
||||
0x55, 0x84,
|
||||
0x56, 0x91,
|
||||
0xcd, 0x9,
|
||||
0x00,
|
||||
|
||||
/* page0d */
|
||||
0x0d,
|
||||
0x4d, 0x9,
|
||||
0xca, 0x9,
|
||||
0x00,
|
||||
|
||||
/* page0e */
|
||||
0x0e,
|
||||
0x38, 0x103,
|
||||
0x39, 0x103,
|
||||
0x3a, 0x9,
|
||||
0x48, 0x107,
|
||||
0x49, 0x107,
|
||||
0x4a, 0x107,
|
||||
0x4b, 0x107,
|
||||
0xb8, 0x118,
|
||||
0xb9, 0x118,
|
||||
0xc8, 0x122,
|
||||
0xc9, 0x122,
|
||||
0xca, 0x122,
|
||||
0xcb, 0x122,
|
||||
0x00,
|
||||
|
||||
/* page0f */
|
||||
0x0f,
|
||||
0x18, 0x220,
|
||||
0x19, 0x220,
|
||||
0x35, 0x220,
|
||||
0x37, 0x220,
|
||||
0x39, 0x216,
|
||||
0x71, 0x129,
|
||||
0x72, 0x130,
|
||||
0x74, 0x132,
|
||||
0x7a, 0x130,
|
||||
0x7b, 0x130,
|
||||
0x7c, 0x130,
|
||||
0x7d, 0x130,
|
||||
0x80, 0x130,
|
||||
0x82, 0x230,
|
||||
0x83, 0x230,
|
||||
0x84, 0x9,
|
||||
0x86, 0x230,
|
||||
0x87, 0x230,
|
||||
0xc6, 0x220,
|
||||
0x00,
|
||||
|
||||
/* page10 */
|
||||
0x10,
|
||||
0x37, 0x7,
|
||||
0x39, 0x9,
|
||||
0x00,
|
||||
|
||||
/* page17 */
|
||||
0x17,
|
||||
0x14, 0x9,
|
||||
0x34, 0x9,
|
||||
0xd2, 0x9,
|
||||
0x00,
|
||||
|
||||
/* page18 */
|
||||
0x18,
|
||||
0xa9, 0x228,
|
||||
0x00,
|
||||
|
||||
/* page20 */
|
||||
0x20,
|
||||
0xd0, 0x230,
|
||||
0xd1, 0x230,
|
||||
0xd2, 0x1,
|
||||
0xd3, 0x1,
|
||||
0xd4, 0x230,
|
||||
0xd5, 0x230,
|
||||
0xd6, 0x230,
|
||||
0xd7, 0x230,
|
||||
0xd8, 0x1,
|
||||
0xd9, 0x1,
|
||||
0xda, 0x1,
|
||||
0xdb, 0x230,
|
||||
0xdc, 0x230,
|
||||
0xe1, 0x230,
|
||||
0xe5, 0x1,
|
||||
0xe6, 0x1,
|
||||
0xe7, 0x230,
|
||||
0xe8, 0x220,
|
||||
0xe9, 0x230,
|
||||
0xea, 0x1,
|
||||
0x00,
|
||||
|
||||
/* page30 */
|
||||
0x30,
|
||||
0x2a, 0x218,
|
||||
0x2b, 0x228,
|
||||
0x2c, 0x232,
|
||||
0x2d, 0x222,
|
||||
0x2e, 0x224,
|
||||
0x2f, 0x224,
|
||||
0x99, 0x8,
|
||||
0x9a, 0x8,
|
||||
0x00,
|
||||
|
||||
/* pagefb */
|
||||
0xfb,
|
||||
0x1e, 0x26,
|
||||
0x00,
|
||||
|
||||
/* pagefe */
|
||||
0xfe,
|
||||
0x20, 0x230,
|
||||
0x21, 0x230,
|
||||
0x22, 0x230,
|
||||
0x23, 0x230,
|
||||
};
|
||||
|
||||
uint16_t *hfsplus_class_pages[256];
|
||||
|
||||
static uint16_t class_pages[19][256];
|
||||
|
||||
void make_hfsplus_class_pages()
|
||||
{
|
||||
int page_idx = -1, char_idx, i;
|
||||
uint16_t *rpt, *page_pt;
|
||||
int page_count = 0;
|
||||
|
||||
memset(class_pages, 0, 19 * 256);
|
||||
for (i = 0; i < 256; i++)
|
||||
hfsplus_class_pages[i] = NULL;
|
||||
|
||||
rpt = (uint16_t *) class_page_data;
|
||||
page_pt = (uint16_t *) class_pages;
|
||||
while (1) {
|
||||
if (*rpt <= page_idx)
|
||||
break;
|
||||
page_count++;
|
||||
page_idx = *(rpt++);
|
||||
char_idx = -1;
|
||||
while (1) {
|
||||
if(*rpt <= char_idx)
|
||||
break;
|
||||
char_idx = *(rpt++);
|
||||
page_pt[char_idx] = *(rpt++);
|
||||
}
|
||||
rpt++;
|
||||
hfsplus_class_pages[page_idx] = class_pages[page_count - 1];
|
||||
page_pt += 256;
|
||||
}
|
||||
}
|
||||
|
1090
libisofs/hfsplus_decompose.c
Normal file
1090
libisofs/hfsplus_decompose.c
Normal file
File diff suppressed because it is too large
Load Diff
505
libisofs/image.c
505
libisofs/image.c
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 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
|
||||
@ -22,6 +22,100 @@
|
||||
#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_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++)
|
||||
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++)
|
||||
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++)
|
||||
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_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.
|
||||
*
|
||||
@ -32,7 +126,7 @@
|
||||
* @param image
|
||||
* Location where the image pointer will be stored.
|
||||
* @return
|
||||
* 1 sucess, < 0 error
|
||||
* 1 success, < 0 error
|
||||
*/
|
||||
int iso_image_new(const char *name, IsoImage **image)
|
||||
{
|
||||
@ -78,13 +172,25 @@ int iso_image_new(const char *name, IsoImage **image)
|
||||
img->volset_id = strdup(name);
|
||||
img->volume_id = strdup(name);
|
||||
}
|
||||
memset(img->application_use, 0, 512);
|
||||
img->system_area_data = NULL;
|
||||
img->system_area_options = 0;
|
||||
img->num_mips_boot_files = 0;
|
||||
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;
|
||||
@ -93,6 +199,11 @@ int iso_image_new(const char *name, IsoImage **image)
|
||||
img->checksum_idx_count = 0;
|
||||
img->checksum_array = NULL;
|
||||
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;
|
||||
|
||||
*image = img;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
@ -112,25 +223,34 @@ void iso_image_ref(IsoImage *image)
|
||||
*/
|
||||
void iso_image_unref(IsoImage *image)
|
||||
{
|
||||
if (--image->refcount == 0) {
|
||||
int nexcl;
|
||||
int nexcl, i;
|
||||
|
||||
if (--image->refcount == 0) {
|
||||
/* we need to free the image */
|
||||
|
||||
if (image->user_data_free != NULL) {
|
||||
/* free attached data */
|
||||
image->user_data_free(image->user_data);
|
||||
}
|
||||
|
||||
for (nexcl = 0; nexcl < image->nexcludes; ++nexcl) {
|
||||
free(image->excludes[nexcl]);
|
||||
}
|
||||
free(image->excludes);
|
||||
|
||||
for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++)
|
||||
if (image->hfsplus_blessed[i] != NULL)
|
||||
iso_node_unref(image->hfsplus_blessed[i]);
|
||||
iso_node_unref((IsoNode*)image->root);
|
||||
iso_node_builder_unref(image->builder);
|
||||
iso_filesystem_unref(image->fs);
|
||||
el_torito_boot_catalog_free(image->bootcat);
|
||||
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);
|
||||
@ -140,9 +260,16 @@ void iso_image_unref(IsoImage *image)
|
||||
free(image->copyright_file_id);
|
||||
free(image->abstract_file_id);
|
||||
free(image->biblio_file_id);
|
||||
free(image->creation_time);
|
||||
free(image->modification_time);
|
||||
free(image->expiration_time);
|
||||
free(image->effective_time);
|
||||
if (image->used_inodes != NULL)
|
||||
free(image->used_inodes);
|
||||
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);
|
||||
free(image);
|
||||
}
|
||||
}
|
||||
@ -328,6 +455,55 @@ const char *iso_image_get_biblio_file_id(const IsoImage *image)
|
||||
return image->biblio_file_id;
|
||||
}
|
||||
|
||||
int iso_image_set_pvd_times(IsoImage *image,
|
||||
char *creation_time, char *modification_time,
|
||||
char *expiration_time, char *effective_time)
|
||||
{
|
||||
if (creation_time == NULL || modification_time == NULL ||
|
||||
expiration_time == NULL || effective_time == NULL)
|
||||
return ISO_NULL_POINTER;
|
||||
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;
|
||||
}
|
||||
|
||||
int iso_image_get_pvd_times(IsoImage *image,
|
||||
char **creation_time, char **modification_time,
|
||||
char **expiration_time, char **effective_time)
|
||||
{
|
||||
if (image->creation_time == NULL || image->modification_time == NULL ||
|
||||
image->expiration_time == NULL || image->effective_time == NULL)
|
||||
return ISO_NULL_POINTER;
|
||||
*creation_time = image->creation_time;
|
||||
*modification_time = image->modification_time;
|
||||
*expiration_time = image->expiration_time;
|
||||
*effective_time = image->effective_time;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
void iso_image_set_app_use(IsoImage *image, const char *app_use_data,
|
||||
int count)
|
||||
{
|
||||
if (count < 0)
|
||||
count= 0;
|
||||
else if(count > 512)
|
||||
count= 512;
|
||||
if (count > 0)
|
||||
memcpy(image->application_use, app_use_data, count);
|
||||
if (count < 512)
|
||||
memset(image->application_use + count, 0, 512 - count);
|
||||
}
|
||||
|
||||
int iso_image_get_msg_id(IsoImage *image)
|
||||
{
|
||||
return image->id;
|
||||
@ -347,21 +523,74 @@ static
|
||||
int dir_update_size(IsoImage *image, IsoDir *dir)
|
||||
{
|
||||
IsoNode *pos;
|
||||
int ret;
|
||||
|
||||
#ifdef Libisofs_update_sizes_abortablE
|
||||
char *path= NULL;
|
||||
IsoStream *base_stream;
|
||||
int cancel_ret, ret;
|
||||
uint32_t lba;
|
||||
#endif
|
||||
|
||||
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) {
|
||||
/* recurse */
|
||||
ret = dir_update_size(image, ISO_DIR(pos));
|
||||
|
||||
#ifdef Libisofs_update_sizes_abortablE
|
||||
if (ret == ISO_CANCELED)
|
||||
return ret; /* Message already issued by dir_update_size */
|
||||
#endif
|
||||
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_update_sizes_abortablE
|
||||
|
||||
/* This would report error and abort according to severity threshold.
|
||||
But it is desirable to let the update_size crawler continue
|
||||
its work after e.g. a file has vanished from hard disk.
|
||||
So normally this macro case should be disabled.
|
||||
*/
|
||||
|
||||
if (ret < 0) {
|
||||
ret = iso_msg_submit(image->id, ret, 0, NULL);
|
||||
if (ret < 0) {
|
||||
return ret; /* cancel due error threshold */
|
||||
cancel_ret = iso_msg_submit(image->id, ret, 0, NULL);
|
||||
path = iso_tree_get_node_path(pos);
|
||||
if (path != NULL) {
|
||||
iso_msg_submit(image->id, ret, 0,
|
||||
"ISO path : %s", path);
|
||||
free(path);
|
||||
}
|
||||
/* Report source path with streams which do not come from
|
||||
the loaded ISO filesystem */
|
||||
if (pos->type == LIBISO_FILE &&
|
||||
iso_node_get_old_image_lba(pos, &lba, 0) == 0) {
|
||||
base_stream = iso_stream_get_input_stream(
|
||||
ISO_FILE(pos)->stream, 1);
|
||||
if (base_stream == NULL)
|
||||
base_stream = ISO_FILE(pos)->stream;
|
||||
path = iso_stream_get_source_path(base_stream, 0);
|
||||
if (path != NULL) {
|
||||
iso_msg_submit(image->id, ret, 0,
|
||||
"Local path: %s", path);
|
||||
free(path);
|
||||
}
|
||||
}
|
||||
if (cancel_ret < 0)
|
||||
return cancel_ret; /* cancel due error threshold */
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if (ret < 0)
|
||||
ret = 1; /* ignore error */
|
||||
|
||||
#endif /* ! Libisofs_update_sizes_abortablE */
|
||||
|
||||
pos = pos->next;
|
||||
}
|
||||
return ISO_SUCCESS;
|
||||
@ -457,7 +686,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
|
||||
@ -467,13 +697,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) {
|
||||
@ -483,10 +713,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;
|
||||
}
|
||||
}
|
||||
@ -655,3 +885,246 @@ int iso_image_give_up_mips_boot(IsoImage *image, int flag)
|
||||
image->num_mips_boot_files = 0;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static void unset_blessing(IsoImage *img, unsigned int idx)
|
||||
{
|
||||
if (img->hfsplus_blessed[idx] != NULL)
|
||||
iso_node_unref(img->hfsplus_blessed[idx]);
|
||||
img->hfsplus_blessed[idx] = NULL;
|
||||
}
|
||||
|
||||
/* API */
|
||||
int iso_image_hfsplus_bless(IsoImage *img, enum IsoHfsplusBlessings blessing,
|
||||
IsoNode *node, int flag)
|
||||
{
|
||||
unsigned int i, ok = 0;
|
||||
|
||||
if (flag & 2) {
|
||||
/* Delete any blessing */
|
||||
for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++) {
|
||||
if (img->hfsplus_blessed[i] == node || node == NULL) {
|
||||
unset_blessing(img, i);
|
||||
ok = 1;
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
if (blessing == ISO_HFSPLUS_BLESS_MAX)
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
if (flag & 1) {
|
||||
/* Delete a particular blessing */
|
||||
if (img->hfsplus_blessed[blessing] == node || node == NULL) {
|
||||
unset_blessing(img, (unsigned int) blessing);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (node == NULL) {
|
||||
unset_blessing(img, (unsigned int) blessing);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* No two hats on one node */
|
||||
for (i = 0; i < ISO_HFSPLUS_BLESS_MAX && node != NULL; i++)
|
||||
if (i != blessing && img->hfsplus_blessed[i] == node)
|
||||
return 0;
|
||||
/* Enforce correct file type */
|
||||
if (blessing == ISO_HFSPLUS_BLESS_INTEL_BOOTFILE) {
|
||||
if (node->type != LIBISO_FILE)
|
||||
return 0;
|
||||
} else {
|
||||
if (node->type != LIBISO_DIR)
|
||||
return 0;
|
||||
}
|
||||
|
||||
unset_blessing(img, (unsigned int) blessing);
|
||||
img->hfsplus_blessed[blessing] = node;
|
||||
if (node != NULL)
|
||||
iso_node_ref(node);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_image_hfsplus_get_blessed(IsoImage *img, IsoNode ***blessed_nodes,
|
||||
int *bless_max, int flag)
|
||||
{
|
||||
*blessed_nodes = img->hfsplus_blessed;
|
||||
*bless_max = ISO_HFSPLUS_BLESS_MAX;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_image_set_sparc_core(IsoImage *img, IsoFile *sparc_core, int flag)
|
||||
{
|
||||
if (img->sparc_core_node != NULL)
|
||||
iso_node_unref((IsoNode *) img->sparc_core_node);
|
||||
img->sparc_core_node = sparc_core;
|
||||
if (sparc_core != NULL)
|
||||
iso_node_ref((IsoNode *) sparc_core);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_image_get_sparc_core(IsoImage *img, IsoFile **sparc_core, int flag)
|
||||
{
|
||||
*sparc_core = img->sparc_core_node;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* @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;
|
||||
}
|
||||
|
||||
|
222
libisofs/image.h
222
libisofs/image.h
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 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
|
||||
@ -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.
|
||||
* (Useful, for example, in Multiple-Document-Interface GUI apps.
|
||||
* [The stuff we have in init belongs really to image!]
|
||||
*/
|
||||
|
||||
@ -49,6 +52,11 @@ struct Iso_Image
|
||||
char *copyright_file_id;
|
||||
char *abstract_file_id;
|
||||
char *biblio_file_id;
|
||||
char *creation_time;
|
||||
char *modification_time;
|
||||
char *expiration_time;
|
||||
char *effective_time;
|
||||
char application_use[512];
|
||||
|
||||
/* el-torito boot catalog */
|
||||
struct el_torito_boot_catalog *bootcat;
|
||||
@ -56,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;
|
||||
|
||||
/*
|
||||
@ -65,6 +75,23 @@ struct Iso_Image
|
||||
int num_mips_boot_files;
|
||||
char *mips_boot_file_paths[15]; /* ISO 9660 Rock Ridge Paths */
|
||||
|
||||
/* A data file of which the position and size shall be written after
|
||||
a SUN Disk Label.
|
||||
*/
|
||||
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;
|
||||
@ -74,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.
|
||||
*/
|
||||
@ -128,6 +160,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
|
||||
@ -149,18 +195,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
|
||||
@ -180,9 +228,30 @@ struct Iso_Image
|
||||
*/
|
||||
int generator_is_running;
|
||||
|
||||
/* Pointers to directories or files which shall be get a HFS+ blessing.
|
||||
* libisofs/hfsplus.c et.al. will compare these pointers
|
||||
* with the ->node pointer of Ecma119Nodes.
|
||||
* See libisofs.h
|
||||
*/
|
||||
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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/* 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
|
||||
@ -201,10 +270,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
|
||||
@ -227,4 +296,141 @@ int iso_image_set_checksums(IsoImage *image, char *checksum_array,
|
||||
uint32_t idx_count, int flag);
|
||||
|
||||
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
|
||||
|
||||
#endif /*LIBISO_IMAGE_H_*/
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* 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
|
||||
@ -17,6 +18,8 @@
|
||||
#include "image.h"
|
||||
#include "filesrc.h"
|
||||
#include "eltorito.h"
|
||||
#include "util.h"
|
||||
#include "ecma119.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@ -73,11 +76,12 @@ void iso1999_node_free(Iso1999Node *node)
|
||||
return;
|
||||
}
|
||||
if (node->type == ISO1999_DIR) {
|
||||
int i;
|
||||
size_t i;
|
||||
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);
|
||||
@ -108,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) {
|
||||
@ -122,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 "
|
||||
@ -191,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, "
|
||||
@ -290,6 +297,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++) {
|
||||
@ -305,29 +314,35 @@ 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);
|
||||
|
||||
/* 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);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
goto ex;
|
||||
}
|
||||
for (i = 0; i < nchildren; ++i) {
|
||||
char *name = children[i]->name;
|
||||
ret = iso_htable_add(table, name, name);
|
||||
if (ret < 0) {
|
||||
goto mangle_cleanup;
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < nchildren; ++i) {
|
||||
char *name, *ext;
|
||||
char full_name[208];
|
||||
int max; /* computed max len for name, without extension */
|
||||
int j = i;
|
||||
int digits = 1; /* characters to change per name */
|
||||
@ -384,7 +399,7 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
|
||||
* This can't happen with current limit of digits.
|
||||
*/
|
||||
ret = ISO_ERROR;
|
||||
goto mangle_cleanup;
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
/* ok, reduce name by digits */
|
||||
@ -398,7 +413,7 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
|
||||
}
|
||||
max = 207 - digits;
|
||||
name = full_name;
|
||||
if (max < strlen(name)) {
|
||||
if ((size_t) max < strlen(name)) {
|
||||
name[max] = '\0';
|
||||
}
|
||||
/* let ext be an empty string */
|
||||
@ -408,7 +423,6 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
|
||||
ok = 1;
|
||||
/* change name of each file */
|
||||
for (k = i; k <= j; ++k) {
|
||||
char tmp[208];
|
||||
char fmt[16];
|
||||
if (dot != NULL) {
|
||||
sprintf(fmt, "%%s%%0%dd.%%s", digits);
|
||||
@ -431,7 +445,7 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
|
||||
char *new = strdup(tmp);
|
||||
if (new == NULL) {
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
goto mangle_cleanup;
|
||||
goto ex;
|
||||
}
|
||||
iso_msg_debug(img->image->id, "\"%s\" renamed to \"%s\"",
|
||||
children[k]->name, new);
|
||||
@ -459,7 +473,7 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
|
||||
}
|
||||
if (digits == 8) {
|
||||
ret = ISO_MANGLE_TOO_MUCH_FILES;
|
||||
goto mangle_cleanup;
|
||||
goto ex;
|
||||
}
|
||||
i = j;
|
||||
}
|
||||
@ -473,8 +487,10 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
|
||||
|
||||
ret = ISO_SUCCESS;
|
||||
|
||||
mangle_cleanup : ;
|
||||
ex:;
|
||||
iso_htable_destroy(table, NULL);
|
||||
LIBISO_FREE_MEM(tmp);
|
||||
LIBISO_FREE_MEM(full_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -683,8 +699,9 @@ void write_one_dir_record(Ecma119Image *t, Iso1999Node *node, int file_id,
|
||||
: (uint8_t*)node->name;
|
||||
|
||||
struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf;
|
||||
IsoNode *iso;
|
||||
|
||||
len_dr = 33 + len_fi + (len_fi % 2 ? 0 : 1);
|
||||
len_dr = 33 + len_fi + ((len_fi % 2) ? 0 : 1);
|
||||
|
||||
memcpy(rec->file_id, name, len_fi);
|
||||
|
||||
@ -714,7 +731,15 @@ void write_one_dir_record(Ecma119Image *t, Iso1999Node *node, int file_id,
|
||||
rec->len_dr[0] = len_dr;
|
||||
iso_bb(rec->block, block, 4);
|
||||
iso_bb(rec->length, len, 4);
|
||||
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->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);
|
||||
rec->len_fi[0] = len_fi;
|
||||
@ -787,10 +812,8 @@ int iso1999_writer_write_vol_desc(IsoImageWriter *writer)
|
||||
strncpy_pad((char*)vol.abstract_file_id, abstract_file_id, 37);
|
||||
strncpy_pad((char*)vol.bibliographic_file_id, biblio_file_id, 37);
|
||||
|
||||
iso_datetime_17(vol.vol_creation_time, t->now, t->always_gmt);
|
||||
iso_datetime_17(vol.vol_modification_time, t->now, t->always_gmt);
|
||||
iso_datetime_17(vol.vol_effective_time, t->now, t->always_gmt);
|
||||
vol.file_structure_version[0] = 1;
|
||||
ecma119_set_voldescr_times(writer, (struct ecma119_pri_vol_desc *) &vol);
|
||||
vol.file_structure_version[0] = 2;
|
||||
|
||||
free(vol_id);
|
||||
free(volset_id);
|
||||
@ -810,15 +833,15 @@ static
|
||||
int write_one_dir(Ecma119Image *t, Iso1999Node *dir)
|
||||
{
|
||||
int ret;
|
||||
uint8_t buffer[BLOCK_SIZE];
|
||||
uint8_t *buffer = NULL;
|
||||
size_t i;
|
||||
size_t fi_len, len;
|
||||
|
||||
/* buf will point to current write position on buffer */
|
||||
uint8_t *buf = buffer;
|
||||
uint8_t *buf;
|
||||
|
||||
/* initialize buffer with 0s */
|
||||
memset(buffer, 0, BLOCK_SIZE);
|
||||
LIBISO_ALLOC_MEM(buffer, uint8_t, BLOCK_SIZE);
|
||||
buf = buffer;
|
||||
|
||||
/* write the "." and ".." entries first */
|
||||
write_one_dir_record(t, dir, 0, buf, 1, 0);
|
||||
@ -832,7 +855,7 @@ int write_one_dir(Ecma119Image *t, Iso1999Node *dir)
|
||||
|
||||
/* compute len of directory entry */
|
||||
fi_len = strlen(child->name);
|
||||
len = fi_len + 33 + (fi_len % 2 ? 0 : 1);
|
||||
len = fi_len + 33 + ((fi_len % 2) ? 0 : 1);
|
||||
|
||||
nsections = (child->type == ISO1999_FILE) ? child->info.file->nsections : 1;
|
||||
for (section = 0; section < nsections; ++section) {
|
||||
@ -840,7 +863,7 @@ int write_one_dir(Ecma119Image *t, Iso1999Node *dir)
|
||||
/* dir doesn't fit in current block */
|
||||
ret = iso_write(t, buffer, BLOCK_SIZE);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
goto ex;
|
||||
}
|
||||
memset(buffer, 0, BLOCK_SIZE);
|
||||
buf = buffer;
|
||||
@ -853,6 +876,8 @@ int write_one_dir(Ecma119Image *t, Iso1999Node *dir)
|
||||
|
||||
/* write the last block */
|
||||
ret = iso_write(t, buffer, BLOCK_SIZE);
|
||||
ex:;
|
||||
LIBISO_FREE_MEM(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -885,13 +910,17 @@ static
|
||||
int write_path_table(Ecma119Image *t, Iso1999Node **pathlist, int l_type)
|
||||
{
|
||||
size_t i, len;
|
||||
uint8_t buf[256]; /* 256 is just a convenient size larger enought */
|
||||
uint8_t *buf = NULL;
|
||||
struct ecma119_path_table_record *rec;
|
||||
void (*write_int)(uint8_t*, uint32_t, int);
|
||||
Iso1999Node *dir;
|
||||
uint32_t path_table_size;
|
||||
int parent = 0;
|
||||
int ret= ISO_SUCCESS;
|
||||
uint8_t *zeros = NULL;
|
||||
|
||||
/* 256 is just a convenient size large enought */
|
||||
LIBISO_ALLOC_MEM(buf, uint8_t, 256);
|
||||
|
||||
path_table_size = 0;
|
||||
write_int = l_type ? iso_lsb : iso_msb;
|
||||
@ -918,7 +947,7 @@ int write_path_table(Ecma119Image *t, Iso1999Node **pathlist, int l_type)
|
||||
ret = iso_write(t, buf, len);
|
||||
if (ret < 0) {
|
||||
/* error */
|
||||
return ret;
|
||||
goto ex;
|
||||
}
|
||||
path_table_size += len;
|
||||
}
|
||||
@ -926,11 +955,14 @@ int write_path_table(Ecma119Image *t, Iso1999Node **pathlist, int l_type)
|
||||
/* we need to fill the last block with zeros */
|
||||
path_table_size %= BLOCK_SIZE;
|
||||
if (path_table_size) {
|
||||
uint8_t zeros[BLOCK_SIZE];
|
||||
LIBISO_ALLOC_MEM(zeros, uint8_t, BLOCK_SIZE);
|
||||
len = BLOCK_SIZE - path_table_size;
|
||||
memset(zeros, 0, len);
|
||||
ret = iso_write(t, zeros, len);
|
||||
}
|
||||
ex:;
|
||||
LIBISO_FREE_MEM(zeros);
|
||||
LIBISO_FREE_MEM(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2007 Mario Danic
|
||||
* 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
|
||||
@ -19,38 +20,77 @@
|
||||
#include "filesrc.h"
|
||||
#include "eltorito.h"
|
||||
#include "libisofs.h"
|
||||
#include "util.h"
|
||||
#include "ecma119.h"
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
/* TODO #00022 : support relaxed constraints in joliet filenames */
|
||||
if (iso->type == LIBISO_DIR) {
|
||||
jname = iso_j_dir_id(ucs_name);
|
||||
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 {
|
||||
jname = iso_j_file_id(ucs_name, !!(t->no_force_dots & 2));
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free(ucs_name);
|
||||
if (jname != NULL) {
|
||||
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,
|
||||
(opts->joliet_long_names << 1) | !!(opts->no_force_dots & 2));
|
||||
}
|
||||
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 {
|
||||
@ -62,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)
|
||||
{
|
||||
@ -69,11 +122,12 @@ void joliet_node_free(JolietNode *node)
|
||||
return;
|
||||
}
|
||||
if (node->type == JOLIET_DIR) {
|
||||
int i;
|
||||
size_t i;
|
||||
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);
|
||||
@ -104,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) {
|
||||
@ -118,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,
|
||||
@ -186,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,
|
||||
@ -247,7 +305,7 @@ int create_tree(Ecma119Image *t, IsoNode *iso, JolietNode **tree, int pathlen)
|
||||
{
|
||||
char *ipath = iso_tree_get_node_path(iso);
|
||||
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 "
|
||||
"Cannot add %s to Joliet tree. %s can only be added to a "
|
||||
"Rock Ridge tree.", ipath, (iso->type == LIBISO_SYMLINK ?
|
||||
"Symlinks" : "Special files"));
|
||||
free(ipath);
|
||||
@ -279,6 +337,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++) {
|
||||
@ -303,8 +363,15 @@ int joliet_create_mangled_name(uint16_t *dest, uint16_t *src, int digits,
|
||||
int ret, pos;
|
||||
uint16_t *ucsnumber;
|
||||
char fmt[16];
|
||||
char nstr[72]; /* The only caller of this function allocates dest with 66
|
||||
elements and limits digits to < 8 */
|
||||
char nstr[72];
|
||||
/* was: The only caller of this function allocates dest
|
||||
with 66 elements and limits digits to < 8
|
||||
But this does not match the usage of nstr which has to take
|
||||
the decimal representation of an int.
|
||||
*/
|
||||
|
||||
if (digits >= 8)
|
||||
return ISO_ASSERT_FAILURE;
|
||||
|
||||
sprintf(fmt, "%%0%dd", digits);
|
||||
sprintf(nstr, fmt, number);
|
||||
@ -324,11 +391,12 @@ int joliet_create_mangled_name(uint16_t *dest, uint16_t *src, int digits,
|
||||
|
||||
if (ext[0] != (uint16_t)0) {
|
||||
size_t extlen = ucslen(ext);
|
||||
dest[pos++] = (uint16_t)0x2E00; /* '.' in big endian UCS */
|
||||
iso_msb((uint8_t *) (dest + pos), 0x002E, 2); /* '.' in UCS */
|
||||
pos++;
|
||||
ucsncpy(dest + pos, ext, extlen);
|
||||
pos += extlen;
|
||||
}
|
||||
dest[pos] = (uint16_t)0;
|
||||
iso_msb((uint8_t *) (dest + pos), 0, 2);
|
||||
free(ucsnumber);
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
@ -337,19 +405,30 @@ static
|
||||
int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
||||
{
|
||||
int ret;
|
||||
int i, nchildren;
|
||||
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);
|
||||
|
||||
if (t->opts->joliet_long_names)
|
||||
maxchar = 103;
|
||||
|
||||
/* a hash table will temporary hold the names, for fast searching */
|
||||
ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash,
|
||||
(compare_function_t)ucscmp, &table);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
goto ex;
|
||||
}
|
||||
for (i = 0; i < nchildren; ++i) {
|
||||
uint16_t *name = children[i]->name;
|
||||
@ -361,7 +440,6 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
||||
|
||||
for (i = 0; i < nchildren; ++i) {
|
||||
uint16_t *name, *ext;
|
||||
uint16_t full_name[66];
|
||||
int max; /* computed max len for name, without extension */
|
||||
int j = i;
|
||||
int digits = 1; /* characters to change per name */
|
||||
@ -380,7 +458,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
||||
* A max of 7 characters is good enought, it allows handling up to
|
||||
* 9,999,999 files with same name.
|
||||
*/
|
||||
/* Important: joliet_create_mangled_name() relies on digits < 72 */
|
||||
/* Important: joliet_create_mangled_name() relies on digits < 8 */
|
||||
|
||||
while (digits < 8) {
|
||||
int ok, k;
|
||||
@ -403,7 +481,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
||||
ext = dot + 1;
|
||||
|
||||
extlen = ucslen(ext);
|
||||
max = 65 - extlen - 1 - digits;
|
||||
max = maxchar + 1 - extlen - 1 - digits;
|
||||
if (max <= 0) {
|
||||
/* this can happen if extension is too long */
|
||||
if (extlen + max > 3) {
|
||||
@ -413,7 +491,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
||||
*/
|
||||
extlen = extlen + max - 1;
|
||||
ext[extlen] = 0;
|
||||
max = 66 - extlen - 1 - digits;
|
||||
max = maxchar + 2 - extlen - 1 - digits;
|
||||
} else {
|
||||
/*
|
||||
* error, we don't support extensions < 3
|
||||
@ -430,13 +508,13 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
||||
} else {
|
||||
/* Directory, or file without extension */
|
||||
if (children[i]->type == JOLIET_DIR) {
|
||||
max = 65 - digits;
|
||||
max = maxchar + 1 - digits;
|
||||
dot = NULL; /* dots have no meaning in dirs */
|
||||
} else {
|
||||
max = 65 - digits;
|
||||
max = maxchar + 1 - digits;
|
||||
}
|
||||
name = full_name;
|
||||
if (max < ucslen(name)) {
|
||||
if ((size_t) max < ucslen(name)) {
|
||||
name[max] = 0;
|
||||
}
|
||||
/* let ext be an empty string */
|
||||
@ -446,7 +524,6 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
||||
ok = 1;
|
||||
/* change name of each file */
|
||||
for (k = i; k <= j; ++k) {
|
||||
uint16_t tmp[66];
|
||||
while (1) {
|
||||
ret = joliet_create_mangled_name(tmp, name, digits,
|
||||
change, ext);
|
||||
@ -508,7 +585,10 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
||||
ret = ISO_SUCCESS;
|
||||
|
||||
mangle_cleanup : ;
|
||||
ex:;
|
||||
iso_htable_destroy(table, NULL);
|
||||
LIBISO_FREE_MEM(tmp);
|
||||
LIBISO_FREE_MEM(full_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -580,7 +660,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;
|
||||
}
|
||||
@ -699,7 +779,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;
|
||||
@ -742,12 +822,13 @@ void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id,
|
||||
: (uint8_t*)node->name;
|
||||
|
||||
struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf;
|
||||
IsoNode *iso;
|
||||
|
||||
len_dr = 33 + len_fi + (len_fi % 2 ? 0 : 1);
|
||||
len_dr = 33 + len_fi + ((len_fi % 2) ? 0 : 1);
|
||||
|
||||
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++] = ';';
|
||||
@ -781,7 +862,15 @@ void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id,
|
||||
rec->len_dr[0] = len_dr;
|
||||
iso_bb(rec->block, block - t->eff_partition_offset, 4);
|
||||
iso_bb(rec->length, len, 4);
|
||||
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->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);
|
||||
rec->len_fi[0] = len_fi;
|
||||
@ -801,18 +890,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)
|
||||
@ -886,9 +979,7 @@ int joliet_writer_write_vol_desc(IsoImageWriter *writer)
|
||||
ucsncpy_pad((uint16_t*)vol.abstract_file_id, abstract_file_id, 37);
|
||||
ucsncpy_pad((uint16_t*)vol.bibliographic_file_id, biblio_file_id, 37);
|
||||
|
||||
iso_datetime_17(vol.vol_creation_time, t->now, t->always_gmt);
|
||||
iso_datetime_17(vol.vol_modification_time, t->now, t->always_gmt);
|
||||
iso_datetime_17(vol.vol_effective_time, t->now, t->always_gmt);
|
||||
ecma119_set_voldescr_times(writer, (struct ecma119_pri_vol_desc *) &vol);
|
||||
vol.file_structure_version[0] = 1;
|
||||
|
||||
free(vol_id);
|
||||
@ -909,15 +1000,16 @@ static
|
||||
int write_one_dir(Ecma119Image *t, JolietNode *dir)
|
||||
{
|
||||
int ret;
|
||||
uint8_t buffer[BLOCK_SIZE];
|
||||
uint8_t *buffer = NULL;
|
||||
size_t i;
|
||||
size_t fi_len, len;
|
||||
|
||||
/* buf will point to current write position on buffer */
|
||||
uint8_t *buf = buffer;
|
||||
uint8_t *buf;
|
||||
|
||||
/* initialize buffer with 0s */
|
||||
memset(buffer, 0, BLOCK_SIZE);
|
||||
LIBISO_ALLOC_MEM(buffer, uint8_t, BLOCK_SIZE);
|
||||
buf = buffer;
|
||||
|
||||
/* write the "." and ".." entries first */
|
||||
write_one_dir_record(t, dir, 0, buf, 1, 0);
|
||||
@ -932,7 +1024,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;
|
||||
}
|
||||
|
||||
@ -944,7 +1037,7 @@ int write_one_dir(Ecma119Image *t, JolietNode *dir)
|
||||
/* dir doesn't fit in current block */
|
||||
ret = iso_write(t, buffer, BLOCK_SIZE);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
goto ex;
|
||||
}
|
||||
memset(buffer, 0, BLOCK_SIZE);
|
||||
buf = buffer;
|
||||
@ -957,6 +1050,8 @@ int write_one_dir(Ecma119Image *t, JolietNode *dir)
|
||||
|
||||
/* write the last block */
|
||||
ret = iso_write(t, buffer, BLOCK_SIZE);
|
||||
ex:;
|
||||
LIBISO_FREE_MEM(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -989,14 +1084,18 @@ static
|
||||
int write_path_table(Ecma119Image *t, JolietNode **pathlist, int l_type)
|
||||
{
|
||||
size_t i, len;
|
||||
uint8_t buf[256]; /* 256 is just a convenient size larger enought */
|
||||
uint8_t *buf = NULL;
|
||||
struct ecma119_path_table_record *rec;
|
||||
void (*write_int)(uint8_t*, uint32_t, int);
|
||||
JolietNode *dir;
|
||||
uint32_t path_table_size;
|
||||
int parent = 0;
|
||||
int ret= ISO_SUCCESS;
|
||||
uint8_t *zeros = NULL;
|
||||
|
||||
/* 256 is just a convenient size large enought */
|
||||
LIBISO_ALLOC_MEM(buf, uint8_t, 256);
|
||||
LIBISO_ALLOC_MEM(zeros, uint8_t, BLOCK_SIZE);
|
||||
path_table_size = 0;
|
||||
write_int = l_type ? iso_lsb : iso_msb;
|
||||
|
||||
@ -1023,7 +1122,7 @@ int write_path_table(Ecma119Image *t, JolietNode **pathlist, int l_type)
|
||||
ret = iso_write(t, buf, len);
|
||||
if (ret < 0) {
|
||||
/* error */
|
||||
return ret;
|
||||
goto ex;
|
||||
}
|
||||
path_table_size += len;
|
||||
}
|
||||
@ -1031,11 +1130,13 @@ int write_path_table(Ecma119Image *t, JolietNode **pathlist, int l_type)
|
||||
/* we need to fill the last block with zeros */
|
||||
path_table_size %= BLOCK_SIZE;
|
||||
if (path_table_size) {
|
||||
uint8_t zeros[BLOCK_SIZE];
|
||||
len = BLOCK_SIZE - path_table_size;
|
||||
memset(zeros, 0, len);
|
||||
ret = iso_write(t, zeros, len);
|
||||
}
|
||||
ex:;
|
||||
LIBISO_FREE_MEM(zeros);
|
||||
LIBISO_FREE_MEM(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1126,8 +1227,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)
|
||||
@ -1175,9 +1276,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;
|
||||
|
@ -18,6 +18,10 @@
|
||||
#include "libisofs.h"
|
||||
#include "ecma119.h"
|
||||
|
||||
/* was formerly 66 = 64 + 2. Now 105 = 103 + 2.
|
||||
*/
|
||||
#define LIBISO_JOLIET_NAME_MAX 105
|
||||
|
||||
enum joliet_node_type {
|
||||
JOLIET_FILE,
|
||||
JOLIET_DIR
|
||||
@ -59,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();
|
||||
@ -288,7 +287,7 @@ int libiso_msgs__sev_to_text(int severity, char **severity_name,
|
||||
int flag)
|
||||
{
|
||||
if(flag&1) {
|
||||
*severity_name= "NEVER\nABORT\nFATAL\nFAILURE\nMISHAP\nSORRY\nWARNING\nHINT\nNOTE\nUPDATE\nDEBUG\nERRFILE\nALL";
|
||||
*severity_name= "ALL ERRFILE DEBUG UPDATE NOTE HINT WARNING SORRY MISHAP FAILURE FATAL ABORT NEVER";
|
||||
return(1);
|
||||
}
|
||||
*severity_name= "";
|
||||
|
@ -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
|
||||
*/
|
||||
|
||||
@ -221,7 +221,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 +266,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)
|
||||
@ -316,7 +317,7 @@ int libiso_msgs_submit(struct libiso_msgs *m, int origin, int error_code,
|
||||
|
||||
/** Convert a registered severity number into a severity name
|
||||
@param flag Bitfield for control purposes:
|
||||
bit0= list all severity names in a newline separated string
|
||||
bit0= list all severity names in a blank separated string
|
||||
@return >0 success, <=0 failure
|
||||
*/
|
||||
int libiso_msgs__sev_to_text(int severity, char **severity_name,
|
||||
@ -510,7 +511,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
|
||||
|
3008
libisofs/libisofs.h
3008
libisofs/libisofs.h
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,6 @@
|
||||
LIBISOFS6 {
|
||||
global:
|
||||
aaip_xinfo_cloner;
|
||||
aaip_xinfo_func;
|
||||
el_torito_get_bootable;
|
||||
el_torito_get_boot_media_type;
|
||||
@ -18,6 +19,8 @@ el_torito_set_load_seg;
|
||||
el_torito_set_load_size;
|
||||
el_torito_set_no_bootable;
|
||||
el_torito_set_selection_crit;
|
||||
iso_conv_name_chars;
|
||||
iso_crc32_gpt;
|
||||
iso_data_source_new_from_file;
|
||||
iso_data_source_ref;
|
||||
iso_data_source_unref;
|
||||
@ -64,11 +67,19 @@ iso_file_source_unref;
|
||||
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;
|
||||
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_filesystem_new;
|
||||
@ -84,27 +95,42 @@ 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;
|
||||
iso_image_get_biblio_file_id;
|
||||
iso_image_get_bootcat;
|
||||
iso_image_get_boot_image;
|
||||
iso_image_get_copyright_file_id;
|
||||
iso_image_get_data_preparer_id;
|
||||
iso_image_dir_get_node;
|
||||
iso_image_get_hppa_palo;
|
||||
iso_image_get_mips_boot_files;
|
||||
iso_image_get_msg_id;
|
||||
iso_image_get_publisher_id;
|
||||
iso_image_get_pvd_times;
|
||||
iso_image_get_root;
|
||||
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;
|
||||
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;
|
||||
iso_image_set_boot_catalog_hidden;
|
||||
@ -112,17 +138,26 @@ 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_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;
|
||||
iso_local_get_acl_text;
|
||||
iso_local_get_attrs;
|
||||
iso_local_get_perms_wo_acl;
|
||||
@ -156,6 +191,7 @@ iso_node_get_hidden;
|
||||
iso_node_get_mode;
|
||||
iso_node_get_mtime;
|
||||
iso_node_get_name;
|
||||
iso_node_get_next_xinfo;
|
||||
iso_node_get_old_image_lba;
|
||||
iso_node_get_parent;
|
||||
iso_node_get_permissions;
|
||||
@ -166,6 +202,8 @@ iso_node_get_xinfo;
|
||||
iso_node_lookup_attr;
|
||||
iso_node_ref;
|
||||
iso_node_remove;
|
||||
iso_node_remove_all_xinfo;
|
||||
iso_node_remove_tree;
|
||||
iso_node_remove_xinfo;
|
||||
iso_node_set_acl_text;
|
||||
iso_node_set_atime;
|
||||
@ -180,6 +218,8 @@ iso_node_set_sort_weight;
|
||||
iso_node_set_uid;
|
||||
iso_node_take;
|
||||
iso_node_unref;
|
||||
iso_node_xinfo_get_cloner;
|
||||
iso_node_xinfo_make_clonable;
|
||||
iso_node_zf_by_magic;
|
||||
iso_obtain_msgs;
|
||||
iso_read_image_features_destroy;
|
||||
@ -190,11 +230,13 @@ iso_read_image_features_has_joliet;
|
||||
iso_read_image_features_has_rockridge;
|
||||
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_new_inos;
|
||||
iso_read_opts_set_no_aaip;
|
||||
@ -210,6 +252,7 @@ iso_set_local_charset;
|
||||
iso_set_msgs_severities;
|
||||
iso_sev_to_text;
|
||||
iso_special_get_dev;
|
||||
iso_stream_clone;
|
||||
iso_stream_close;
|
||||
iso_stream_cmp_ino;
|
||||
iso_stream_get_external_filter;
|
||||
@ -235,6 +278,7 @@ iso_tree_add_new_node;
|
||||
iso_tree_add_new_special;
|
||||
iso_tree_add_new_symlink;
|
||||
iso_tree_add_node;
|
||||
iso_tree_clone;
|
||||
iso_tree_get_follow_symlinks;
|
||||
iso_tree_get_ignore_hidden;
|
||||
iso_tree_get_ignore_special;
|
||||
@ -242,11 +286,13 @@ iso_tree_get_node_path;
|
||||
iso_tree_get_replace_mode;
|
||||
iso_tree_path_to_node;
|
||||
iso_tree_remove_exclude;
|
||||
iso_tree_resolve_symlink;
|
||||
iso_tree_set_follow_symlinks;
|
||||
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;
|
||||
@ -255,6 +301,7 @@ iso_write_opts_get_data_start;
|
||||
iso_write_opts_new;
|
||||
iso_write_opts_set_aaip;
|
||||
iso_write_opts_set_aaip_susp_1_10;
|
||||
iso_write_opts_set_allow_7bit_ascii;
|
||||
iso_write_opts_set_allow_deep_paths;
|
||||
iso_write_opts_set_allow_dir_id_ext;
|
||||
iso_write_opts_set_allow_full_ascii;
|
||||
@ -262,6 +309,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;
|
||||
@ -269,26 +318,38 @@ iso_write_opts_set_default_timestamp;
|
||||
iso_write_opts_set_default_uid;
|
||||
iso_write_opts_set_dir_rec_mtime;
|
||||
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_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_ms_block;
|
||||
iso_write_opts_set_no_force_dots;
|
||||
iso_write_opts_set_old_empty;
|
||||
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_partition_img;
|
||||
iso_write_opts_set_prep_img;
|
||||
iso_write_opts_set_pvd_times;
|
||||
iso_write_opts_set_record_md5;
|
||||
iso_write_opts_set_relaxed_vol_atts;
|
||||
iso_write_opts_set_replace_mode;
|
||||
iso_write_opts_set_replace_timestamps;
|
||||
iso_write_opts_set_rockridge;
|
||||
iso_write_opts_set_rr_reloc;
|
||||
iso_write_opts_set_rrip_1_10_px_ino;
|
||||
iso_write_opts_set_rrip_version_1_10;
|
||||
iso_write_opts_set_scdbackup_tag;
|
||||
@ -300,5 +361,6 @@ iso_write_opts_set_will_cancel;
|
||||
iso_zisofs_get_params;
|
||||
iso_zisofs_get_refcounts;
|
||||
iso_zisofs_set_params;
|
||||
serial_id;
|
||||
local: *;
|
||||
};
|
||||
|
@ -1,10 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2008 - 2015 Thomas Schmitt
|
||||
* with special credits to H. Peter Anvin for isohybrid
|
||||
* and 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"
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@ -15,6 +33,13 @@
|
||||
/* for gettimeofday() */
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "filesrc.h"
|
||||
#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
|
||||
under GPL which is Copyright 2002-2008 H. Peter Anvin.
|
||||
@ -37,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-2010 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.
|
||||
@ -127,13 +152,12 @@ int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag)
|
||||
|
||||
static int h = 64, s = 32;
|
||||
|
||||
int i, warn_size = 0, id;
|
||||
int i, id;
|
||||
char *wpt;
|
||||
off_t imgsize, cylsize, frac, padding, c, cc;
|
||||
|
||||
/* 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 */
|
||||
@ -156,7 +180,6 @@ int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag)
|
||||
*img_blocks = imgsize / (off_t) 2048;
|
||||
c = imgsize / cylsize;
|
||||
if (c > 1024) {
|
||||
warn_size = 1;
|
||||
cc = 1024;
|
||||
} else
|
||||
cc = c;
|
||||
@ -189,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));
|
||||
|
||||
/*
|
||||
@ -346,6 +369,12 @@ Main:
|
||||
*/
|
||||
|
||||
|
||||
/* The new stuff about GPT and APM which was learned from Matthew Garret
|
||||
and isohybrid.c is described in doc/boot_sectord.txt chapter
|
||||
"SYSLINUX isohybrid for MBR, UEFI and x86-Mac"
|
||||
*/
|
||||
|
||||
|
||||
static
|
||||
int lba512chs_to_buf(char **wpt, off_t lba, int head_count, int sector_count)
|
||||
{
|
||||
@ -370,30 +399,281 @@ 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] = {
|
||||
0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44,
|
||||
0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7
|
||||
};
|
||||
static uint8_t hfs_uuid[16] = {
|
||||
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;
|
||||
|
||||
*gpt_count = 0;
|
||||
*apm_count = 0;
|
||||
|
||||
if (t->catalog != NULL)
|
||||
num_img = t->catalog->num_bootimages;
|
||||
else
|
||||
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) &&
|
||||
!(t->boot_appended_idx[i] >= 0 && t->opts->appended_as_gpt)) {
|
||||
if (*gpt_count < 128)
|
||||
gpt_idx[*gpt_count] = i;
|
||||
(*gpt_count)++;
|
||||
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);
|
||||
iso_ascii_utf_16le(gpt_name);
|
||||
if (((ilx_opts >> 2) & 63) == 2)
|
||||
uuid = hfs_uuid;
|
||||
else
|
||||
uuid = basic_data_uuid;
|
||||
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->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) && !(flag & 2)) {
|
||||
(*apm_count)++;
|
||||
if ((flag & 1) &&
|
||||
(t->bootsrc[i] != NULL || t->boot_appended_idx[i] >= 0)) {
|
||||
/* Register APM entry */
|
||||
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->opts->apm_block_size = 2048;
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
/* Let it be open ended. iso_write_gpt() will truncate it as needed. */
|
||||
block_count = 0xffffffff;
|
||||
ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
|
||||
(uint64_t) t->opts->partition_offset * 4,
|
||||
((uint64_t) block_count) * 4,
|
||||
basic_data_uuid, zero_uuid, gpt_flags,
|
||||
(uint8_t *) gpt_name);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* Remove ban on GPT overlapping */
|
||||
t->gpt_req_flags |= 1;
|
||||
}
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Insert APM head into MBR */
|
||||
static int insert_apm_head(uint8_t *buf, int apm_count)
|
||||
{
|
||||
int i;
|
||||
static uint8_t apm_mbr_start[32] = {
|
||||
0x33, 0xed, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||
};
|
||||
static uint8_t apm_head[32] = {
|
||||
0x45, 0x52, 0x08, 0x00, 0x00, 0x00, 0x90, 0x90,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
if (apm_count) {
|
||||
for (i = 0; i < 32; i++)
|
||||
if(buf[i] != apm_mbr_start[i])
|
||||
break;
|
||||
if (i < 32) {
|
||||
/* Maybe it is already patched by apm_head ? */
|
||||
for (i = 0; i < 32; i++)
|
||||
if(buf[i] != apm_head[i])
|
||||
break;
|
||||
}
|
||||
if (i < 32) {
|
||||
iso_msgs_submit(0,
|
||||
"MBR template file seems not prepared for Apple Partition Map.",
|
||||
0, "FAILURE", 0);
|
||||
return ISO_ISOLINUX_CANT_PATCH;
|
||||
}
|
||||
for (i = 0; i < 32; i++)
|
||||
buf[i] = apm_head[i];
|
||||
}
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Describe GPT boot images as MBR partitions */
|
||||
static int gpt_images_as_mbr_partitions(Ecma119Image *t, char *wpt,
|
||||
int gpt_idx[128], int *gpt_cursor)
|
||||
{
|
||||
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)" */
|
||||
|
||||
memcpy(wpt + 5, dummy_chs, 3);
|
||||
|
||||
/* Start LBA (in 512 blocks) */
|
||||
wpt += 8;
|
||||
lsb_to_buf(&wpt, t->bootsrc[gpt_idx[*gpt_cursor]]->sections[0].block * 4,
|
||||
32, 0);
|
||||
|
||||
/* Number of blocks */
|
||||
hd_blocks = t->bootsrc[gpt_idx[*gpt_cursor]]->sections[0].size;
|
||||
hd_blocks = hd_blocks / 512 + !!(hd_blocks % 512);
|
||||
lsb_to_buf(&wpt, (int) hd_blocks, 32, 0);
|
||||
|
||||
(*gpt_cursor)++;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* 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
|
||||
*/
|
||||
int make_isolinux_mbr(int32_t *img_blocks, uint32_t boot_lba,
|
||||
uint32_t mbr_id, int head_count, int sector_count,
|
||||
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 spc, id, part, nominal_part_size;
|
||||
uint32_t id, part, nominal_part_size;
|
||||
off_t hd_img_blocks, hd_boot_lba;
|
||||
char *wpt;
|
||||
/* For generating a weak random number */
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
uint32_t boot_lba;
|
||||
int head_count, sector_count, ret;
|
||||
int gpt_count = 0, gpt_idx[128], apm_count = 0, gpt_cursor, i;
|
||||
|
||||
/* Pad image_size to a multiple of sector_count*head_count
|
||||
*/
|
||||
spc = head_count * sector_count;
|
||||
hd_img_blocks = ((off_t) *img_blocks) * (off_t) 4;
|
||||
if (hd_img_blocks % spc) {
|
||||
hd_img_blocks += spc - (hd_img_blocks % spc);
|
||||
*img_blocks = hd_img_blocks / 4 + !!(hd_img_blocks % 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;
|
||||
head_count = t->partition_heads_per_cyl;
|
||||
sector_count = t->partition_secs_per_head;
|
||||
|
||||
ret = assess_isohybrid_gpt_apm(t, &gpt_count, gpt_idx, &apm_count, 0);
|
||||
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;
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
wpt = (char *) buf + 432;
|
||||
|
||||
/* write qword boot_lba # Offset 432
|
||||
@ -406,9 +686,10 @@ int make_isolinux_mbr(int32_t *img_blocks, uint32_t boot_lba,
|
||||
(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));
|
||||
id = iso_make_mbr_id(t, 0);
|
||||
lsb_to_buf(&wpt, id, 32, 0);
|
||||
} else {
|
||||
wpt+= 4;
|
||||
}
|
||||
|
||||
/* write word 0 # Offset 444
|
||||
@ -417,21 +698,35 @@ int make_isolinux_mbr(int32_t *img_blocks, uint32_t boot_lba,
|
||||
|
||||
/* # Offset 446
|
||||
*/
|
||||
gpt_cursor= 0;
|
||||
for (part = 1 ; part <= 4; part++) {
|
||||
if (part != part_number) {
|
||||
/* if this_partition != partition_number: write 16 zero bytes */
|
||||
if ((int) part != part_number) {
|
||||
/* if this_partition != partition_number: write 16 zero bytes
|
||||
(this is now overriden by the eventual desire to announce
|
||||
EFI and HFS boot images.)
|
||||
*/
|
||||
memset(wpt, 0, 16);
|
||||
|
||||
if (gpt_cursor < gpt_count) {
|
||||
ret = gpt_images_as_mbr_partitions(t, wpt, gpt_idx,
|
||||
&gpt_cursor);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
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);
|
||||
lsb_to_buf(&wpt, fs_type, 8, 0);
|
||||
lba512chs_to_buf(&wpt, hd_img_blocks - 1, head_count, sector_count);
|
||||
|
153
libisofs/md5.c
153
libisofs/md5.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2013 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
|
||||
@ -12,7 +12,14 @@
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
@ -222,10 +229,10 @@ static int md5_init(libisofs_md5_ctx *ctx, int flag)
|
||||
static int md5_update(libisofs_md5_ctx *ctx, unsigned char *data,
|
||||
int datalen, int flag)
|
||||
{
|
||||
unsigned int i, index, partlen;
|
||||
int i, index, partlen;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
index = (unsigned int)((ctx->count[0] >> 3) & 0x3F);
|
||||
index = ((ctx->count[0] >> 3) & 0x3F);
|
||||
/* Update number of bits */
|
||||
if ((ctx->count[0] += ((uint32_t) datalen << 3)) <
|
||||
((uint32_t) datalen << 3))
|
||||
@ -417,6 +424,22 @@ int checksum_cx_xinfo_func(void *data, int flag)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The iso_node_xinfo_cloner function which gets associated to
|
||||
* checksum_cx_xinfo_func by iso_init() resp. iso_init_with_flag() via
|
||||
* iso_node_xinfo_make_clonable()
|
||||
*/
|
||||
int checksum_cx_xinfo_cloner(void *old_data, void **new_data, int flag)
|
||||
{
|
||||
*new_data = NULL;
|
||||
if (flag)
|
||||
return ISO_XINFO_NO_CLONE;
|
||||
if (old_data == NULL)
|
||||
return 0;
|
||||
/* data is an int disguised as pointer. It does not point to memory. */
|
||||
*new_data = old_data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Function to identify and manage md5 sums of unspecified providence stored
|
||||
* directly in this xinfo.
|
||||
@ -429,6 +452,24 @@ int checksum_md5_xinfo_func(void *data, int flag)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The iso_node_xinfo_cloner function which gets associated to
|
||||
* checksum_md5_xinfo_func by iso_init() resp. iso_init_with_flag() via
|
||||
* iso_node_xinfo_make_clonable()
|
||||
*/
|
||||
int checksum_md5_xinfo_cloner(void *old_data, void **new_data, int flag)
|
||||
{
|
||||
*new_data = NULL;
|
||||
if (flag)
|
||||
return ISO_XINFO_NO_CLONE;
|
||||
if (old_data == NULL)
|
||||
return 0;
|
||||
*new_data = calloc(1, 16);
|
||||
if (*new_data == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
memcpy(*new_data, old_data, 16);
|
||||
return 16;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
@ -456,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 */
|
||||
@ -486,19 +527,25 @@ int checksum_copy_old_nodes(Ecma119Image *target, IsoNode *node, int flag)
|
||||
if (md5_pt == NULL)
|
||||
return 0;
|
||||
|
||||
ret = iso_node_lookup_attr(node, "isofs.cx", &value_length,
|
||||
&value, 0);
|
||||
if (ret == 1 && value_length == 4) {
|
||||
for (i = 0; i < 4; i++)
|
||||
idx = (idx << 8) | ((unsigned char *) value)[i];
|
||||
if (idx > 0 && idx <= target->checksum_idx_counter) {
|
||||
memcpy(target->checksum_buffer + 16 * idx, md5_pt, 16);
|
||||
if (!target->opts->will_cancel) {
|
||||
ret = iso_node_lookup_attr(node, "isofs.cx", &value_length,
|
||||
&value, 0);
|
||||
if (ret == 1 && value_length == 4) {
|
||||
for (i = 0; i < 4; i++)
|
||||
idx = (idx << 8) | ((unsigned char *) value)[i];
|
||||
if (idx > 0 && idx <= target->checksum_idx_counter) {
|
||||
memcpy(target->checksum_buffer + 16 * idx, md5_pt, 16);
|
||||
}
|
||||
}
|
||||
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.
|
||||
*/
|
||||
iso_node_remove_xinfo(node, checksum_md5_xinfo_func);
|
||||
}
|
||||
if (value != NULL)
|
||||
free(value);
|
||||
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) {
|
||||
@ -524,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++;
|
||||
@ -580,11 +627,6 @@ int checksum_writer_write_data(IsoImageWriter *writer)
|
||||
void *ctx = NULL;
|
||||
char md5[16];
|
||||
|
||||
#ifdef NIX
|
||||
char tag_block[2048];
|
||||
int l;
|
||||
#endif
|
||||
|
||||
if (writer == NULL) {
|
||||
return ISO_ASSERT_FAILURE;
|
||||
}
|
||||
@ -670,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++;
|
||||
}
|
||||
@ -683,15 +725,16 @@ int iso_md5_write_scdbackup_tag(Ecma119Image *t, char *tag_block, int flag)
|
||||
{
|
||||
void *ctx = NULL;
|
||||
off_t pos = 0, line_start;
|
||||
int record_len, block_len, res, i;
|
||||
char postext[40], md5[16], record[160];
|
||||
int record_len, block_len, ret, i;
|
||||
char postext[40], md5[16], *record = NULL;
|
||||
|
||||
LIBISO_ALLOC_MEM(record, char, 160);
|
||||
line_start = strlen(tag_block);
|
||||
iso_md5_compute(t->checksum_ctx, tag_block, line_start);
|
||||
res = iso_md5_clone(t->checksum_ctx, &ctx);
|
||||
if (res < 0)
|
||||
ret = iso_md5_clone(t->checksum_ctx, &ctx);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
res = iso_md5_end(&ctx, md5);
|
||||
ret = iso_md5_end(&ctx, md5);
|
||||
|
||||
pos = (off_t) t->checksum_tag_pos * (off_t) 2048 + line_start;
|
||||
if(pos >= 1000000000)
|
||||
@ -699,15 +742,15 @@ 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,
|
||||
"%2.2x", ((unsigned char *) md5)[i]);
|
||||
record_len += 32;
|
||||
|
||||
res = iso_md5_start(&ctx);
|
||||
if (res < 0)
|
||||
ret = iso_md5_start(&ctx);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
iso_md5_compute(ctx, record, record_len);
|
||||
iso_md5_end(&ctx, md5);
|
||||
@ -721,14 +764,15 @@ 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);
|
||||
res = ISO_SUCCESS;
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
if (ctx != NULL)
|
||||
iso_md5_end(&ctx, md5);
|
||||
return res;
|
||||
LIBISO_FREE_MEM(record);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -742,20 +786,20 @@ ex:;
|
||||
*/
|
||||
int iso_md5_write_tag(Ecma119Image *t, int flag)
|
||||
{
|
||||
int res, mode, l, i, wres, tag_id_len;
|
||||
int ret, mode, l, i, wres, tag_id_len;
|
||||
void *ctx = NULL;
|
||||
char md5[16], tag_block[2048], *tag_id;
|
||||
char md5[16], *tag_block = NULL, *tag_id;
|
||||
uint32_t size = 0, pos = 0, start;
|
||||
|
||||
LIBISO_ALLOC_MEM(tag_block, char, 2048);
|
||||
start = t->checksum_range_start;
|
||||
memset(tag_block, 0, 2048);
|
||||
mode = flag & 255;
|
||||
if (mode < 1 || mode > 4)
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
res = iso_md5_clone(t->checksum_ctx, &ctx);
|
||||
if (res < 0)
|
||||
return res;
|
||||
res = iso_md5_end(&ctx, md5);
|
||||
{ret = ISO_WRONG_ARG_VALUE; goto ex;}
|
||||
ret = iso_md5_clone(t->checksum_ctx, &ctx);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
ret = iso_md5_end(&ctx, md5);
|
||||
if (mode == 1) {
|
||||
size = t->checksum_range_size;
|
||||
pos = t->checksum_tag_pos;
|
||||
@ -770,7 +814,7 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
|
||||
}
|
||||
size = pos - start;
|
||||
}
|
||||
if (res < 0)
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
|
||||
iso_util_tag_magic(mode, &tag_id, &tag_id_len, 0);
|
||||
@ -783,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);
|
||||
@ -792,8 +836,8 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
|
||||
((unsigned char *) md5)[i]);
|
||||
l+= 32;
|
||||
|
||||
res = iso_md5_start(&ctx);
|
||||
if (res > 0) {
|
||||
ret = iso_md5_start(&ctx);
|
||||
if (ret > 0) {
|
||||
iso_md5_compute(ctx, tag_block, l);
|
||||
iso_md5_end(&ctx, md5);
|
||||
strcpy(tag_block + l, " self=");
|
||||
@ -804,12 +848,12 @@ 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 {
|
||||
res = iso_md5_write_scdbackup_tag(t, tag_block, 0);
|
||||
if (res < 0)
|
||||
ret = iso_md5_write_scdbackup_tag(t, tag_block, 0);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
@ -820,16 +864,17 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
|
||||
} else {
|
||||
wres = iso_write(t, tag_block, 2048);
|
||||
if (wres < 0) {
|
||||
res = wres;
|
||||
ret = wres;
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
|
||||
res = ISO_SUCCESS;
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
if (ctx != NULL)
|
||||
iso_md5_end(&ctx, md5);
|
||||
return res;
|
||||
LIBISO_FREE_MEM(tag_block);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* 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
|
||||
@ -36,6 +37,8 @@
|
||||
#include "messages.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "node.h"
|
||||
#include "stream.h"
|
||||
|
||||
|
||||
/*
|
||||
@ -79,16 +82,82 @@ int abort_threshold = LIBISO_MSGS_SEV_FAILURE;
|
||||
struct libiso_msgs *libiso_msgr = NULL;
|
||||
|
||||
|
||||
/* ------------- List of xinfo clone functions ----------- */
|
||||
|
||||
struct iso_xinfo_cloner_assoc {
|
||||
iso_node_xinfo_func proc;
|
||||
iso_node_xinfo_cloner cloner;
|
||||
struct iso_xinfo_cloner_assoc *next;
|
||||
};
|
||||
|
||||
struct iso_xinfo_cloner_assoc *iso_xinfo_cloner_list = NULL;
|
||||
|
||||
/* API */
|
||||
int iso_node_xinfo_make_clonable(iso_node_xinfo_func proc,
|
||||
iso_node_xinfo_cloner cloner, int flag)
|
||||
{
|
||||
struct iso_xinfo_cloner_assoc *assoc;
|
||||
|
||||
/* Look for existing assoc of proc */
|
||||
for (assoc = iso_xinfo_cloner_list; assoc != NULL; assoc = assoc->next)
|
||||
if (assoc->proc == proc)
|
||||
break;
|
||||
|
||||
if (assoc == NULL) {
|
||||
assoc = calloc(1, sizeof(struct iso_xinfo_cloner_assoc));
|
||||
if (assoc == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
assoc->proc = proc;
|
||||
assoc->next = iso_xinfo_cloner_list;
|
||||
iso_xinfo_cloner_list = assoc;
|
||||
}
|
||||
assoc->cloner = cloner;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
/* API */
|
||||
int iso_node_xinfo_get_cloner(iso_node_xinfo_func proc,
|
||||
iso_node_xinfo_cloner *cloner, int flag)
|
||||
{
|
||||
struct iso_xinfo_cloner_assoc *assoc;
|
||||
|
||||
*cloner = NULL;
|
||||
for (assoc = iso_xinfo_cloner_list; assoc != NULL; assoc = assoc->next) {
|
||||
if (assoc->proc != proc)
|
||||
continue;
|
||||
*cloner = assoc->cloner;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int iso_node_xinfo_dispose_cloners(int flag)
|
||||
{
|
||||
struct iso_xinfo_cloner_assoc *assoc, *next;
|
||||
|
||||
for (assoc = iso_xinfo_cloner_list; assoc != NULL; assoc = next) {
|
||||
next = assoc->next;
|
||||
free((char *) assoc);
|
||||
}
|
||||
iso_xinfo_cloner_list= NULL;
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* ------------- End of xinfo clone functions list ----------- */
|
||||
|
||||
|
||||
/*
|
||||
@param flag bit0= do not set up locale by LC_* environment variables
|
||||
*/
|
||||
int iso_init_with_flag(int flag)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#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 */
|
||||
@ -119,7 +188,6 @@ LIBJTE_MISCONFIGURATION_ = 0;
|
||||
|
||||
#endif /* Libisofs_with_libjtE */
|
||||
|
||||
|
||||
if (! (flag & 1)) {
|
||||
iso_init_locale(0);
|
||||
}
|
||||
@ -129,10 +197,33 @@ LIBJTE_MISCONFIGURATION_ = 0;
|
||||
}
|
||||
libiso_msgs_set_severities(libiso_msgr, LIBISO_MSGS_SEV_NEVER,
|
||||
LIBISO_MSGS_SEV_FATAL, "libisofs: ", 0);
|
||||
|
||||
ret = iso_node_xinfo_make_clonable(aaip_xinfo_func, aaip_xinfo_cloner, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = iso_node_xinfo_make_clonable(checksum_cx_xinfo_func,
|
||||
checksum_cx_xinfo_cloner, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = iso_node_xinfo_make_clonable(checksum_md5_xinfo_func,
|
||||
checksum_md5_xinfo_cloner, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = iso_node_xinfo_make_clonable(zisofs_zf_xinfo_func,
|
||||
zisofs_zf_xinfo_cloner, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = iso_node_xinfo_make_clonable(iso_px_ino_xinfo_func,
|
||||
iso_px_ino_xinfo_cloner, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = iso_node_xinfo_make_clonable(iso_hfsplus_xinfo_func,
|
||||
iso_hfsplus_xinfo_cloner, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int iso_init()
|
||||
{
|
||||
return iso_init_with_flag(0);
|
||||
@ -141,6 +232,8 @@ int iso_init()
|
||||
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)
|
||||
@ -159,15 +252,18 @@ int iso_set_abort_severity(char *severity)
|
||||
|
||||
void iso_msg_debug(int imgid, const char *fmt, ...)
|
||||
{
|
||||
char msg[MAX_MSG_LEN];
|
||||
char *msg = NULL;
|
||||
va_list ap;
|
||||
|
||||
LIBISO_ALLOC_MEM_VOID(msg, char, MAX_MSG_LEN);
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(msg, MAX_MSG_LEN, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
libiso_msgs_submit(libiso_msgr, imgid, 0x00000002, LIBISO_MSGS_SEV_DEBUG,
|
||||
LIBISO_MSGS_PRIO_ZERO, msg, 0, 0);
|
||||
ex:;
|
||||
LIBISO_FREE_MEM(msg);
|
||||
}
|
||||
|
||||
const char *iso_error_to_msg(int errcode)
|
||||
@ -251,9 +347,9 @@ const char *iso_error_to_msg(int errcode)
|
||||
case ISO_WRONG_PVD:
|
||||
return "Wrong or damaged Primary Volume Descriptor";
|
||||
case ISO_WRONG_RR:
|
||||
return "Wrong or damaged RR entry";
|
||||
return "Wrong or damaged Rock Ridge entry";
|
||||
case ISO_UNSUPPORTED_RR:
|
||||
return "Unsupported RR feature";
|
||||
return "Unsupported Rock Ridge feature";
|
||||
case ISO_WRONG_ECMA119:
|
||||
return "Wrong or damaged ECMA-119";
|
||||
case ISO_UNSUPPORTED_ECMA119:
|
||||
@ -267,9 +363,9 @@ const char *iso_error_to_msg(int errcode)
|
||||
case ISO_UNSUPPORTED_SUSP:
|
||||
return "Unsupported SUSP feature";
|
||||
case ISO_WRONG_RR_WARN:
|
||||
return "Error on a RR entry that can be ignored";
|
||||
return "Error on a Rock Ridge entry that can be ignored";
|
||||
case ISO_SUSP_UNHANDLED:
|
||||
return "Error on a RR entry that can be ignored";
|
||||
return "Unhandled SUSP entry";
|
||||
case ISO_SUSP_MULTIPLE_ER:
|
||||
return "Multiple ER SUSP entries found";
|
||||
case ISO_UNSUPPORTED_VD:
|
||||
@ -284,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:
|
||||
@ -358,11 +454,99 @@ const char *iso_error_to_msg(int errcode)
|
||||
case ISO_BAD_PARTITION_FILE:
|
||||
return "Cannot open data file for appended partition";
|
||||
case ISO_NON_MBR_SYS_AREA:
|
||||
return "May not combine appended partition with non-MBR system area";
|
||||
return "May not combine MBR partition with non-MBR system area";
|
||||
case ISO_DISPLACE_ROLLOVER:
|
||||
return "Displacement offset leads outside 32 bit range";
|
||||
case ISO_NAME_NEEDS_TRANSL:
|
||||
return "File name cannot be written into ECMA-119 untranslated";
|
||||
case ISO_STREAM_NO_CLONE:
|
||||
return "Data file input stream object offers no cloning method";
|
||||
case ISO_XINFO_NO_CLONE:
|
||||
return "Extended information class offers no cloning method";
|
||||
case ISO_MD5_TAG_COPIED:
|
||||
return "Found copied superblock checksum tag";
|
||||
case ISO_RR_NAME_TOO_LONG:
|
||||
return "Rock Ridge leaf name too long";
|
||||
case ISO_RR_NAME_RESERVED:
|
||||
return "Reserved Rock Ridge leaf name";
|
||||
case ISO_RR_PATH_TOO_LONG:
|
||||
return "Rock Ridge path too long";
|
||||
case ISO_AAIP_BAD_ATTR_NAME:
|
||||
return "Attribute name cannot be represented";
|
||||
case ISO_AAIP_ACL_MULT_OBJ:
|
||||
return "ACL text contains multiple entries of user::, group::, other::";
|
||||
case ISO_SECT_SCATTERED:
|
||||
return "File sections do not form consecutive array of blocks";
|
||||
case ISO_BOOT_TOO_MANY_APM:
|
||||
return "Too many Apple Partition Map entries requested";
|
||||
case ISO_BOOT_APM_OVERLAP:
|
||||
return "Overlapping Apple Partition Map entries requested";
|
||||
case ISO_BOOT_TOO_MANY_GPT:
|
||||
return "Too many GPT entries requested";
|
||||
case ISO_BOOT_GPT_OVERLAP:
|
||||
return "Overlapping GPT entries requested";
|
||||
case ISO_BOOT_TOO_MANY_MBR:
|
||||
return "Too many MBR partition entries requested";
|
||||
case ISO_BOOT_MBR_OVERLAP:
|
||||
return "Overlapping MBR partition entries requested";
|
||||
case ISO_BOOT_MBR_COLLISION:
|
||||
return "Attempt to use an MBR partition entry twice";
|
||||
case ISO_BOOT_NO_EFI_ELTO:
|
||||
return "No suitable El Torito EFI boot image for exposure as GPT partition";
|
||||
case ISO_BOOT_HFSP_BAD_BSIZE:
|
||||
return "Not a supported HFS+ or APM block size";
|
||||
case ISO_BOOT_APM_GPT_BSIZE:
|
||||
return "APM block size prevents coexistence with GPT";
|
||||
case ISO_HFSP_NO_MANGLE:
|
||||
return "Name collision in HFS+, mangling not possible";
|
||||
case ISO_DEAD_SYMLINK:
|
||||
return "Symbolic link cannot be resolved";
|
||||
case ISO_DEEP_SYMLINK:
|
||||
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";
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
@ -382,7 +566,7 @@ int iso_msg_submit(int imgid, int errcode, int causedby, const char *fmt, ...)
|
||||
va_list ap;
|
||||
|
||||
/* when called with ISO_CANCELED, we don't need to submit any message */
|
||||
if (errcode == ISO_CANCELED && fmt == NULL) {
|
||||
if (errcode == (int) ISO_CANCELED && fmt == NULL) {
|
||||
return ISO_CANCELED;
|
||||
}
|
||||
|
||||
@ -391,7 +575,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),
|
||||
|
538
libisofs/node.c
538
libisofs/node.c
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 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
|
||||
@ -19,6 +19,7 @@
|
||||
#include "aaip_0_2.h"
|
||||
#include "messages.h"
|
||||
#include "util.h"
|
||||
#include "eltorito.h"
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
@ -28,11 +29,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX Libisofs_default_path_maX
|
||||
#endif
|
||||
|
||||
|
||||
struct dir_iter_data
|
||||
{
|
||||
/* points to the last visited child, to NULL before start */
|
||||
@ -59,6 +55,8 @@ void iso_node_ref(IsoNode *node)
|
||||
*/
|
||||
void iso_node_unref(IsoNode *node)
|
||||
{
|
||||
if (node == NULL)
|
||||
return;
|
||||
if (--node->refcount == 0) {
|
||||
switch (node->type) {
|
||||
case LIBISO_DIR:
|
||||
@ -83,6 +81,14 @@ void iso_node_unref(IsoNode *node)
|
||||
IsoSymlink *link = (IsoSymlink*) node;
|
||||
free(link->dest);
|
||||
}
|
||||
break;
|
||||
case LIBISO_BOOT:
|
||||
{
|
||||
IsoBoot *bootcat = (IsoBoot *) node;
|
||||
if (bootcat->content != NULL)
|
||||
free(bootcat->content);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* other kind of nodes does not need to delete anything here */
|
||||
break;
|
||||
@ -226,6 +232,89 @@ int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* API */
|
||||
int iso_node_get_next_xinfo(IsoNode *node, void **handle,
|
||||
iso_node_xinfo_func *proc, void **data)
|
||||
{
|
||||
IsoExtendedInfo *xinfo;
|
||||
|
||||
if (node == NULL || handle == NULL || proc == NULL || data == NULL)
|
||||
return ISO_NULL_POINTER;
|
||||
*proc = NULL;
|
||||
*data = NULL;
|
||||
xinfo = (IsoExtendedInfo *) *handle;
|
||||
if (xinfo == NULL)
|
||||
xinfo = node->xinfo;
|
||||
else
|
||||
xinfo = xinfo->next;
|
||||
*handle = xinfo;
|
||||
if (xinfo == NULL)
|
||||
return 0;
|
||||
*proc = xinfo->process;
|
||||
*data = xinfo->data;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_node_remove_all_xinfo(IsoNode *node, int flag)
|
||||
{
|
||||
IsoExtendedInfo *pos, *next;
|
||||
|
||||
for (pos = node->xinfo; pos != NULL; pos = next) {
|
||||
next = pos->next;
|
||||
pos->process(pos->data, 1);
|
||||
free((char *) pos);
|
||||
}
|
||||
node->xinfo = NULL;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
int iso_node_revert_xinfo_list(IsoNode *node, int flag)
|
||||
{
|
||||
|
||||
IsoExtendedInfo *pos, *next, *prev = NULL;
|
||||
|
||||
for (pos = node->xinfo; pos != NULL; pos = next) {
|
||||
next = pos->next;
|
||||
pos->next = prev;
|
||||
prev = pos;
|
||||
}
|
||||
node->xinfo = prev;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_node_clone_xinfo(IsoNode *from_node, IsoNode *to_node, int flag)
|
||||
{
|
||||
void *handle = NULL, *data, *new_data;
|
||||
iso_node_xinfo_func proc;
|
||||
iso_node_xinfo_cloner cloner;
|
||||
int ret;
|
||||
|
||||
iso_node_remove_all_xinfo(to_node, 0);
|
||||
while (1) {
|
||||
ret = iso_node_get_next_xinfo(from_node, &handle, &proc, &data);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
ret = iso_node_xinfo_get_cloner(proc, &cloner, 0);
|
||||
if (ret == 0)
|
||||
return ISO_XINFO_NO_CLONE;
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = (*cloner)(data, &new_data, 0);
|
||||
if (ret < 0)
|
||||
break;
|
||||
ret = iso_node_add_xinfo(to_node, proc, new_data);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
if (ret < 0) {
|
||||
iso_node_remove_all_xinfo(to_node, 0);
|
||||
} else {
|
||||
ret = iso_node_revert_xinfo_list(to_node, 0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of an IsoNode.
|
||||
*/
|
||||
@ -238,31 +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;
|
||||
}
|
||||
|
||||
/* check if the name is valid */
|
||||
if (!iso_node_is_valid_name(name)) {
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
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)
|
||||
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;
|
||||
@ -274,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -287,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;
|
||||
}
|
||||
|
||||
@ -520,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.
|
||||
*
|
||||
@ -651,6 +819,9 @@ int iso_node_take(IsoNode *node)
|
||||
if (dir == NULL) {
|
||||
return ISO_NODE_NOT_ADDED_TO_DIR;
|
||||
}
|
||||
|
||||
/* >>> Do not take root directory ! (dir == node) ? */;
|
||||
|
||||
pos = iso_dir_find_node(dir, node);
|
||||
if (pos == NULL) {
|
||||
/* should never occur */
|
||||
@ -686,6 +857,44 @@ int iso_node_remove(IsoNode *node)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* API */
|
||||
int iso_node_remove_tree(IsoNode *node, IsoDirIter *boss_iter)
|
||||
{
|
||||
IsoDirIter *iter = NULL;
|
||||
IsoNode *sub_node;
|
||||
int ret;
|
||||
|
||||
if (node->type != LIBISO_DIR) {
|
||||
|
||||
/* >>> Do not remove root directory ! (node->parent == node) ? */;
|
||||
|
||||
ret = iso_dir_get_children((IsoDir *) node, &iter);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
while(1) {
|
||||
ret = iso_dir_iter_next(iter, &sub_node);
|
||||
if (ret == 0)
|
||||
break;
|
||||
ret = iso_node_remove_tree(sub_node, iter);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
if (node->parent == NULL) {
|
||||
/* node is not grafted into a boss directory */
|
||||
iso_node_unref(node);
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
if (boss_iter != NULL)
|
||||
ret = iso_dir_iter_remove(boss_iter);
|
||||
else
|
||||
ret = iso_node_remove(node);
|
||||
ex:;
|
||||
if (iter != NULL)
|
||||
iso_dir_iter_free(iter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the parent of the given iso tree node. No extra ref is added to the
|
||||
* returned directory, you must take your ref. with iso_node_ref() if you
|
||||
@ -881,10 +1090,11 @@ const char *iso_symlink_get_dest(const IsoSymlink *link)
|
||||
int iso_symlink_set_dest(IsoSymlink *link, const char *dest)
|
||||
{
|
||||
char *d;
|
||||
if (!iso_node_is_valid_link_dest(dest)) {
|
||||
/* guard against null or empty dest */
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
int ret;
|
||||
|
||||
ret = iso_node_is_valid_link_dest(dest);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
d = strdup(dest);
|
||||
if (d == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
@ -904,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)
|
||||
{
|
||||
@ -916,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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -984,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.
|
||||
*
|
||||
@ -1035,24 +1246,32 @@ int iso_node_is_valid_name(const char *name)
|
||||
{
|
||||
/* a name can't be NULL */
|
||||
if (name == NULL) {
|
||||
return 0;
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
|
||||
/* guard against the empty string or big names... */
|
||||
if (name[0] == '\0' || strlen(name) > 255) {
|
||||
return 0;
|
||||
}
|
||||
if (name[0] == '\0')
|
||||
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 0;
|
||||
}
|
||||
if (!strcmp(name, ".") || !strcmp(name, ".."))
|
||||
goto rr_reserved;
|
||||
|
||||
/* ...and against names with '/' */
|
||||
if (strchr(name, '/') != NULL) {
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1068,13 +1287,18 @@ int iso_node_is_valid_link_dest(const char *dest)
|
||||
|
||||
/* a dest can't be NULL */
|
||||
if (dest == NULL) {
|
||||
return 0;
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
|
||||
/* guard against the empty string or big dest... */
|
||||
if (dest[0] == '\0' || strlen(dest) > PATH_MAX) {
|
||||
return 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;
|
||||
|
||||
/* check that all components are valid */
|
||||
if (!strcmp(dest, "/")) {
|
||||
@ -1084,7 +1308,7 @@ int iso_node_is_valid_link_dest(const char *dest)
|
||||
|
||||
ptr = strdup(dest);
|
||||
if (ptr == NULL) {
|
||||
return 0;
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
@ -1092,7 +1316,7 @@ int iso_node_is_valid_link_dest(const char *dest)
|
||||
while (component) {
|
||||
if (strcmp(component, ".") && strcmp(component, "..")) {
|
||||
ret = iso_node_is_valid_name(component);
|
||||
if (ret == 0) {
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1251,15 +1475,16 @@ int iso_node_new_root(IsoDir **root)
|
||||
int iso_node_new_dir(char *name, IsoDir **dir)
|
||||
{
|
||||
IsoDir *new;
|
||||
int ret;
|
||||
|
||||
if (dir == NULL || name == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
|
||||
/* check if the name is valid */
|
||||
if (!iso_node_is_valid_name(name)) {
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
ret = iso_node_is_valid_name(name);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
new = calloc(1, sizeof(IsoDir));
|
||||
if (new == NULL) {
|
||||
@ -1276,15 +1501,16 @@ int iso_node_new_dir(char *name, IsoDir **dir)
|
||||
int iso_node_new_file(char *name, IsoStream *stream, IsoFile **file)
|
||||
{
|
||||
IsoFile *new;
|
||||
int ret;
|
||||
|
||||
if (file == NULL || name == NULL || stream == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
|
||||
/* check if the name is valid */
|
||||
if (!iso_node_is_valid_name(name)) {
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
ret = iso_node_is_valid_name(name);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
new = calloc(1, sizeof(IsoFile));
|
||||
if (new == NULL) {
|
||||
@ -1294,6 +1520,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;
|
||||
|
||||
@ -1304,21 +1532,21 @@ int iso_node_new_file(char *name, IsoStream *stream, IsoFile **file)
|
||||
int iso_node_new_symlink(char *name, char *dest, IsoSymlink **link)
|
||||
{
|
||||
IsoSymlink *new;
|
||||
int ret;
|
||||
|
||||
if (link == NULL || name == NULL || dest == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
|
||||
/* check if the name is valid */
|
||||
if (!iso_node_is_valid_name(name)) {
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
ret = iso_node_is_valid_name(name);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* check if destination is valid */
|
||||
if (!iso_node_is_valid_link_dest(dest)) {
|
||||
/* guard against null or empty dest */
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
ret = iso_node_is_valid_link_dest(dest);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
new = calloc(1, sizeof(IsoSymlink));
|
||||
if (new == NULL) {
|
||||
@ -1340,6 +1568,7 @@ int iso_node_new_special(char *name, mode_t mode, dev_t dev,
|
||||
IsoSpecial **special)
|
||||
{
|
||||
IsoSpecial *new;
|
||||
int ret;
|
||||
|
||||
if (special == NULL || name == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
@ -1349,9 +1578,9 @@ int iso_node_new_special(char *name, mode_t mode, dev_t dev,
|
||||
}
|
||||
|
||||
/* check if the name is valid */
|
||||
if (!iso_node_is_valid_name(name)) {
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
ret = iso_node_is_valid_name(name);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
new = calloc(1, sizeof(IsoSpecial));
|
||||
if (new == NULL) {
|
||||
@ -1380,11 +1609,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];
|
||||
@ -1447,7 +1682,7 @@ int iso_aa_get_attrs(unsigned char *aa_string, size_t *num_attrs,
|
||||
goto ex;
|
||||
}
|
||||
|
||||
if (rpt - aa_string != len) {
|
||||
if ((size_t) (rpt - aa_string) != len) {
|
||||
/* aaip_decode_attrs() returns 2 but still bytes are left */
|
||||
ret = ISO_AAIP_BAD_AASTRING;
|
||||
goto ex;
|
||||
@ -1489,13 +1724,15 @@ int iso_aa_lookup_attr(unsigned char *aa_string, char *name,
|
||||
|
||||
ret = iso_aa_get_attrs(aa_string, &num_attrs, &names,
|
||||
&value_lengths, &values, 0);
|
||||
for (i = 0; i < num_attrs; i++) {
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
for (i = 0; i < (int) num_attrs; i++) {
|
||||
if (strcmp(names[i], name))
|
||||
continue;
|
||||
*value_length = value_lengths[i];
|
||||
*value = calloc(*value_length + 1, 1);
|
||||
if (*value == NULL) {
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
found = ISO_OUT_OF_MEM;
|
||||
break;
|
||||
}
|
||||
if (*value_length > 0)
|
||||
@ -1581,13 +1818,14 @@ 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
|
||||
bit4= do not overwrite value of empty name
|
||||
bit5= do not overwrite isofs attributes
|
||||
bit15= release memory and return 1
|
||||
*/
|
||||
static
|
||||
@ -1636,6 +1874,8 @@ int iso_node_merge_xattr(IsoNode *node, size_t num_attrs, char **names,
|
||||
continue;
|
||||
if (names[i][0] == 0 && (flag & 16))
|
||||
continue;
|
||||
if ((flag & 32) && strncmp(names[i], "isofs.", 6) == 0)
|
||||
continue;
|
||||
for (j = 0; j < *m_num_attrs; j++) {
|
||||
if ((*m_names)[j] == NULL)
|
||||
continue;
|
||||
@ -1681,6 +1921,8 @@ int iso_node_merge_xattr(IsoNode *node, size_t num_attrs, char **names,
|
||||
continue;
|
||||
if (names[i][0] == 0 && (flag & 16))
|
||||
continue;
|
||||
if ((flag & 32) && strncmp(names[i], "isofs.", 6) == 0)
|
||||
continue;
|
||||
for (j = 0; j < *m_num_attrs; j++) {
|
||||
if ((*m_names)[j] == NULL)
|
||||
continue;
|
||||
@ -1723,21 +1965,22 @@ 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))
|
||||
for (i = 0; i < num_attrs; i++)
|
||||
if (strncmp(names[i], "user.", 5) != 0 && names[i][0] != 0)
|
||||
return ISO_AAIP_NON_USER_NAME;
|
||||
|
||||
if ((flag & (2 | 4)) || !(flag & 8)) {
|
||||
if ((flag & (2 | 4 | 16)) || !(flag & 8)) {
|
||||
/* Merge old and new lists */
|
||||
ret = iso_node_merge_xattr(
|
||||
node, num_attrs, names, value_lengths, values,
|
||||
&m_num, &m_names, &m_value_lengths, &m_values,
|
||||
(flag & 4) | (!(flag & 2)) | ((!(flag & 1)) << 4));
|
||||
(flag & 4) | (!(flag & 2)) | ((!(flag & 1)) << 4) |
|
||||
((flag & 16) << 1));
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
num_attrs = m_num;
|
||||
@ -1763,28 +2006,34 @@ 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:;
|
||||
@ -2002,20 +2251,20 @@ 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);
|
||||
} 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);
|
||||
}
|
||||
if (ret <= 0) {
|
||||
if (ret == -1)
|
||||
ret = ISO_OUT_OF_MEM;
|
||||
else if (ret <= 0 && ret >= -3)
|
||||
ret = ISO_AAIP_BAD_ACL_TEXT;
|
||||
if (ret <= 0)
|
||||
goto ex;
|
||||
}
|
||||
|
||||
if(acl == NULL) { /* Delete whole ACL attribute */
|
||||
/* Update S_IRWXG by eventual "group::" ACL entry.
|
||||
@ -2068,6 +2317,8 @@ int iso_node_set_acl_text(IsoNode *node, char *access_text, char *default_text,
|
||||
}
|
||||
ret = aaip_encode_both_acl(access_text, default_text,
|
||||
st_mode, &acl_len, &acl, 2 | 8);
|
||||
if (ret < -3)
|
||||
goto ex;
|
||||
if (ret <= 0) {
|
||||
ret = ISO_AAIP_BAD_ACL_TEXT;
|
||||
goto ex;
|
||||
@ -2153,6 +2404,23 @@ int zisofs_zf_xinfo_func(void *data, int flag)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The iso_node_xinfo_cloner function which gets associated to
|
||||
* zisofs_zf_xinfo_func by iso_init() resp. iso_init_with_flag() via
|
||||
* iso_node_xinfo_make_clonable()
|
||||
*/
|
||||
int zisofs_zf_xinfo_cloner(void *old_data, void **new_data, int flag)
|
||||
{
|
||||
*new_data = NULL;
|
||||
if (flag)
|
||||
return ISO_XINFO_NO_CLONE;
|
||||
if (old_data == NULL)
|
||||
return 0;
|
||||
*new_data = calloc(1, sizeof(struct zisofs_zf_info));
|
||||
if (*new_data == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
memcpy(*new_data, old_data, sizeof(struct zisofs_zf_info));
|
||||
return (int) sizeof(struct zisofs_zf_info);
|
||||
}
|
||||
|
||||
/* Checks whether a file effectively bears a zisofs file header and eventually
|
||||
* marks this by a struct zisofs_zf_info as xinfo of the file node.
|
||||
@ -2274,6 +2542,21 @@ int iso_px_ino_xinfo_func(void *data, int flag)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The iso_node_xinfo_cloner function which gets associated to
|
||||
* iso_px_ino_xinfo_func by iso_init() resp. iso_init_with_flag() via
|
||||
* iso_node_xinfo_make_clonable()
|
||||
*/
|
||||
int iso_px_ino_xinfo_cloner(void *old_data, void **new_data, int flag)
|
||||
{
|
||||
*new_data = NULL;
|
||||
if (flag)
|
||||
return ISO_XINFO_NO_CLONE;
|
||||
*new_data = calloc(1, sizeof(ino_t));
|
||||
if (*new_data == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
memcpy(*new_data, old_data, sizeof(ino_t));
|
||||
return (int) sizeof(ino_t);
|
||||
}
|
||||
|
||||
/*
|
||||
* @param flag
|
||||
@ -2364,7 +2647,6 @@ int iso_node_set_ino_xinfo(IsoNode *node, ino_t ino, int flag)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int iso_node_set_ino(IsoNode *node, ino_t ino, int flag)
|
||||
{
|
||||
int ret;
|
||||
@ -2387,6 +2669,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;
|
||||
@ -2577,6 +2860,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)
|
||||
{
|
||||
@ -2586,9 +2871,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;
|
||||
@ -2667,6 +2957,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)
|
||||
{
|
||||
@ -2693,7 +3027,7 @@ int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag)
|
||||
ret = 0;
|
||||
goto ex;
|
||||
}
|
||||
for (i = 0; i < value_len; i++)
|
||||
for (i = 0; i < (int) value_len; i++)
|
||||
idx = (idx << 8) | ((unsigned char *) value)[i];
|
||||
if (idx == 0 || idx > image->checksum_idx_count - 1) {
|
||||
/* (last index is not MD5 of a file) */
|
||||
@ -2720,21 +3054,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 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
|
||||
@ -20,7 +20,38 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Maximum length of a leaf name in the libisofs node tree. This is currently
|
||||
restricted by the implemented maximum length of a Rock Ridge name.
|
||||
This might later become larger and may then be limited to smaller values.
|
||||
|
||||
Rock Ridge specs do not impose an explicit limit on name length.
|
||||
But 255 is also specified by
|
||||
http://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html
|
||||
which says
|
||||
NAME_MAX >= _XOPEN_NAME_MAX = 255
|
||||
*/
|
||||
#define LIBISOFS_NODE_NAME_MAX 255
|
||||
|
||||
|
||||
/* Maximum length of a path in the libisofs node tree.
|
||||
Rock Ridge specs do not impose an explicit limit on path length.
|
||||
|
||||
http://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html
|
||||
says
|
||||
PATH_MAX >= _XOPEN_PATH_MAX = 1024
|
||||
*/
|
||||
#define LIBISOFS_NODE_PATH_MAX 1024
|
||||
|
||||
|
||||
/**
|
||||
* The extended information is a way to attach additional information to each
|
||||
@ -113,12 +144,20 @@ struct Iso_Dir
|
||||
IsoNode *children; /**< list of children. ptr to first child */
|
||||
};
|
||||
|
||||
/* IMPORTANT: Any change must be reflected by iso_tree_clone_file. */
|
||||
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 +316,7 @@ int iso_node_new_special(char *name, mode_t mode, dev_t dev,
|
||||
* Check if a given name is valid for an iso node.
|
||||
*
|
||||
* @return
|
||||
* 1 if yes, 0 if not
|
||||
* 1 if yes, <0 if not. The value is a specific ISO_* error code.
|
||||
*/
|
||||
int iso_node_is_valid_name(const char *name);
|
||||
|
||||
@ -448,7 +487,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.
|
||||
*/
|
||||
@ -473,4 +512,51 @@ 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.
|
||||
*/
|
||||
int iso_node_clone_xinfo(IsoNode *from_node, IsoNode *to_node, int flag);
|
||||
|
||||
|
||||
/**
|
||||
* The iso_node_xinfo_func instance which governs the storing of the inode
|
||||
* number from Rock Ridge field PX.
|
||||
*/
|
||||
int iso_px_ino_xinfo_func(void *data, int flag);
|
||||
|
||||
/* The iso_node_xinfo_cloner function which gets associated to
|
||||
* iso_px_ino_xinfo_func by iso_init() resp. iso_init_with_flag() via
|
||||
* iso_node_xinfo_make_clonable()
|
||||
*/
|
||||
int iso_px_ino_xinfo_cloner(void *old_data, void **new_data, int flag);
|
||||
|
||||
|
||||
/* Function to identify and manage ZF parameters of zisofs compression.
|
||||
* data is supposed to be a pointer to struct zisofs_zf_info
|
||||
*/
|
||||
int zisofs_zf_xinfo_func(void *data, int flag);
|
||||
|
||||
/* The iso_node_xinfo_cloner function which gets associated to
|
||||
* zisofs_zf_xinfo_func by iso_init() resp. iso_init_with_flag() via
|
||||
* iso_node_xinfo_make_clonable()
|
||||
*/
|
||||
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 - 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
|
||||
@ -63,10 +63,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 +198,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);
|
||||
size_t *ce, size_t base_ce);
|
||||
|
||||
/**
|
||||
* Fill a struct susp_info with the RR/SUSP entries needed for a given
|
||||
@ -346,4 +360,12 @@ 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);
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
|
@ -81,8 +81,7 @@ int susp_iter_next(SuspIterator *iter, struct susp_sys_user_entry **sue)
|
||||
* (IEEE 1281, SUSP. section 4)
|
||||
*/
|
||||
if (iter->ce_len) {
|
||||
uint32_t block;
|
||||
int nblocks;
|
||||
uint32_t block, nblocks;
|
||||
|
||||
/* A CE has found, there is another continuation area */
|
||||
nblocks = DIV_UP(iter->ce_off + iter->ce_len, BLOCK_SIZE);
|
||||
@ -212,10 +211,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;
|
||||
}
|
||||
|
||||
@ -413,7 +421,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') {
|
||||
@ -443,7 +451,7 @@ int read_rr_PN(struct susp_sys_user_entry *pn, struct stat *st)
|
||||
}
|
||||
|
||||
|
||||
/* AA is the field signature of AAIP versions < 2.0
|
||||
/* AA is the obsolete field signature of AAIP versions < 2.0
|
||||
*/
|
||||
int read_aaip_AA(struct susp_sys_user_entry *sue,
|
||||
unsigned char **aa_string, size_t *aa_size, size_t *aa_len,
|
||||
@ -514,7 +522,7 @@ int read_aaip_AA(struct susp_sys_user_entry *sue,
|
||||
}
|
||||
|
||||
|
||||
/* AL is the obsolete field signature of AAIP versions >= 2.0
|
||||
/* AL is the field signature of AAIP versions >= 2.0
|
||||
*/
|
||||
int read_aaip_AL(struct susp_sys_user_entry *sue,
|
||||
unsigned char **aa_string, size_t *aa_size, size_t *aa_len,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 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
|
||||
@ -16,6 +16,7 @@
|
||||
#include "stream.h"
|
||||
#include "fsource.h"
|
||||
#include "util.h"
|
||||
#include "node.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -157,8 +158,56 @@ int fsrc_update_size(IsoStream *stream)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
IsoStream *fsrc_get_input_stream(IsoStream *stream, int flag)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int fsrc_clone_stream(IsoStream *old_stream, IsoStream **new_stream,
|
||||
int flag)
|
||||
{
|
||||
FSrcStreamData *data, *new_data;
|
||||
IsoStream *stream;
|
||||
int ret;
|
||||
|
||||
if (flag)
|
||||
return ISO_STREAM_NO_CLONE; /* unknown option required */
|
||||
|
||||
data = (FSrcStreamData*) old_stream->data;
|
||||
if (data->src->class->version < 2)
|
||||
return ISO_STREAM_NO_CLONE; /* No clone_src() method available */
|
||||
|
||||
*new_stream = NULL;
|
||||
stream = calloc(1, sizeof(IsoStream));
|
||||
if (stream == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
new_data = calloc(1, sizeof(FSrcStreamData));
|
||||
if (new_data == NULL) {
|
||||
free((char *) stream);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
*new_stream = stream;
|
||||
stream->class = old_stream->class;
|
||||
stream->refcount = 1;
|
||||
stream->data = new_data;
|
||||
|
||||
ret = data->src->class->clone_src(data->src, &(new_data->src), 0);
|
||||
if (ret < 0) {
|
||||
free((char *) stream);
|
||||
free((char *) new_data);
|
||||
return ret;
|
||||
}
|
||||
new_data->dev_id = data->dev_id;
|
||||
new_data->ino_id = data->ino_id;
|
||||
new_data->size = data->size;
|
||||
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
IsoStreamIface fsrc_stream_class = {
|
||||
1, /* update_size is defined for this stream */
|
||||
4, /* version */
|
||||
"fsrc",
|
||||
fsrc_open,
|
||||
fsrc_close,
|
||||
@ -167,7 +216,10 @@ IsoStreamIface fsrc_stream_class = {
|
||||
fsrc_is_repeatable,
|
||||
fsrc_get_id,
|
||||
fsrc_free,
|
||||
fsrc_update_size
|
||||
fsrc_update_size,
|
||||
fsrc_get_input_stream,
|
||||
NULL,
|
||||
fsrc_clone_stream
|
||||
};
|
||||
|
||||
int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream)
|
||||
@ -338,7 +390,7 @@ static
|
||||
int cut_out_read(IsoStream *stream, void *buf, size_t count)
|
||||
{
|
||||
struct cut_out_stream *data = stream->data;
|
||||
count = (size_t)MIN(data->size - data->pos, count);
|
||||
count = (size_t) MIN((size_t) (data->size - data->pos), count);
|
||||
if (count == 0) {
|
||||
return 0;
|
||||
}
|
||||
@ -375,11 +427,68 @@ void cut_out_free(IsoStream *stream)
|
||||
free(data);
|
||||
}
|
||||
|
||||
static
|
||||
int cut_out_update_size(IsoStream *stream)
|
||||
{
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
IsoStream* cut_out_get_input_stream(IsoStream *stream, int flag)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
int cut_out_clone_stream(IsoStream *old_stream, IsoStream **new_stream,
|
||||
int flag)
|
||||
{
|
||||
struct cut_out_stream *data, *new_data;
|
||||
IsoStream *stream;
|
||||
int ret;
|
||||
|
||||
if (flag)
|
||||
return ISO_STREAM_NO_CLONE; /* unknown option required */
|
||||
|
||||
data = (struct cut_out_stream *) old_stream->data;
|
||||
if (data->src->class->version < 2)
|
||||
return ISO_STREAM_NO_CLONE; /* No clone_src() method available */
|
||||
|
||||
*new_stream = NULL;
|
||||
stream = calloc(1, sizeof(IsoStream));
|
||||
if (stream == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
stream->refcount = 1;
|
||||
stream->class = old_stream->class;
|
||||
new_data = calloc(1, sizeof(struct cut_out_stream));
|
||||
if (new_data == NULL) {
|
||||
free((char *) stream);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
ret = data->src->class->clone_src(data->src, &(new_data->src), 0);
|
||||
if (ret < 0) {
|
||||
free((char *) stream);
|
||||
free((char *) new_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
new_data->dev_id = (dev_t) 0;
|
||||
new_data->ino_id = cut_out_serial_id++;
|
||||
new_data->offset = data->offset;
|
||||
new_data->size = data->size;
|
||||
new_data->pos = 0;
|
||||
|
||||
stream->data = new_data;
|
||||
*new_stream = stream;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO update cut out streams to deal with update_size(). Seems hard.
|
||||
*/
|
||||
static
|
||||
IsoStreamIface cut_out_stream_class = {
|
||||
0,
|
||||
4, /* version */
|
||||
"cout",
|
||||
cut_out_open,
|
||||
cut_out_close,
|
||||
@ -387,7 +496,12 @@ IsoStreamIface cut_out_stream_class = {
|
||||
cut_out_read,
|
||||
cut_out_is_repeatable,
|
||||
cut_out_get_id,
|
||||
cut_out_free
|
||||
cut_out_free,
|
||||
cut_out_update_size,
|
||||
cut_out_get_input_stream,
|
||||
NULL,
|
||||
cut_out_clone_stream
|
||||
|
||||
};
|
||||
|
||||
int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
|
||||
@ -517,7 +631,7 @@ int mem_read(IsoStream *stream, void *buf, size_t count)
|
||||
return ISO_FILE_NOT_OPENED;
|
||||
}
|
||||
|
||||
if (data->offset >= data->size) {
|
||||
if (data->offset >= (ssize_t) data->size) {
|
||||
return 0; /* EOF */
|
||||
}
|
||||
|
||||
@ -549,12 +663,69 @@ void mem_free(IsoStream *stream)
|
||||
{
|
||||
MemStreamData *data;
|
||||
data = (MemStreamData*)stream->data;
|
||||
free(data->buf);
|
||||
if (data->buf != NULL)
|
||||
free(data->buf);
|
||||
free(data);
|
||||
}
|
||||
|
||||
static
|
||||
int mem_update_size(IsoStream *stream)
|
||||
{
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
IsoStream* mem_get_input_stream(IsoStream *stream, int flag)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
int mem_clone_stream(IsoStream *old_stream, IsoStream **new_stream,
|
||||
int flag)
|
||||
{
|
||||
MemStreamData *data, *new_data;
|
||||
IsoStream *stream;
|
||||
uint8_t *new_buf = NULL;
|
||||
|
||||
if (flag)
|
||||
return ISO_STREAM_NO_CLONE; /* unknown option required */
|
||||
|
||||
*new_stream = NULL;
|
||||
stream = calloc(1, sizeof(IsoStream));
|
||||
if (stream == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
stream->refcount = 1;
|
||||
stream->class = old_stream->class;
|
||||
new_data = calloc(1, sizeof(MemStreamData));
|
||||
if (new_data == NULL) {
|
||||
free((char *) stream);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
data = (MemStreamData *) old_stream->data;
|
||||
if (data->size > 0) {
|
||||
new_buf = calloc(1, data->size);
|
||||
if (new_buf == NULL) {
|
||||
free((char *) stream);
|
||||
free((char *) new_data);
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
memcpy(new_buf, data->buf, data->size);
|
||||
}
|
||||
new_data->buf = new_buf;
|
||||
new_data->offset = -1;
|
||||
new_data->ino_id = mem_serial_id++;
|
||||
new_data->size = data->size;
|
||||
|
||||
stream->data = new_data;
|
||||
*new_stream = stream;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
IsoStreamIface mem_stream_class = {
|
||||
0,
|
||||
4, /* version */
|
||||
"mem ",
|
||||
mem_open,
|
||||
mem_close,
|
||||
@ -562,7 +733,12 @@ IsoStreamIface mem_stream_class = {
|
||||
mem_read,
|
||||
mem_is_repeatable,
|
||||
mem_get_id,
|
||||
mem_free
|
||||
mem_free,
|
||||
mem_update_size,
|
||||
mem_get_input_stream,
|
||||
NULL,
|
||||
mem_clone_stream
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@ -570,7 +746,7 @@ IsoStreamIface mem_stream_class = {
|
||||
* When the Stream refcount reach 0, the buffer is free(3).
|
||||
*
|
||||
* @return
|
||||
* 1 sucess, < 0 error
|
||||
* 1 success, < 0 error
|
||||
*/
|
||||
int iso_memory_stream_new(unsigned char *buf, size_t size, IsoStream **stream)
|
||||
{
|
||||
@ -669,7 +845,12 @@ void iso_stream_get_file_name(IsoStream *stream, char *name)
|
||||
if (!strncmp(type, "fsrc", 4)) {
|
||||
FSrcStreamData *data = stream->data;
|
||||
char *path = iso_file_source_get_path(data->src);
|
||||
strncpy(name, path, PATH_MAX);
|
||||
if (path == NULL) {
|
||||
name[0] = 0;
|
||||
return;
|
||||
}
|
||||
strncpy(name, path, PATH_MAX - 1);
|
||||
name[PATH_MAX - 1] = 0;
|
||||
free(path);
|
||||
} else if (!strncmp(type, "boot", 4)) {
|
||||
strcpy(name, "BOOT CATALOG");
|
||||
@ -682,17 +863,27 @@ void iso_stream_get_file_name(IsoStream *stream, char *name)
|
||||
}
|
||||
}
|
||||
|
||||
/* @param flag bit0= Obtain most fundamental stream */
|
||||
IsoStream *iso_stream_get_input_stream(IsoStream *stream, int flag)
|
||||
{
|
||||
IsoStreamIface* class;
|
||||
IsoStream *result = NULL, *next;
|
||||
|
||||
if (stream == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
class = stream->class;
|
||||
if (class->version < 2)
|
||||
return NULL;
|
||||
return class->get_input_stream(stream, 0);
|
||||
while (1) {
|
||||
class = stream->class;
|
||||
if (class->version < 2)
|
||||
return result;
|
||||
next = class->get_input_stream(stream, 0);
|
||||
if (next == NULL)
|
||||
return result;
|
||||
result = next;
|
||||
if (!(flag & 1))
|
||||
return result;
|
||||
stream = result;
|
||||
}
|
||||
}
|
||||
|
||||
char *iso_stream_get_source_path(IsoStream *stream, int flag)
|
||||
@ -725,12 +916,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;
|
||||
@ -739,6 +940,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)
|
||||
{
|
||||
@ -747,8 +1046,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
|
||||
@ -765,10 +1062,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);
|
||||
@ -824,14 +1183,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);
|
||||
}
|
||||
@ -875,14 +1226,15 @@ int iso_stream_read_buffer(IsoStream *stream, char *buf, size_t count,
|
||||
*/
|
||||
int iso_stream_make_md5(IsoStream *stream, char md5[16], int flag)
|
||||
{
|
||||
int res, is_open = 0;
|
||||
char buffer[2048];
|
||||
int ret, is_open = 0;
|
||||
char * buffer = NULL;
|
||||
void *ctx= NULL;
|
||||
off_t file_size;
|
||||
uint32_t b, nblocks;
|
||||
size_t got_bytes;
|
||||
IsoStream *input_stream;
|
||||
|
||||
LIBISO_ALLOC_MEM(buffer, char, 2048);
|
||||
if (flag & 1) {
|
||||
while(1) {
|
||||
input_stream = iso_stream_get_input_stream(stream, 0);
|
||||
@ -893,34 +1245,74 @@ int iso_stream_make_md5(IsoStream *stream, char md5[16], int flag)
|
||||
}
|
||||
|
||||
if (! iso_stream_is_repeatable(stream))
|
||||
return 0;
|
||||
res = iso_md5_start(&ctx);
|
||||
if (res < 0)
|
||||
return res;
|
||||
res = iso_stream_open(stream);
|
||||
if (res < 0)
|
||||
return 0;
|
||||
{ret = 0; goto ex;}
|
||||
ret = iso_md5_start(&ctx);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
ret = iso_stream_open(stream);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
is_open = 1;
|
||||
file_size = iso_stream_get_size(stream);
|
||||
nblocks = DIV_UP(file_size, 2048);
|
||||
for (b = 0; b < nblocks; ++b) {
|
||||
res = iso_stream_read_buffer(stream, buffer, 2048, &got_bytes);
|
||||
if (res < 0) {
|
||||
res = 0;
|
||||
ret = iso_stream_read_buffer(stream, buffer, 2048, &got_bytes);
|
||||
if (ret < 0) {
|
||||
ret = 0;
|
||||
goto ex;
|
||||
}
|
||||
/* Do not use got_bytes to stay closer to IsoFileSrc processing */
|
||||
if (file_size - b * 2048 > 2048)
|
||||
res = 2048;
|
||||
ret = 2048;
|
||||
else
|
||||
res = file_size - b * 2048;
|
||||
iso_md5_compute(ctx, buffer, res);
|
||||
ret = file_size - b * 2048;
|
||||
iso_md5_compute(ctx, buffer, ret);
|
||||
}
|
||||
res = 1;
|
||||
ret = 1;
|
||||
ex:;
|
||||
if (is_open)
|
||||
iso_stream_close(stream);
|
||||
if (ctx != NULL)
|
||||
iso_md5_end(&ctx, md5);
|
||||
return res;
|
||||
LIBISO_FREE_MEM(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* API */
|
||||
int iso_stream_clone(IsoStream *old_stream, IsoStream **new_stream, int flag)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (old_stream->class->version < 4)
|
||||
return ISO_STREAM_NO_CLONE;
|
||||
ret = old_stream->class->clone_stream(old_stream, new_stream, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iso_stream_clone_filter_common(IsoStream *old_stream,
|
||||
IsoStream **new_stream,
|
||||
IsoStream **new_input, int flag)
|
||||
{
|
||||
IsoStream *stream, *input_stream;
|
||||
int ret;
|
||||
|
||||
*new_stream = NULL;
|
||||
*new_input = NULL;
|
||||
input_stream = iso_stream_get_input_stream(old_stream, 0);
|
||||
if (input_stream == NULL)
|
||||
return ISO_STREAM_NO_CLONE;
|
||||
stream = calloc(1, sizeof(IsoStream));
|
||||
if (stream == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
ret = iso_stream_clone(input_stream, new_input, 0);
|
||||
if (ret < 0) {
|
||||
free((char *) stream);
|
||||
return ret;
|
||||
}
|
||||
stream->class = old_stream->class;
|
||||
stream->refcount = 1;
|
||||
stream->data = NULL;
|
||||
*new_stream = stream;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 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
|
||||
@ -15,6 +15,7 @@
|
||||
*/
|
||||
#include "fsource.h"
|
||||
|
||||
/* IMPORTANT: Any change must be reflected by fsrc_clone_stream */
|
||||
typedef struct
|
||||
{
|
||||
IsoFileSource *src;
|
||||
@ -28,7 +29,8 @@ typedef struct
|
||||
/**
|
||||
* Get an identifier for the file of the source, for debug purposes
|
||||
* @param name
|
||||
* Should provide at least PATH_MAX bytes
|
||||
* Must provide at least PATH_MAX bytes. If no PATH_MAX is defined
|
||||
* then assume PATH_MAX = Libisofs_default_path_maX from libisofs.h
|
||||
*/
|
||||
void iso_stream_get_file_name(IsoStream *stream, char *name);
|
||||
|
||||
@ -39,7 +41,7 @@ void iso_stream_get_file_name(IsoStream *stream, char *name);
|
||||
* take an extra ref.
|
||||
*
|
||||
* @return
|
||||
* 1 sucess, < 0 error
|
||||
* 1 success, < 0 error
|
||||
* Possible errors:
|
||||
*
|
||||
*/
|
||||
@ -50,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);
|
||||
@ -94,5 +96,29 @@ int iso_stream_read_buffer(IsoStream *stream, char *buf, size_t count,
|
||||
int iso_stream_make_md5(IsoStream *stream, char md5[16], int flag);
|
||||
|
||||
|
||||
/**
|
||||
* Create a clone of the input stream of old_stream and a roughly initialized
|
||||
* clone of old_stream which has the same class and refcount 1. Its data
|
||||
* pointer will be NULL and needs to be filled by an expert which knows how
|
||||
* to clone the data of old_stream.
|
||||
* @param old_stream The existing stream which is in process of cloning
|
||||
* @param new_stream Will return the uninitialized memory object which shall
|
||||
* later become the clone of old_stream.
|
||||
* @param new_input The clone of the input stream of old stream.
|
||||
* @param flag Submit 0 for now.
|
||||
* @return ISO_SUCCESS or an error code <0
|
||||
*/
|
||||
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,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Vreixo Formoso
|
||||
* Copyright (c) 2012 - 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
|
||||
@ -46,6 +47,11 @@ int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag);
|
||||
*/
|
||||
int iso_write_system_area(Ecma119Image *t, uint8_t *buf);
|
||||
|
||||
/**
|
||||
* Adjust t->tail_blocks to the eventual alignment needs of isohybrid booting.
|
||||
*/
|
||||
int iso_align_isohybrid(Ecma119Image *t, int flag);
|
||||
|
||||
|
||||
/**
|
||||
* Read the necessary ELF information from the first MIPS boot file.
|
||||
@ -58,4 +64,262 @@ int iso_read_mipsel_elf(Ecma119Image *t, int flag);
|
||||
*/
|
||||
int iso_compute_append_partitions(Ecma119Image *t, int flag);
|
||||
|
||||
|
||||
/* The parameter struct for production of a single MBR partition entry.
|
||||
See also the description of MBR in doc/boot_sectors.txt.
|
||||
No sorting by start sector and gap filling is done before the System Area
|
||||
gets written. But the entries may get assigned to a desired slot number
|
||||
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 and block_count of the previous entry.
|
||||
Empty requested entries will be represented as 16 bytes of 0.
|
||||
*/
|
||||
struct iso_mbr_partition_request {
|
||||
|
||||
/* Always given in blocks of 512 bytes */
|
||||
uint64_t start_block;
|
||||
|
||||
/* A block count of 0 means that the partition reaches up to the start of
|
||||
the next one.
|
||||
*/
|
||||
uint64_t block_count;
|
||||
|
||||
/* Partition type */
|
||||
uint8_t type_byte;
|
||||
|
||||
/* 0x80 = bootable */
|
||||
uint8_t status_byte;
|
||||
|
||||
/* If >= 1 && <= 4 : The partition slot number in MBR.
|
||||
If more than one partition desires the same slot, then an error
|
||||
ISO_BOOT_MBR_COLLISION occurs at registration time.
|
||||
Use iso_mbr_entry_slot_is_free() to detect this in advance.
|
||||
If desired_slot is 0, then the partition entry is put into the
|
||||
lowest MBR slot that is not occupied by an entry with desired_slot > 0
|
||||
or by an entry that was registered before this entry.
|
||||
*/
|
||||
int desired_slot;
|
||||
|
||||
};
|
||||
|
||||
/* 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(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(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);
|
||||
|
||||
/* Peek in advance whether a desired slot number is already occupied by a
|
||||
registered MBR entry.
|
||||
Parameter slot may be between 0 and 4. 0 always returns "free".
|
||||
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(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 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.
|
||||
If no such entry is requested, then it will be prepended automatically
|
||||
with name "Apple" and type "Apple_partition_map".
|
||||
The requested entries will get sorted and gaps will be filled by more
|
||||
entries.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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];
|
||||
};
|
||||
|
||||
/* 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(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(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
|
||||
in the same process, then one must wait until the output of
|
||||
gettimeofday(2) changes.
|
||||
It is advised to obtain them as late as possible, so that Ecma119Image *t
|
||||
can distinguish itself from other image production setups which might be
|
||||
run on other machines with the same process number at the same time.
|
||||
*/
|
||||
|
||||
/* 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_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.
|
||||
The list of entries is stored in Ecma119Image.gpt_req.
|
||||
The GPT header block at byte 0x200 will get produced automatically.
|
||||
The requested entries will get sorted and gaps will be filled by more
|
||||
entries. Overlapping partitions are allowed only if
|
||||
(Ecma119Image.gpt_req_flags & 1).
|
||||
The block_count will be truncated to the image size before the GPT backup.
|
||||
|
||||
The GPT entries will be stored after the Apple Partition Map, if such
|
||||
gets generated too. Both partition descriptions must fit into the 32 KiB
|
||||
of the ISO 9660 System Area.
|
||||
GPT can be combined with APM only if (Ecma119Image.apm_block_size > 512).
|
||||
Otherwise, block 1 of APM and GPT header block would collide.
|
||||
So Ecma119Image.apm_block_size is set automatically to 2048 if at least
|
||||
one GPT entry is requested. (One could try 1024 ...).
|
||||
*/
|
||||
struct iso_gpt_partition_request {
|
||||
|
||||
/* Always given in blocks of 512 bytes.
|
||||
*/
|
||||
uint64_t start_block;
|
||||
uint64_t block_count;
|
||||
|
||||
/* The registered GUID which defines the partition type */
|
||||
uint8_t type_guid[16];
|
||||
|
||||
/* An individual GUID which shall be unique to the partition.
|
||||
If the caller submits 0...0 then a (weak) random uuid will be generated.
|
||||
*/
|
||||
uint8_t partition_guid[16];
|
||||
|
||||
/* bit0= "System Partition" Do not alter,
|
||||
bit2= Legacy BIOS bootable (MBR partition type 0x80)
|
||||
bit60= read-only
|
||||
*/
|
||||
uint64_t flags;
|
||||
|
||||
/* Fill with text encoded as UTF-16LE.
|
||||
All 72 bytes get copied to the system area.
|
||||
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;
|
||||
};
|
||||
|
||||
/* 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(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(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]);
|
||||
|
||||
|
||||
/* Internal helper that will be used by system_area.c and make_isohybrid_mbr.c
|
||||
*/
|
||||
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]);
|
||||
|
||||
|
||||
/* Parameters of MBR patching for GRUB2
|
||||
Might later become variables in Ecma119Image
|
||||
*/
|
||||
#define Libisofs_grub2_mbr_patch_poS 0x1b0
|
||||
#define Libisofs_grub2_mbr_patch_offsT 4
|
||||
|
||||
/* Parameters of SUN Disk Label patching for GRUB2
|
||||
See API iso_image_set_sparc_core().
|
||||
*/
|
||||
#define Libisofs_grub2_sparc_patch_adr_poS 0x228
|
||||
#define Libisofs_grub2_sparc_patch_size_poS 0x230
|
||||
|
||||
|
||||
/* >>> It is unclear whether there is a use case for appended partitions
|
||||
inside the ISO filesystem range.
|
||||
# define Libisofs_appended_partitions_inlinE yes
|
||||
*/
|
||||
|
||||
#endif /* SYSTEM_AREA_H_ */
|
||||
|
810
libisofs/tree.c
810
libisofs/tree.c
File diff suppressed because it is too large
Load Diff
@ -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_*/
|
||||
|
925
libisofs/util.c
925
libisofs/util.c
File diff suppressed because it is too large
Load Diff
160
libisofs/util.h
160
libisofs/util.h
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2012 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
|
||||
@ -11,9 +11,22 @@
|
||||
#ifndef LIBISO_UTIL_H_
|
||||
#define LIBISO_UTIL_H_
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#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,9 +62,16 @@ int iso_init_locale(int flag);
|
||||
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
|
||||
*
|
||||
@ -81,13 +101,32 @@ int str2ascii(const char *icharset, const char *input, char **output);
|
||||
*/
|
||||
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 ouput 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.
|
||||
*
|
||||
* @param src
|
||||
* The identifier, in ASCII encoding.
|
||||
* @param relaxed
|
||||
* 0 only allow d-characters, 1 allow also lowe case chars,
|
||||
* 2 allow all characters
|
||||
*/
|
||||
char *iso_1_dirid(const char *src);
|
||||
char *iso_1_dirid(const char *src, int relaxed);
|
||||
|
||||
/**
|
||||
* Create a level 2 directory identifier.
|
||||
@ -117,8 +156,13 @@ char *iso_r_dirid(const char *src, int size, int relaxed);
|
||||
*
|
||||
* @param src
|
||||
* The identifier, in ASCII encoding.
|
||||
* @param relaxed
|
||||
* 0 only allow d-characters, 1 allow also lowe case chars,
|
||||
* 2 allow all characters
|
||||
* @param force_dots
|
||||
* If 1 then prepend empty extension by SEPARATOR1 = '.'
|
||||
*/
|
||||
char *iso_1_fileid(const char *src);
|
||||
char *iso_1_fileid(const char *src, int relaxed, int force_dots);
|
||||
|
||||
/**
|
||||
* Create a level 2 file identifier.
|
||||
@ -146,13 +190,15 @@ char *iso_r_fileid(const char *src, size_t len, int relaxed, int forcedot);
|
||||
|
||||
/**
|
||||
* Create a Joliet file identifier that consists of name and extension. The
|
||||
* combined name and extension length will not exceed 128 bytes, and the
|
||||
* name and extension will be separated (.). All characters consist of
|
||||
* 2 bytes and the resulting string is NULL-terminated by a 2-byte NULL.
|
||||
* combined name and extension length will normally not exceed 64 characters
|
||||
* (= 128 bytes). The name and the extension will be separated (.).
|
||||
* All characters consist of 2 bytes and the resulting string is
|
||||
* NULL-terminated by a 2-byte NULL.
|
||||
*
|
||||
* Note that version number and (;1) is not appended.
|
||||
* @param flag
|
||||
* bit0= no_force_dots
|
||||
* bit1= allow 103 characters rather than 64
|
||||
* @return
|
||||
* NULL if the original name and extension both are of length 0.
|
||||
*/
|
||||
@ -164,10 +210,12 @@ uint16_t *iso_j_file_id(const uint16_t *src, int flag);
|
||||
* and the name and extension will be separated (.). All characters consist of
|
||||
* 2 bytes and the resulting string is NULL-terminated by a 2-byte NULL.
|
||||
*
|
||||
* @param flag
|
||||
* bit1= allow 103 characters rather than 64
|
||||
* @return
|
||||
* NULL if the original name and extension both are of length 0.
|
||||
*/
|
||||
uint16_t *iso_j_dir_id(const uint16_t *src);
|
||||
uint16_t *iso_j_dir_id(const uint16_t *src, int flag);
|
||||
|
||||
/**
|
||||
* Like strlen, but for Joliet strings.
|
||||
@ -201,6 +249,12 @@ 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
|
||||
@ -213,6 +267,10 @@ void iso_lsb(uint8_t *buf, uint32_t num, int bytes);
|
||||
void iso_msb(uint8_t *buf, uint32_t num, int bytes);
|
||||
void iso_bb(uint8_t *buf, uint32_t num, int bytes);
|
||||
|
||||
/* An alternative to iso_lsb() which advances the write pointer
|
||||
*/
|
||||
int iso_lsb_to_buf(char **wpt, uint32_t value, int bytes, int flag);
|
||||
|
||||
uint32_t iso_read_lsb(const uint8_t *buf, int bytes);
|
||||
uint32_t iso_read_msb(const uint8_t *buf, int bytes);
|
||||
|
||||
@ -221,6 +279,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)
|
||||
*
|
||||
@ -346,6 +407,12 @@ size_t iso_rbtree_get_size(IsoRBTree *tree);
|
||||
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.
|
||||
*
|
||||
@ -492,6 +559,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 *)
|
||||
@ -505,13 +580,84 @@ int iso_util_tag_magic(int tag_type, char **tag_magic, int *len, int flag);
|
||||
*/
|
||||
int checksum_cx_xinfo_func(void *data, int flag);
|
||||
|
||||
/* The iso_node_xinfo_cloner function which gets associated to
|
||||
* checksum_cx_xinfo_func by iso_init() resp. iso_init_with_flag() via
|
||||
* iso_node_xinfo_make_clonable()
|
||||
*/
|
||||
int checksum_cx_xinfo_cloner(void *old_data, void **new_data, int flag);
|
||||
|
||||
|
||||
/* Function to identify and manage md5 sums of unspecified providence stored
|
||||
* directly in this xinfo. This is supposed to override any other recorded
|
||||
* MD5 of the node unless data get copied and checksummed during that copying.
|
||||
*/
|
||||
int checksum_md5_xinfo_func(void *data, int flag);
|
||||
|
||||
/* The iso_node_xinfo_cloner function which gets associated to
|
||||
* checksum_md5_xinfo_func by iso_init() resp. iso_init_with_flag() via
|
||||
* iso_node_xinfo_make_clonable()
|
||||
*/
|
||||
int checksum_md5_xinfo_cloner(void *old_data, void **new_data, 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_node_xinfo_make_clonable()
|
||||
*/
|
||||
int iso_hfsplus_xinfo_cloner(void *old_data, void **new_data, int flag);
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
void *iso_alloc_mem(size_t size, size_t count, int flag);
|
||||
|
||||
#define LIBISO_ALLOC_MEM(pt, typ, count) { \
|
||||
pt= (typ *) iso_alloc_mem(sizeof(typ), (size_t) (count), 0); \
|
||||
if(pt == NULL) { \
|
||||
ret= ISO_OUT_OF_MEM; goto ex; \
|
||||
} }
|
||||
|
||||
#define LIBISO_ALLOC_MEM_VOID(pt, typ, count) { \
|
||||
pt= (typ *) iso_alloc_mem(sizeof(typ), (size_t) (count), 0); \
|
||||
if(pt == NULL) { \
|
||||
goto ex; \
|
||||
} }
|
||||
|
||||
#define LIBISO_FREE_MEM(pt) { \
|
||||
if(pt != NULL) \
|
||||
free((char *) pt); \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@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 rathern 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);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/* To avoid the need to include more system header files */
|
||||
uint16_t iso_ntohs(uint16_t v);
|
||||
uint16_t iso_htons(uint16_t v);
|
||||
|
||||
|
||||
#endif /*LIBISO_UTIL_H_*/
|
||||
|
@ -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) {
|
||||
|
@ -164,7 +164,7 @@ int iso_rbtree_insert(IsoRBTree *tree, void *data, void **item)
|
||||
new = data;
|
||||
added = 1;
|
||||
} else {
|
||||
struct iso_rbnode head = { 0 }; /* False tree root */
|
||||
struct iso_rbnode head = { 0, {NULL, NULL}, 0 }; /* False tree root */
|
||||
|
||||
struct iso_rbnode *g, *t; /* Grandparent & parent */
|
||||
struct iso_rbnode *p, *q; /* Iterator & parent */
|
||||
@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user