Compare commits
304 Commits
release-1.
...
release-1.
Author | SHA1 | Date | |
---|---|---|---|
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
AUTHORS
1
AUTHORS
@ -1,3 +1,4 @@
|
|||||||
Vreixo Formoso
|
Vreixo Formoso
|
||||||
Mario Danic
|
Mario Danic
|
||||||
|
Vladimir Serbinenko
|
||||||
Thomas Schmitt
|
Thomas Schmitt
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
Vreixo Formoso <metalpain2002@yahoo.es>,
|
Vreixo Formoso <metalpain2002@yahoo.es>,
|
||||||
Mario Danic <mario.danic@gmail.com>,
|
Mario Danic <mario.danic@gmail.com>,
|
||||||
Thomas Schmitt <scdbackup@gmx.net>
|
Thomas Schmitt <scdbackup@gmx.net>
|
||||||
Copyright (C) 2007-2010 Vreixo Formoso, Mario Danic, Thomas Schmitt
|
Copyright (C) 2007-2011 Vreixo Formoso, Mario Danic, Thomas Schmitt
|
||||||
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
119
ChangeLog
119
ChangeLog
@ -1,6 +1,121 @@
|
|||||||
bzr branch lp:libisofs/for-libisoburn (to become libisofs-1.0.2.tar.gz)
|
libisofs-1.2.6.tar.gz Tue Jan 08 2013
|
||||||
===============================================================================
|
===============================================================================
|
||||||
- no novelties yet
|
* 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
|
libisofs-1.0.0.tar.gz Mon Jan 17 2011
|
||||||
===============================================================================
|
===============================================================================
|
||||||
|
13
Makefile.am
13
Makefile.am
@ -6,6 +6,7 @@ pkgconfigdir=$(LIBBURNIA_PKGCONFDIR)
|
|||||||
libincludedir=$(includedir)/libisofs
|
libincludedir=$(includedir)/libisofs
|
||||||
|
|
||||||
lib_LTLIBRARIES = libisofs/libisofs.la
|
lib_LTLIBRARIES = libisofs/libisofs.la
|
||||||
|
ACLOCAL_AMFLAGS = -I ./
|
||||||
|
|
||||||
## ========================================================================= ##
|
## ========================================================================= ##
|
||||||
|
|
||||||
@ -65,6 +66,11 @@ libisofs_libisofs_la_SOURCES = \
|
|||||||
libisofs/rockridge_read.c \
|
libisofs/rockridge_read.c \
|
||||||
libisofs/joliet.h \
|
libisofs/joliet.h \
|
||||||
libisofs/joliet.c \
|
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.h \
|
||||||
libisofs/eltorito.c \
|
libisofs/eltorito.c \
|
||||||
libisofs/system_area.h \
|
libisofs/system_area.h \
|
||||||
@ -219,6 +225,12 @@ demo_demo_SOURCES = demo/demo.c
|
|||||||
# test/mocked_fsrc.h \
|
# test/mocked_fsrc.h \
|
||||||
# test/mocked_fsrc.c
|
# 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)
|
## Build documentation (You need Doxygen for this to work)
|
||||||
@ -249,6 +261,7 @@ nodist_pkgconfig_DATA = \
|
|||||||
# ts A80114 : added aaip-os*
|
# ts A80114 : added aaip-os*
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
|
bootstrap \
|
||||||
libisofs-1.pc.in \
|
libisofs-1.pc.in \
|
||||||
version.h.in \
|
version.h.in \
|
||||||
doc/doxygen.conf.in \
|
doc/doxygen.conf.in \
|
||||||
|
6
README
6
README
@ -4,7 +4,10 @@
|
|||||||
|
|
||||||
Released under GPL (see COPYING file for details).
|
Released under GPL (see COPYING file for details).
|
||||||
|
|
||||||
Copyright (C) 2008 - 2010 Vreixo Formoso, Mario Danic, Thomas Schmitt
|
Copyright (C) 2008 - 2012 Vreixo Formoso,
|
||||||
|
Mario Danic,
|
||||||
|
Vladimir Serbinenko,
|
||||||
|
Thomas Schmitt
|
||||||
|
|
||||||
libisofs is part of the libburnia project (libburnia-project.org)
|
libisofs is part of the libburnia project (libburnia-project.org)
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
@ -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-libacl avoid use of ACL functions like acl_to_text()
|
||||||
--disable-xattr avoid use of xattr functions like listxattr()
|
--disable-xattr avoid use of xattr functions like listxattr()
|
||||||
--disable-zlib avoid use of zlib functions like compress2()
|
--disable-zlib avoid use of zlib functions like compress2()
|
||||||
|
--disable-libjte avoid use of libjte functions
|
||||||
|
|
||||||
See INSTALL file for general options of ./configure.
|
See INSTALL file for general options of ./configure.
|
||||||
|
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
#!/bin/sh -x
|
#!/bin/sh -x
|
||||||
|
|
||||||
aclocal
|
aclocal -I .
|
||||||
libtoolize --copy --force
|
libtoolize --copy --force
|
||||||
autoconf
|
autoconf
|
||||||
|
|
||||||
# ts A61101 : libburn is not prepared for config.h
|
|
||||||
# autoheader
|
|
||||||
|
|
||||||
automake --foreign --add-missing --copy --include-deps
|
automake --foreign --add-missing --copy --include-deps
|
||||||
|
31
configure.ac
31
configure.ac
@ -1,4 +1,4 @@
|
|||||||
AC_INIT([libisofs], [1.0.0], [http://libburnia-project.org])
|
AC_INIT([libisofs], [1.2.6], [http://libburnia-project.org])
|
||||||
AC_PREREQ([2.50])
|
AC_PREREQ([2.50])
|
||||||
dnl AC_CONFIG_HEADER([config.h])
|
dnl AC_CONFIG_HEADER([config.h])
|
||||||
|
|
||||||
@ -8,6 +8,7 @@ AC_CANONICAL_TARGET
|
|||||||
LIBBURNIA_SET_FLAGS
|
LIBBURNIA_SET_FLAGS
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE([subdir-objects])
|
AM_INIT_AUTOMAKE([subdir-objects])
|
||||||
|
AC_CONFIG_MACRO_DIR([./])
|
||||||
|
|
||||||
dnl
|
dnl
|
||||||
dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match
|
dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match
|
||||||
@ -39,8 +40,8 @@ dnl
|
|||||||
dnl If LIBISOFS_*_VERSION changes, be sure to change AC_INIT above to match.
|
dnl If LIBISOFS_*_VERSION changes, be sure to change AC_INIT above to match.
|
||||||
dnl
|
dnl
|
||||||
LIBISOFS_MAJOR_VERSION=1
|
LIBISOFS_MAJOR_VERSION=1
|
||||||
LIBISOFS_MINOR_VERSION=0
|
LIBISOFS_MINOR_VERSION=2
|
||||||
LIBISOFS_MICRO_VERSION=0
|
LIBISOFS_MICRO_VERSION=6
|
||||||
LIBISOFS_VERSION=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION.$LIBISOFS_MICRO_VERSION
|
LIBISOFS_VERSION=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION.$LIBISOFS_MICRO_VERSION
|
||||||
|
|
||||||
AC_SUBST(LIBISOFS_MAJOR_VERSION)
|
AC_SUBST(LIBISOFS_MAJOR_VERSION)
|
||||||
@ -50,10 +51,10 @@ AC_SUBST(LIBISOFS_VERSION)
|
|||||||
|
|
||||||
dnl Libtool versioning
|
dnl Libtool versioning
|
||||||
LT_RELEASE=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION
|
LT_RELEASE=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION
|
||||||
# 2011.01.16 development jump has not yet happened
|
# 2013.01.08 development jump has not yet happened
|
||||||
# SONAME = 44 - 38 = 6 . Library name = libisofs.6.38.0
|
# SONAME = 68 - 62 = 6 . Library name = libisofs.6.62.0
|
||||||
LT_CURRENT=44
|
LT_CURRENT=68
|
||||||
LT_AGE=38
|
LT_AGE=62
|
||||||
LT_REVISION=0
|
LT_REVISION=0
|
||||||
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
|
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
|
||||||
|
|
||||||
@ -139,7 +140,7 @@ if test x$enable_debug != xyes; then
|
|||||||
CFLAGS="-DNDEBUG $CFLAGS"
|
CFLAGS="-DNDEBUG $CFLAGS"
|
||||||
else
|
else
|
||||||
if test x$GCC = xyes; then
|
if test x$GCC = xyes; then
|
||||||
CFLAGS="-g -pedantic -Wall $CFLAGS"
|
CFLAGS="-g -pedantic -Wall -Wextra -Wno-unused-parameter $CFLAGS"
|
||||||
fi
|
fi
|
||||||
CFLAGS="-DDEBUG $CFLAGS"
|
CFLAGS="-DDEBUG $CFLAGS"
|
||||||
fi
|
fi
|
||||||
@ -159,14 +160,19 @@ LIBBURNIA_SET_PKGCONFIG
|
|||||||
dnl Add compiler-specific flags
|
dnl Add compiler-specific flags
|
||||||
|
|
||||||
AC_ARG_ENABLE(libacl,
|
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)
|
, enable_libacl=yes)
|
||||||
if test "x$enable_libacl" = xyes; then
|
if test "x$enable_libacl" = xyes; then
|
||||||
dnl Check whether there is libacl-devel and libacl-runtime.
|
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
|
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
|
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= )
|
has_acl_h_but_no_func=0
|
||||||
|
AC_CHECK_HEADER(sys/acl.h, AC_CHECK_LIB(acl, acl_to_text, , has_acl_h_but_no_libacl=1 ), LIBACL_DEF= )
|
||||||
|
if test "$has_acl_h_but_no_libacl" = 1
|
||||||
|
then
|
||||||
|
AC_CHECK_LIB(c, acl_to_text, X= , LIBACL_DEF= )
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
LIBACL_DEF=
|
LIBACL_DEF=
|
||||||
fi
|
fi
|
||||||
@ -182,6 +188,11 @@ dnl Check whether there is the header for Linux xattr.
|
|||||||
dnl If not, erase this macro which would enable use of listxattr and others
|
dnl If not, erase this macro which would enable use of listxattr and others
|
||||||
XATTR_DEF="-DLibisofs_with_aaip_xattR"
|
XATTR_DEF="-DLibisofs_with_aaip_xattR"
|
||||||
AC_CHECK_HEADER(attr/xattr.h, AC_CHECK_LIB(c, listxattr, X= , XATTR_DEF= ), XATTR_DEF= )
|
AC_CHECK_HEADER(attr/xattr.h, AC_CHECK_LIB(c, listxattr, X= , XATTR_DEF= ), XATTR_DEF= )
|
||||||
|
if test "x$XATTR_DEF" = x
|
||||||
|
then
|
||||||
|
XATTR_DEF="-DLibisofs_with_freebsd_extattR"
|
||||||
|
AC_CHECK_HEADER(sys/extattr.h, AC_CHECK_LIB(c, extattr_list_file, X=, XATTR_DEF= ), XATTR_DEF= )
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
XATTR_DEF=
|
XATTR_DEF=
|
||||||
fi
|
fi
|
||||||
|
27
demo/demo.c
27
demo/demo.c
@ -50,6 +50,7 @@ static char helptext[][80] = {
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
#ifndef PATH_MAX
|
#ifndef PATH_MAX
|
||||||
@ -372,7 +373,11 @@ int gesture_iso(int argc, char **argv)
|
|||||||
iso_write_opts_free(opts);
|
iso_write_opts_free(opts);
|
||||||
|
|
||||||
while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
|
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);
|
fclose(fp);
|
||||||
burn_src->free_data(burn_src);
|
burn_src->free_data(burn_src);
|
||||||
@ -537,7 +542,7 @@ int gesture_iso_read(int argc, char **argv)
|
|||||||
|
|
||||||
int gesture_iso_cat(int argc, char **argv)
|
int gesture_iso_cat(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int res;
|
int res, write_ret;
|
||||||
IsoFilesystem *fs;
|
IsoFilesystem *fs;
|
||||||
IsoFileSource *file;
|
IsoFileSource *file;
|
||||||
struct stat info;
|
struct stat info;
|
||||||
@ -596,7 +601,11 @@ int gesture_iso_cat(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
while ((res = iso_file_source_read(file, buf, 1024)) > 0) {
|
while ((res = iso_file_source_read(file, buf, 1024)) > 0) {
|
||||||
fwrite(buf, 1, res, stdout);
|
write_ret = fwrite(buf, 1, res, stdout);
|
||||||
|
if (write_ret < res) {
|
||||||
|
printf ("Cannot write block to stdout. errno= %d\n", errno);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
fprintf(stderr, "Error reading, err = %d\n", res);
|
fprintf(stderr, "Error reading, err = %d\n", res);
|
||||||
@ -700,7 +709,11 @@ int gesture_iso_modify(int argc, char **argv)
|
|||||||
iso_write_opts_free(opts);
|
iso_write_opts_free(opts);
|
||||||
|
|
||||||
while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
|
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);
|
fclose(fp);
|
||||||
burn_src->free_data(burn_src);
|
burn_src->free_data(burn_src);
|
||||||
@ -814,7 +827,11 @@ int gesture_iso_ms(int argc, char **argv)
|
|||||||
iso_write_opts_free(opts);
|
iso_write_opts_free(opts);
|
||||||
|
|
||||||
while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
|
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);
|
fclose(fp);
|
||||||
burn_src->free_data(burn_src);
|
burn_src->free_data(burn_src);
|
||||||
|
@ -15,9 +15,11 @@ specifications, some is just rumor which happens to work (maybe not even that).
|
|||||||
|
|
||||||
EL Torito CD booting, for PC-BIOS x86, PowerPC, (old) Mac, EFI.
|
EL Torito CD booting, for PC-BIOS x86, PowerPC, (old) Mac, EFI.
|
||||||
|
|
||||||
MBR, for PC-BIOS x86 from (pseudo-) hard disk
|
Master Boot Record (MBR), for PC-BIOS x86 from (pseudo-) hard disk
|
||||||
- SYSLINUX isohybrid MBR
|
|
||||||
- GRUB2 grub-mkrescue MBR.
|
Apple Partition Map (APM), for more modern Mac
|
||||||
|
|
||||||
|
GUID Partition Table (GPT), for EFI from (pseudo-) hard disk
|
||||||
|
|
||||||
MIPS Volume Header, for MIPS Big Endian, e.g. SGI Indigo2.
|
MIPS Volume Header, for MIPS Big Endian, e.g. SGI Indigo2.
|
||||||
|
|
||||||
@ -25,6 +27,16 @@ DEC Boot Block, for MIPS Little Endian , e.g. DECstation.
|
|||||||
|
|
||||||
SUN Disk Label and boot images, for SUN SPARC
|
SUN Disk Label and boot images, for SUN SPARC
|
||||||
|
|
||||||
|
PowerPC Reference Platform (PReP), for IBM PowerPC
|
||||||
|
|
||||||
|
Common Hardware Reference Platform (CHRP), for IBM PowerPC
|
||||||
|
|
||||||
|
Combinations of boot mechanisms:
|
||||||
|
- SYSLINUX isohybrid MBR
|
||||||
|
- SYSLINUX isohybrid for MBR, UEFI and x86-Mac
|
||||||
|
- GRUB2 grub-mkrescue MBR
|
||||||
|
>>> Mac and/or PowerPC bootable GRUB2 image with HFS+/FAT, APM,
|
||||||
|
EFI GPT partition, PreP MBR partition, mountable FAT partition
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -44,7 +56,13 @@ with arbitrary content. This prescription is obeyed by PC-BIOS systems only
|
|||||||
if the ISO 9660 image is presented on CD, DVD or BD media.
|
if the ISO 9660 image is presented on CD, DVD or BD media.
|
||||||
In this case the El Torito Boot record is the starting point of booting.
|
In this case the El Torito Boot record is the starting point of booting.
|
||||||
|
|
||||||
The Boot Record is a ECMA-119 Volume Descriptor which is eventually located
|
After the System Area, an ISO 9660 image usually has three distinct block
|
||||||
|
intervals for:
|
||||||
|
- Volume descriptors (Primary Volume Descriptor, Boot Record, Joliet, ...)
|
||||||
|
- Directory trees, tables, boot catalog, embedded partitions and filesystems.
|
||||||
|
- Data file content, including content of El Torito boot images.
|
||||||
|
|
||||||
|
The Boot Record is an ECMA-119 Volume Descriptor which is eventually located
|
||||||
at 2 kB block number 17 (decimal). Its content points to the location of the
|
at 2 kB block number 17 (decimal). Its content points to the location of the
|
||||||
Boot Catalog.
|
Boot Catalog.
|
||||||
The format is described in part by ECMA-119 8.2 "Boot Record" and further
|
The format is described in part by ECMA-119 8.2 "Boot Record" and further
|
||||||
@ -101,7 +119,7 @@ Defined by El Torito are:
|
|||||||
0 = "80x86" which is used for standard PCs with Intel x86 or compatible CPU
|
0 = "80x86" which is used for standard PCs with Intel x86 or compatible CPU
|
||||||
1 = "PowerPC" (possibly for IBM machines with PowerPC CPU)
|
1 = "PowerPC" (possibly for IBM machines with PowerPC CPU)
|
||||||
2 = "Mac" (possibly for Apple computers with MC68000 or PowerPC CPU)
|
2 = "Mac" (possibly for Apple computers with MC68000 or PowerPC CPU)
|
||||||
Further in use by GRUB2 is:
|
Further in use by GRUB2 and ISOLINUX is:
|
||||||
0xef = EFI, a competitor resp. successor to PC-BIOS, possibly in use with
|
0xef = EFI, a competitor resp. successor to PC-BIOS, possibly in use with
|
||||||
Intel ia64 Itanium and possibly with newer Apple machines.
|
Intel ia64 Itanium and possibly with newer Apple machines.
|
||||||
|
|
||||||
@ -248,7 +266,7 @@ Byte Range | Value | Meaning
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
MBR
|
Master Boot Record (MBR)
|
||||||
for PC-BIOS x86 from (pseudo-) hard disk
|
for PC-BIOS x86 from (pseudo-) hard disk
|
||||||
|
|
||||||
Sources:
|
Sources:
|
||||||
@ -343,92 +361,244 @@ See <libisofs/libisofs.h> for call iso_write_opts_set_part_offset()
|
|||||||
and http://libburnia-project.org/wiki/PartitionOffset for examples with
|
and http://libburnia-project.org/wiki/PartitionOffset for examples with
|
||||||
program xorriso.
|
program xorriso.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
Apple Partition Map (APM)
|
||||||
|
for Apple Macs introduced since 2000 and more computer-like than iPad
|
||||||
|
from CD and often from (pseudo-) hard disk
|
||||||
|
|
||||||
|
Sources:
|
||||||
|
http://mjg59.dreamwidth.org/11285.html
|
||||||
|
http://opensource.apple.com/source/IOStorageFamily/IOStorageFamily-116/IOApplePartitionScheme.h (typedef struct Block0)
|
||||||
|
http://www.informit.com/articles/article.aspx?p=376123&seqNum=3
|
||||||
|
syslinux-4.05/utils/isohybrid.c
|
||||||
|
Mail conversations with Vladimir Serbinenko.
|
||||||
|
|
||||||
|
|
||||||
|
APM has an adjustable block size. Because the ISO images shall always work
|
||||||
|
on optical media, and in order to make room for the header block of an
|
||||||
|
additional GPT, only block size 2048 is considered here.
|
||||||
|
The role of APM in the boot process is to guide the firmware to a
|
||||||
|
HFS+ filesystem.
|
||||||
|
|
||||||
|
Block0 of an APM begins at byte 0 of the medium. Thus it collides with MBR and
|
||||||
|
other boot sector formats. By lucky coincidence it is possible to compose
|
||||||
|
a mock-up of a Block0 which is acceptable to firmware which expects APM,
|
||||||
|
and is also harmless x86 machine code with no negative side effects.
|
||||||
|
So it is possible to combine APM with an especially prepared MBR.
|
||||||
|
|
||||||
|
The layout of a Block0 of an APM is:
|
||||||
|
|
||||||
|
Byte Range | Value | Meaning (all numbers are stored big endian)
|
||||||
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
0 - 1 | sig | Signature 0x45 = 'E' , 0x52 = 'R'
|
||||||
|
2 - 3 | block_size | 0x0800 = 2048
|
||||||
|
4 - 7 | block_count| Number of blocks covered by APM
|
||||||
|
| | Often some x86-harmless dummy. E.g. 0x9090 = 37008
|
||||||
|
| | or 0xeb02ffff = 3,942,842,367
|
||||||
|
8 - 9 | dev_type | obscure: "device type"
|
||||||
|
10 - 11 | dev_id | obscure: "device id"
|
||||||
|
12 - 15 | drv_data | obscure: "driver data"
|
||||||
|
16 - 17 | drv_count | obscure: "driver descriptor count"
|
||||||
|
18 - 81 | drv_map | obscure: "driver descriptor table"
|
||||||
|
| | with 8 entries of 16 bytes each
|
||||||
|
82 - 511 | reserved |
|
||||||
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
|
||||||
|
The SYSLINUX program isohybrid.c overwrites the first 32 bytes of this
|
||||||
|
layout by its dummy values. It uses the small block_count 0x00009090 and
|
||||||
|
sets all bytes up to 31 to 0.
|
||||||
|
The libisofs HFS+ extension by Vladimir Serbinenko overwrites only the
|
||||||
|
first 8 bytes. It uses the large block_count 0xeb02ffff.
|
||||||
|
|
||||||
|
Block0 and the following APM entries each occupy 1 block of the announced size.
|
||||||
|
|
||||||
|
The first APM entry describes the range from its own start to the end of the
|
||||||
|
last APM entry. Each of the other APM entries describes a partition.
|
||||||
|
|
||||||
|
The layout of an Apple partition map entry is:
|
||||||
|
|
||||||
|
Byte Range | Value | Meaning (all numbers are stored big endian)
|
||||||
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
0 - 1 | sig | Signature 0x50 = 'P' , 0x4d = 'M'
|
||||||
|
2 - 3 | reserved |
|
||||||
|
4 - 7 | map_entries| Number of partition entries.
|
||||||
|
| | All entries show the same number.
|
||||||
|
8 - 11 | start_block| "physical block start of partition"
|
||||||
|
12 - 15 | block_count| "physical block count of partition"
|
||||||
|
16 - 47 | name | Partition name
|
||||||
|
48 - 79 | type | Type string
|
||||||
|
80 - 83 | lb_start | Logical block start = 0
|
||||||
|
84 - 87 | lb_count | Logical block count (same as block_count)
|
||||||
|
88 - 91 | flags | Status flags
|
||||||
|
| | bit0= entry is valid
|
||||||
|
| | bit1= entry is allocated
|
||||||
|
| | bit4= partition is readable
|
||||||
|
| | bit5= partition is writable
|
||||||
|
| | bit30= automatic mount (legacy Mac)
|
||||||
|
92 - 95 | boot_block | Logical start block number of boot code = 0
|
||||||
|
96 - 99 | boot_bytes | Number of bytes in boot code = 0
|
||||||
|
100 - 119 | | More boot code stuff = 0
|
||||||
|
120 - 135 | processor | "processor type" = 0
|
||||||
|
136 - 511 | reserved |
|
||||||
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
|
||||||
|
For the first APM entry (byte 0x0800), the following values apply:
|
||||||
|
map_entries = number of APM entries, including itself. E.g. 4.
|
||||||
|
start_block = 1
|
||||||
|
block_count = map_entries
|
||||||
|
name = "Apple"
|
||||||
|
type = "Apple_partition_map"
|
||||||
|
flags = 3
|
||||||
|
|
||||||
|
libisofs uses APM to mark a HFS+ filesystem partition within an ISO 9660 image.
|
||||||
|
Usually the APM has 3 more entries after the first entry:
|
||||||
|
|
||||||
|
Entry 2 (byte 0x1000) describes the block interval from ISO image start to
|
||||||
|
the start of the HFS+ filesystem meta data.
|
||||||
|
start_block = 16
|
||||||
|
block_count = start_of_hfs - 16
|
||||||
|
name = "Gap0"
|
||||||
|
type = "ISO9660_data"
|
||||||
|
flags = 0x13
|
||||||
|
|
||||||
|
Entry 3 (byte 0x1800) describes the interval from the start of the HFS+ meta
|
||||||
|
data to the end of the HFS+ data at the end of its partition. This includes all
|
||||||
|
content blocks of the data files in the ISO image.
|
||||||
|
start_block = start_of_hfs
|
||||||
|
block_count = end_of_hfs - start_of_hfs
|
||||||
|
name = "HFSPLUS_Hybrid"
|
||||||
|
type = "Apple_HFS"
|
||||||
|
flags = 0x40000013
|
||||||
|
|
||||||
|
Entry 4 (byte 0x2000) describes the interval from the end of the HFS+
|
||||||
|
partition to the end of the ISO image. It is possible that this interval is
|
||||||
|
empty. In this case, no fourth APM entry will be written.
|
||||||
|
start_block = end_of_hfs
|
||||||
|
block_count = end_of_iso - end_of_hfs
|
||||||
|
name = "Gap1"
|
||||||
|
type = "ISO9660_data"
|
||||||
|
flags = 0x13
|
||||||
|
|
||||||
|
|
||||||
|
>>> Open questions:
|
||||||
|
>>> What HFS+ blessings are needed for booting ?
|
||||||
|
>>> What files need what HFS creator and type settings ?
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
SYSLINUX Isohybrid MBR
|
GUID Partition Table (GPT)
|
||||||
|
for alternative mountability paths
|
||||||
|
and for EFI booting of some Apple Macs from (pseudo-) hard disk
|
||||||
|
|
||||||
Sources:
|
Sources:
|
||||||
syslinux-3.72/utils/isohybrid , a perl script by H. Peter Anvin = hpa.
|
http://mjg59.dreamwidth.org/11285.html
|
||||||
Mailing list conversations with hpa.
|
http://mjg59.fedorapeople.org/Fedora-LiveCD.iso
|
||||||
|
http://en.wikipedia.org/wiki/GUID_Partition_Table
|
||||||
|
http://en.wikipedia.org/wiki/GUID
|
||||||
|
|
||||||
|
|
||||||
An isohybrid MBR directs the booting BIOS to an ISOLINUX boot image which
|
GPT is the partition map format of EFI, a successor of PC-BIOS.
|
||||||
is also the target of an El Torito boot catalog entry.
|
Block size is always 512. GPT consists of a header block at block address 1 and
|
||||||
For that purpose one has to take an MBR template and has to set a few bytes
|
a partition table near the start of the medium. This is called the primary GPT.
|
||||||
to values which sufficiently describe the ISO image and the boot image file.
|
There is a backup copy of header and table near the end of the medium.
|
||||||
|
|
||||||
Words are composed little-endian style.
|
GPT is particularly designed to co-exist with MBR. If it is present, then the
|
||||||
|
booting firmware may or may not prefer it over the MBR partition table.
|
||||||
|
GPT can co-exist with APM if APM block size is at least 1024. In this case,
|
||||||
|
the primary partition table will begin after the last APM entry block.
|
||||||
|
|
||||||
Byte Range | Value | Meaning
|
The header block format is:
|
||||||
|
Byte Range | Value | Meaning (little endian numbers, LBA unit is 512 byte)
|
||||||
---------- | ---------- | ----------------------------------------------------
|
---------- | ---------- | ----------------------------------------------------
|
||||||
0 - 431 | = opaque = | Syslinux machine code provided by MBR template
|
0 - 7 | sig | Signature "EFI PART" (with no trailing zero)
|
||||||
| |
|
8 - 11 | revision | Revision = {0x00, 0x00, 0x01, 0x00} meaning "1.0"
|
||||||
432 - 439 | hd_bootlba | Address of the ISOLINUX boot image file in the
|
12 - 15 | head_size | Header size = 0x5c = 92
|
||||||
| | ISO image. Counted in 512 byte blocks.
|
16 - 19 | head_crc | CRC-32 of this header while head_crc is 0
|
||||||
| |
|
20 - 23 | reserved | = 0
|
||||||
440 - 443 | mbr_id | Random number
|
24 - 31 | curr_lba | Location of this header block = 1
|
||||||
444 - 445 | 0 | Padding
|
32 - 39 | back_lba | Location of header backup block. See below.
|
||||||
| |
|
40 - 47 | first_lba | First usable LBA for partitions
|
||||||
446 - 509 | ========== | Partition table
|
48 - 55 | last_lba | Last usable LBA for partitions
|
||||||
| |
|
56 - 71 | guid | Disk GUID, Random
|
||||||
446 - 461 | part_entry | Partition table entry 1 describing ISO image size
|
72 - 79 | part_start | Partition entries start
|
||||||
| | starting at LBA 0. I.e. contrary to tradition.
|
| | Normally this is 2. But to co-exist with APM, it
|
||||||
| | See above for partition table entry format.
|
| might become some other number up to 62.
|
||||||
| |
|
80 - 83 | entry_count| Number of partition entries
|
||||||
462 - 509 | 0 | Unused partition entries 2 to 4
|
84 - 87 | entry_size | Size of a partition entry = 0x80 = 128
|
||||||
510 - 511 | 0xaa55 | MBR signature
|
88 - 91 | p_arr_crc | CRC-32 of the partition array
|
||||||
|
92 - 511 | reserved | Must be 0
|
||||||
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
|
||||||
|
The CRC-32 algorithm can be characterized as follows:
|
||||||
|
The generating polynomial has the bit representation 0x104c11db7.
|
||||||
|
The seed value for a bit shifting division algorithm is 0x46af6449. It is
|
||||||
|
chosen so that the CRC of 0 bytes of input is 0x00000000.
|
||||||
|
The least significant bits of input bytes get processed first. I.e. bit0 of
|
||||||
|
the last input byte gets mapped to x exp (7 + 32), bit7 of this byte gets
|
||||||
|
mapped to x exp (0 + 32).
|
||||||
|
The resulting division residue gets bitwise mirrored. E.g. bit0 becomes bit31,
|
||||||
|
bit1 becomes bit30, and so on. Further it gets exored with 0xffffffff.
|
||||||
|
|
||||||
|
A GUID consists of a 32-bit integer, two 16-bit integers, and an array of
|
||||||
|
8 bytes. The integers are to be stored big-endian.
|
||||||
|
A globally registered class of GUID are the partition type GUIDs.
|
||||||
|
This example uses two of them
|
||||||
|
Basic data partition: a2 a0 d0 eb , e5 b9 , 33 44 , 87 c0 68 b6 b7 26 99 c7
|
||||||
|
HFS+ partition : 00 53 46 48 , 00 00 , aa 11 , aa 11 00 30 65 43 ec ac
|
||||||
|
EFI System partition: 28 73 2a c1 , 1f f8 , d2 11 , ba 4b 00 a0 c9 3e c9 3b
|
||||||
|
Note that the wikipedia list shows the first 32-bit word and the next two
|
||||||
|
16-bit words in little-endia interpretation.
|
||||||
|
|
||||||
|
The partition table is an array of entries. Each has a size of 128 bytes.
|
||||||
|
A partition table entry looks like:
|
||||||
|
|
||||||
|
Byte Range | Value | Meaning (numbers are stored little endian)
|
||||||
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
0 - 15 | type_guid | Partition type GUID
|
||||||
|
16 - 31 | part_guid | Unique partition GUID, Random
|
||||||
|
32 - 39 | start_lba | First LBA
|
||||||
|
40 - 47 | end_lba | Last LBA (inclusive)
|
||||||
|
48 - 55 | flags | Attribute flags
|
||||||
|
| | bit0= "System Partition" Do not alter.
|
||||||
|
| | bit2= Legacy BIOS bootable (MBR partition type 0x80)
|
||||||
|
| | bit60= read-only
|
||||||
|
56 - 127 | name | Characters encoded as UTF-16LE. Padded by 0-bytes.
|
||||||
---------- | ---------- | ----------------------------------------------------
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
hpa about MBR templates and partition table filesystem types:
|
About header field "Location of header backup block":
|
||||||
|
|
||||||
"[MBR templates] are available in the Syslinux build tree under the names:
|
Near to the end of the image, after any data blocks which might be of interest
|
||||||
mbr/isohdp[fp]x*.bin
|
for the filesystems covered by GPT partitions, there is a backup of partition
|
||||||
The default probably should be mbr/isohdppx.bin, but it's ultimately up
|
table and header block.
|
||||||
to the user.
|
The header block is supposed to mark the end of the usable medium. But libisofs
|
||||||
[...]
|
may have the need to add more data.
|
||||||
Note: the filesystem type is largely arbitrary, in theory it can be any
|
The partition table is stored directly before the header block. So it will
|
||||||
value other than 0x00, 0x05, 0x0f, 0x85, 0xee, or 0xef. 0x17 ("Windows
|
normally not begin at a 2 KiB block start.
|
||||||
IFS Hidden") seems safeish, some people believe 0x83 (Linux) is better.
|
|
||||||
"
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
The content of the backup partition table is the same as the one of the
|
||||||
|
primary table.
|
||||||
|
The backup header differs from the primary header by
|
||||||
GRUB2 grub-mkrescue MBR
|
Byte Range | Value | Meaning (little endian numbers, LBA unit is 512 byte)
|
||||||
|
|
||||||
Sources:
|
|
||||||
Mailing list conversations with Vladimir Serbinenko.
|
|
||||||
|
|
||||||
|
|
||||||
The MBR file that is used with GRUB2 script grub-mkrescue needs only a
|
|
||||||
partition table entry which describes the image size.
|
|
||||||
|
|
||||||
Byte Range | Value | Meaning
|
|
||||||
---------- | ---------- | ----------------------------------------------------
|
---------- | ---------- | ----------------------------------------------------
|
||||||
0 - 445 | = opaque = | GRUB2 machine code provided by MBR template
|
16 - 19 | head_crc | CRC-32 of this header while head_crc is 0.
|
||||||
| |
|
| | Is recomputed after the following changes.
|
||||||
446 - 509 | ========== | Partition table
|
24 - 31 | curr_lba | Location of this header block.
|
||||||
| |
|
| | Shows own block address.
|
||||||
446 - 461 | part_entry | Partition table entry 1 describing ISO image size
|
32 - 39 | back_lba | Location of header backup block.
|
||||||
| | Peculiar is the start offset of 1 block.
|
| | Points to primary header block = 1
|
||||||
| | This prevents mounting of the partition.
|
72 - 79 | part_start | Partition entries start.
|
||||||
| | See above for partition table entry format.
|
| | Points to start of backup partition table.
|
||||||
| |
|
|
||||||
462 - 509 | 0 | Unused partition entries 2 to 4
|
|
||||||
510 - 511 | 0xaa55 | MBR signature
|
|
||||||
---------- | ---------- | ----------------------------------------------------
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
|
||||||
Vladimir Serbinenko about the partition table entry:
|
|
||||||
"Currently we use first and not last entry. You need to:
|
An EFI System partition usually contains the same data blocks as the El Torito
|
||||||
1) Zero-fill 446-510
|
boot image for EFI. It is used for booting some Macs from (pseudo-) hard disk.
|
||||||
2) Put 0x55, 0xAA into 510-512
|
|
||||||
3) Put 0x80 (for bootable partition), 0, 2, 0 (C/H/S of the start), 0xcd
|
|
||||||
(partition type), [3 bytes of C/H/S end], 0x01, 0x00, 0x00, 0x00 (LBA
|
|
||||||
start in little endian), [LBA end in little endian] at 446-462
|
|
||||||
"
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -715,6 +885,36 @@ Byte Range | Value | Meaning
|
|||||||
---------- | ---------- | ----------------------------------------------------
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
PowerPC Reference Platform (PReP)
|
||||||
|
for IBM PowerPC
|
||||||
|
|
||||||
|
Sources:
|
||||||
|
Mail conversations with Vladimir Serbinenko.
|
||||||
|
|
||||||
|
|
||||||
|
PReP boots via a MBR partition containing only raw ELF and having type 0x41.
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
Common Hardware Reference Platform (CHRP)
|
||||||
|
for IBM PowerPC
|
||||||
|
|
||||||
|
Sources:
|
||||||
|
Mail conversations with Vladimir Serbinenko.
|
||||||
|
|
||||||
|
|
||||||
|
CHRP is marked by an MBR partition entry of type 0x96 spanning the whole
|
||||||
|
ISO 9660 image.
|
||||||
|
|
||||||
|
PReP boot may be preferable. At least it can co-exist with other partitions
|
||||||
|
in the ISO image.
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
>>> ??? HP-PA
|
>>> ??? HP-PA
|
||||||
@ -723,5 +923,505 @@ Byte Range | Value | Meaning
|
|||||||
|
|
||||||
>>> ??? DEC Alpha
|
>>> ??? DEC Alpha
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Combinations of boot mechanisms
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
SYSLINUX Isohybrid MBR
|
||||||
|
|
||||||
|
Sources:
|
||||||
|
syslinux-3.72/utils/isohybrid , a perl script by H. Peter Anvin = hpa.
|
||||||
|
Mailing list conversations with hpa.
|
||||||
|
|
||||||
|
|
||||||
|
An isohybrid MBR directs the booting BIOS to an ISOLINUX boot image which
|
||||||
|
is also the target of an El Torito boot catalog entry.
|
||||||
|
For that purpose one has to take an MBR template and has to set a few bytes
|
||||||
|
to values which sufficiently describe the ISO image and the boot image file.
|
||||||
|
|
||||||
|
Words are composed little-endian style.
|
||||||
|
|
||||||
|
Byte Range | Value | Meaning
|
||||||
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
0 - 431 | = opaque = | Syslinux machine code provided by MBR template
|
||||||
|
| |
|
||||||
|
432 - 439 | hd_bootlba | Address of the ISOLINUX boot image file in the
|
||||||
|
| | ISO image. Counted in 512 byte blocks.
|
||||||
|
| |
|
||||||
|
440 - 443 | mbr_id | Random number
|
||||||
|
444 - 445 | 0 | Padding
|
||||||
|
| |
|
||||||
|
446 - 509 | ========== | Partition table
|
||||||
|
| |
|
||||||
|
446 - 461 | part_entry | Partition table entry 1 describing ISO image size
|
||||||
|
| | rounded up to the next full MiB. The partition starts
|
||||||
|
| | at LBA 0. (I.e. contrary to tradition.)
|
||||||
|
| | See above for partition table entry format.
|
||||||
|
| |
|
||||||
|
462 - 509 | 0 | Unused partition entries 2 to 4
|
||||||
|
510 - 511 | 0xaa55 | MBR signature
|
||||||
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
|
||||||
|
The ISO image file gets padded up to the next full MiB.
|
||||||
|
|
||||||
|
hpa about MBR templates and partition table filesystem types:
|
||||||
|
|
||||||
|
"[MBR templates] are available in the Syslinux build tree under the names:
|
||||||
|
mbr/isohdp[fp]x*.bin
|
||||||
|
The default probably should be mbr/isohdppx.bin, but it's ultimately up
|
||||||
|
to the user.
|
||||||
|
[...]
|
||||||
|
Note: the filesystem type is largely arbitrary, in theory it can be any
|
||||||
|
value other than 0x00, 0x05, 0x0f, 0x85, 0xee, or 0xef. 0x17 ("Windows
|
||||||
|
IFS Hidden") seems safeish, some people believe 0x83 (Linux) is better.
|
||||||
|
"
|
||||||
|
|
||||||
|
|
||||||
|
>>> SYSLINUX isohybrid for MBR, UEFI and x86-Mac
|
||||||
|
|
||||||
|
Sources:
|
||||||
|
http://mjg59.dreamwidth.org/11285.html
|
||||||
|
http://mjg59.fedorapeople.org/Fedora-LiveCD.iso
|
||||||
|
http://opensource.apple.com/source/IOStorageFamily/IOStorageFamily-116/IOApplePartitionScheme.h (typedef struct Block0)
|
||||||
|
http://www.informit.com/articles/article.aspx?p=376123&seqNum=3
|
||||||
|
http://en.wikipedia.org/wiki/GUID_Partition_Table
|
||||||
|
http://en.wikipedia.org/wiki/GUID
|
||||||
|
syslinux-4.05/utils/isohybrid.c
|
||||||
|
|
||||||
|
>>> Motivation: What systems will use the additional data ? amd64 UEFI ?
|
||||||
|
|
||||||
|
This is a very condensed format which exposes a lot of entry points for boot
|
||||||
|
firmware. It disobeys some of the prescriptions in the previous chapter.
|
||||||
|
|
||||||
|
Byte Range | Value | Meaning
|
||||||
|
-------------- | ---------- | -------------------------------------------------
|
||||||
|
0 - 511 | mbr | Isohybrid MBR pointing to x86 boot image file,
|
||||||
|
| | with three entries in its partition map.
|
||||||
|
| | It shares its first 32 bytes with apm_head.
|
||||||
|
0 - 31 | apm_head | Mock-up of the start of the first block of
|
||||||
|
| | an Apple Partition Map (APM).
|
||||||
|
446 - 461 | mbr_entry1 | Partition table entry 1 describing the size of
|
||||||
|
| | the ISO image plus the backup GPT, padded up to
|
||||||
|
| | the next full MiB.
|
||||||
|
462 - 477 | mbr_entry2 | Entry 2 describing the EFI VFAT boot image.
|
||||||
|
478 - 493 | mbr_entry3 | Entry 3 describing the HFS+ boot image.
|
||||||
|
| |
|
||||||
|
512 - 1023 | gpt_head | GPT header describing the GPT partition array.
|
||||||
|
1024 - 2047 | unused |
|
||||||
|
2048 - 4095 | apm_entry1 | APM entry 1 describing APM entries 1 to 3.
|
||||||
|
4096 - 6143 | apm_entry2 | APM entry 2 describing the EFI VFAT boot image.
|
||||||
|
6144 - 8195 | apm_entry3 | APM entry 3 describing the HFS+ boot image.
|
||||||
|
8192 - 8319 | gpt_entry1 | GPT partition entry 1 for the ISO image size.
|
||||||
|
8320 - 8447 | gpt_entry2 | GPT partition entry 2 for EFI VFAT boot image,
|
||||||
|
8448 - 8575 | gpt_entry3 | GPT partition entry 3 for the HFS+ boot image.
|
||||||
|
8576 - 24575 | gtp_empty | Empty GPT partition entries 4 to 128.
|
||||||
|
24576 - 32767 | unused |
|
||||||
|
32768 - 34815 | iso_pvd | ISO 9660 superblock
|
||||||
|
34816 - 36863 | el_torito | EL Torito boot block pointing to a boot catalog
|
||||||
|
| | with entries for the MBR boot image (platform id
|
||||||
|
| | 0x00), and for the two other boot images
|
||||||
|
| | (platform id 0xef)
|
||||||
|
-------------- | ---------- | -------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
For the purpose of booting, there may be two EFI boot image files in the
|
||||||
|
ISO image. A VFAT image and a HFS+ image. The content of both is not in the
|
||||||
|
scope of this document.
|
||||||
|
These boot images get announced by EL Torito boot catalog entries with
|
||||||
|
Platform Id 0xef.
|
||||||
|
|
||||||
|
|
||||||
|
Newer SYSLINUX MBR templates begin by 32 bytes of machine code which are
|
||||||
|
intentionally non-essential:
|
||||||
|
33 ed 90 90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||||
|
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||||
|
They may be overwritten by other bytes which must not produce errors or
|
||||||
|
undesirable side effects when executed as x86 machine code.
|
||||||
|
The following 32 bytes from block 0 of an Apple Partiton Map (APM) are such
|
||||||
|
harmless code. They stem from Fedora-LiveCD.iso by Matthew Garret:
|
||||||
|
45 52 08 00 00 00 90 90 00 00 00 00 00 00 00 00
|
||||||
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
They do not depend on any properties of the ISO image or the information
|
||||||
|
that is described in the following text.
|
||||||
|
|
||||||
|
The layout of Block0 is constant:
|
||||||
|
|
||||||
|
Byte Range | Value | Meaning (all numbers are stored big endian)
|
||||||
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
0 - 1 | sig | Signature 0x45 = 'E' , 0x52 = 'R'
|
||||||
|
2 - 3 | block_size | 0x0800 = 2048
|
||||||
|
4 - 7 | block_count| 0x9090 = 37008
|
||||||
|
8 - 9 | dev_type | obscure: "device type" = 0
|
||||||
|
10 - 11 | dev_id | obscure: "device id" = 0
|
||||||
|
12 - 15 | drv_data | obscure: "driver data" = 0
|
||||||
|
16 - 17 | drv_count | obscure: "driver descriptor count" = 0
|
||||||
|
18 - 81 | drv_map | obscure: "driver descriptor table"
|
||||||
|
| | with 8 entries of 16 bytes each
|
||||||
|
| | first 14 bytes are 0
|
||||||
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
|
||||||
|
The block_count of 0x9090 is pure fantasy. It shall only mark the disc as
|
||||||
|
not empty.
|
||||||
|
|
||||||
|
The data block ranges of the two EFI boot images get described by MBR
|
||||||
|
partition entries 2 and 3, which thus claim blocks inside of partition 1.
|
||||||
|
This partition nesting is acceptable to some EFI implementations only if the
|
||||||
|
type of partition 1 is 0x00.
|
||||||
|
|
||||||
|
The MBR partition entry number 1 is
|
||||||
|
80 00 01 00 00 3f a0 89 00 00 00 00 00 50 14 00
|
||||||
|
It marks the partition as bootable, starting at block 0, with a size that
|
||||||
|
is the smallest full MiB not smaller than the ISO image size + 18 KiB.
|
||||||
|
(The 18 KiB are needed for the GPT backup.)
|
||||||
|
The ISO image has a size of 332362 blocks of 2K = 1329448 * 512 = 649.14 MiB.
|
||||||
|
The partition size is 0x145000 = 1331200 * 512 = 650 MiB.
|
||||||
|
Start C/H/S = 0/0/1, type is 0x0 ("Empty"), end C/H/S is 649/63/32.
|
||||||
|
|
||||||
|
Partition 2:
|
||||||
|
00 fe ff ff ef fe ff ff a4 00 00 00 70 04 00 00
|
||||||
|
Start block is 0xa4 = 164 * 512 = 41 * 2048. The VFAT image file.
|
||||||
|
Partition size is 0x0470 = 1136 * 512. The size of that file.
|
||||||
|
Start C/H/S = 1023/254/63, type 0xef (fdisk says: "EFI (FAT-12/16/"),
|
||||||
|
end C/H/S = 1023/254/63.
|
||||||
|
|
||||||
|
Partition 3:
|
||||||
|
00 fe ff ff 00 fe ff ff 44 05 00 00 c0 08 00 00
|
||||||
|
Start block is 0x0544 = 1348 * 512 = 337 * 2048. The HFS+ image file.
|
||||||
|
Partition size is 0x08c0 = 2240 * 512. The size of that file.
|
||||||
|
Start C/H/S = 1023/254/63, type 0x00 ("Empty"), end C/H/S = 1023/254/63.
|
||||||
|
|
||||||
|
|
||||||
|
The second 512-block in the ISO image is the GPT header.
|
||||||
|
|
||||||
|
45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00
|
||||||
|
E F I P A R T
|
||||||
|
13 db 71 5d 00 00 00 00 01 00 00 00 00 00 00 00
|
||||||
|
fe 4f 14 00 00 00 00 00 30 00 00 00 00 00 00 00
|
||||||
|
de 4f 14 00 00 00 00 00 73 23 c8 79 19 e6 97 4d
|
||||||
|
95 17 69 30 c5 38 e2 99 10 00 00 00 00 00 00 00
|
||||||
|
80 00 00 00 80 00 00 00 5b 6b 8a 65
|
||||||
|
|
||||||
|
Byte Range | Value | Meaning (little endian numbers, LBA unit is 512 byte)
|
||||||
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
12 - 15 | head_size | Header size = 0x5c = 92
|
||||||
|
24 - 31 | curr_lba | Location of this header block = 0x1
|
||||||
|
32 - 39 | back_lba | Location of header backup block = 0x144ffe = 1331198
|
||||||
|
| | This is 1 KiB before the end of MBR partition 1
|
||||||
|
| | (but should be 512 bytes).
|
||||||
|
| | (Potential isohybrid.c bug #1:
|
||||||
|
| | Backup GPT is dislocated by 512 bytes.)
|
||||||
|
40 - 47 | first_lba | First usable LBA for partitions = 0x30 = 48
|
||||||
|
48 - 55 | last_lba | Last usable LBA for partitions = 0x144fde = 1331166
|
||||||
|
56 - 71 | guid | Disk GUID
|
||||||
|
| | Random, produced by uuid_generate(),
|
||||||
|
| | 32,16,16 byte swapped
|
||||||
|
72 - 79 | part_start | Partition entries start LBA = 0x10 = 16 = byte 0x2000
|
||||||
|
| | (This is unusual. It leaves room for the Apple
|
||||||
|
| | partition map entries.)
|
||||||
|
80 - 83 | entry_count| Number of partition entries 0x80 = 128
|
||||||
|
84 - 87 | entry_size | Size of a partition entry = 0x80 = 128
|
||||||
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
Because the block size was announced as 2048, the first Apple partition map
|
||||||
|
entry is located at byte 0x800 = 2048.
|
||||||
|
It describes the partition map itself:
|
||||||
|
50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 10
|
||||||
|
P M
|
||||||
|
41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
A p p l e
|
||||||
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f
|
||||||
|
A p p l e _ p a r t i t i o n _
|
||||||
|
6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
m a p
|
||||||
|
00 00 00 00 00 00 00 0a 00 00 00 03 00 00 00 00
|
||||||
|
|
||||||
|
|
||||||
|
Byte Range | Value | Meaning (all numbers are stored big endian)
|
||||||
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
4 - 7 | map_entries| "number of partition entries" = 3
|
||||||
|
8 - 11 | start_block| "physical block start of partition" = 1
|
||||||
|
12 - 15 | block_count| "physical block count of partition" = 16
|
||||||
|
| | (Potential isohybrid.c bug #2:
|
||||||
|
| | The value of 16 claims the ISO 9660 PVD as part of
|
||||||
|
| | the partition table. It should be 4 instead.)
|
||||||
|
16 - 47 | name | Partition name = "Apple"
|
||||||
|
48 - 79 | type | Type string = "Apple_partition_map"
|
||||||
|
80 - 83 | lb_start | Logical block start = 0
|
||||||
|
84 - 87 | lb_count | Logical block count = 10
|
||||||
|
88 - 91 | flags | Status flags = 3 (valid, allocated)
|
||||||
|
92 - 95 | boot_block | Logical start block number of boot code = 0
|
||||||
|
96 - 99 | boot_bytes | Number of bytes in boot code = 0
|
||||||
|
100 - 119 | | More boot code stuff = 0
|
||||||
|
120 - 135 | processor | "processor type" = 0
|
||||||
|
136 - 511 | reserved |
|
||||||
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
|
||||||
|
(Potential isohybrid.c bug #2:
|
||||||
|
Apple partition map entries bear the block count for blocks of 512 bytes
|
||||||
|
whereas Apple Block0 announces blocks of 2048 bytes.)
|
||||||
|
|
||||||
|
The next Apple partition map entry is at byte 0x1000 = 4096:
|
||||||
|
|
||||||
|
50 4d 00 00 00 00 00 03 00 00 00 29 00 00 04 70
|
||||||
|
45 46 49 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
E F I
|
||||||
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
41 70 70 6c 65 5f 48 46 53 00 00 00 00 00 00 00
|
||||||
|
A p p l e _ H F S
|
||||||
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
00 00 00 00 00 00 04 70 00 00 00 33 00 00 00 00
|
||||||
|
|
||||||
|
3 partitions, start block is 0x29 = 41,
|
||||||
|
block count is 0x0470 = 1136 (should be 284), name is "EFI",
|
||||||
|
type is "Apple_HFS" (although this is a FAT image),
|
||||||
|
logical block start = 0, lb_count = 1136 (should be 284),
|
||||||
|
flags = 0x33 : valid, allocated, readable, writable.
|
||||||
|
This points to file /isolinux/efiboot.img in the ISO image.
|
||||||
|
(Potential isohybrid.c bug #2:
|
||||||
|
Apple partition map entries bear the block count for blocks of 512 bytes
|
||||||
|
whereas Apple Block0 announces blocks of 2048 bytes.)
|
||||||
|
|
||||||
|
At byte 0x1800 = 6144, there is Apple partition map entry 3:
|
||||||
|
|
||||||
|
50 4d 00 00 00 00 00 03 00 00 01 51 00 00 08 c0
|
||||||
|
45 46 49 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
E F I
|
||||||
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
41 70 70 6c 65 5f 48 46 53 00 00 00 00 00 00 00
|
||||||
|
A p p l e _ H F S
|
||||||
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
00 00 00 00 00 00 08 c0 00 00 00 33 00 00 00 00
|
||||||
|
|
||||||
|
3 partitions, start block is 0x0151 = 337 (LBA of /isolinux/macboot.img),
|
||||||
|
block count = 0x08c0 = 2240 (should be 560), name is "EFI",
|
||||||
|
type is "Apple_HFS", logical block start = 0, lb_count = 2240 (should be 560),
|
||||||
|
flags = 0x33 : valid, allocated, readable, writable.
|
||||||
|
(Potential isohybrid.c bug #2:
|
||||||
|
Apple partition map entries bear the block count for blocks of 512 bytes
|
||||||
|
whereas Apple Block0 announces blocks of 2048 bytes.)
|
||||||
|
|
||||||
|
At byte 0x2000 = 8192 begins the GPT partition array.
|
||||||
|
It ends at byte 0x4000 = 16384.
|
||||||
|
|
||||||
|
a2 a0 d0 eb e5 b9 33 44 87 c0 68 b6 b7 26 99 c7
|
||||||
|
a1 87 a1 ba 4d 2c 27 45 ae 05 cf ab a6 fa 87 c1
|
||||||
|
00 00 00 00 00 00 00 00 28 49 14 00 00 00 00 00
|
||||||
|
00 00 00 00 00 00 00 00 49 53 4f 48 79 62 72 69
|
||||||
|
I S O H y b r i
|
||||||
|
64 20 49 53 4f 00 49 53 4f 48 79 62 72 69 64 00
|
||||||
|
d I S O I S O H y b r i d
|
||||||
|
41 70 70 6c 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
A p p l
|
||||||
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
|
||||||
|
Byte Range | Value | Meaning (numbers are stored little endian)
|
||||||
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
0 - 15 | type_guid | Partition type GUID = Basic data partition
|
||||||
|
| | Wikipedia: "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"
|
||||||
|
| | (Note: The first three words are shown byte swapped)
|
||||||
|
16 - 31 | part_guid | Unique partition GUID
|
||||||
|
| | Random, produced by uuid_generate()
|
||||||
|
| | 32,16,16 byte swapped
|
||||||
|
32 - 39 | start_lba | First LBA = 0
|
||||||
|
40 - 47 | end_lba | Last LBA (inclusive) = 0x144828 = 1329448
|
||||||
|
| | This is the ISO image size in blocks of 512.
|
||||||
|
| | (Potential isohybrid.c bug #3:
|
||||||
|
| | The end_lba in the first GPT entry should be 1 less
|
||||||
|
| | than the count of 512 byte blocks of the ISO image.)
|
||||||
|
48 - 55 | flags | Attribute flags = 0
|
||||||
|
56 - 127 | name | Wikipedia says UTF-16LE.
|
||||||
|
| | (Potential isohybrid.c bug #4:
|
||||||
|
| | The name in Fedora-LiveCD.iso is 8 bit and result
|
||||||
|
| | of faulty memory operation on a text constant.)
|
||||||
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
|
||||||
|
Next entry is at 0x2800 = 10240:
|
||||||
|
|
||||||
|
a2 a0 d0 eb e5 b9 33 44 87 c0 68 b6 b7 26 99 c7
|
||||||
|
c8 de c8 1f fb f0 51 40 8c 8a d2 f6 b1 46 16 dc
|
||||||
|
a4 00 00 00 00 00 00 00 13 05 00 00 00 00 00 00
|
||||||
|
00 00 00 00 00 00 00 00 49 53 4f 48 79 62 72 69
|
||||||
|
I S O H y b r i
|
||||||
|
64 00 41 70 70 6c 65 00 41 70 70 6c 00 00 00 00
|
||||||
|
d A p p l e A p p l
|
||||||
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
|
||||||
|
Partition type GUID : "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7" = Basic data
|
||||||
|
Start at block 0xa4 = 164 * 512 = 41 * 2048. The VFAT image file.
|
||||||
|
Last block is 0x0513 = 1299 = 164 + 1135. This end is correct.
|
||||||
|
(Potential isohybrid.c bug #4:
|
||||||
|
Wrong character set and incidential bytes in GPT partition name.)
|
||||||
|
|
||||||
|
Next entry at byte 0x02100 = 8448:
|
||||||
|
|
||||||
|
00 53 46 48 00 00 aa 11 aa 11 00 30 65 43 ec ac
|
||||||
|
c8 de c8 1f fb f0 51 40 8c 8a d2 f6 b1 46 16 dc
|
||||||
|
44 05 00 00 00 00 00 00 03 0e 00 00 00 00 00 00
|
||||||
|
00 00 00 00 00 00 00 00 49 53 4f 48 79 62 72 69
|
||||||
|
I S O H y b r i
|
||||||
|
64 00 41 70 70 6c 65 00 41 70 70 6c 00 00 00 00
|
||||||
|
d A p p l e A p p l
|
||||||
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
|
||||||
|
Partition type GUID : "48465300-0000-11AA-AA11-00306543ECAC" = HFS+
|
||||||
|
Start block is 0x0544 = 1348 * 512 = 337 * 2048. The HFS+ image file.
|
||||||
|
Last block is 0x0e03 = 3587 = 1348 + 2239. Correct.
|
||||||
|
(Potential isohybrid.c bug #4:
|
||||||
|
Wrong character set and incidential bytes in GPT partition name.)
|
||||||
|
|
||||||
|
The rest of the System Area is 0 up to the Primary Volume Descriptor
|
||||||
|
at block 16.
|
||||||
|
|
||||||
|
|
||||||
|
The ISO image file gets padded up to full MiB with sufficient room for the GPT
|
||||||
|
backup which is stored near the very end of the image file. There is need for
|
||||||
|
at least 16.5 KiB, which effectively occupy 18 KiB.
|
||||||
|
|
||||||
|
The backup partition array is stored 17 KiB before the end of MBR partition 1
|
||||||
|
resp. the image file.
|
||||||
|
(Potential isohybrid.c bug #1:
|
||||||
|
Wikipedia suggests "LBA -33" counted from end. This would be 16.5 KiB before
|
||||||
|
end.)
|
||||||
|
|
||||||
|
The GPT header is stored 1 KiB before the end of MBR partition 1.
|
||||||
|
(Potential isohybrid.c bug #1:
|
||||||
|
Wikipedia suggests "LBA -1" counted from end. This would be 512 bytes.)
|
||||||
|
|
||||||
|
45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00
|
||||||
|
E F I P A R T
|
||||||
|
f6 61 10 1c 00 00 00 00 fe 4f 14 00 00 00 00 00
|
||||||
|
01 00 00 00 00 00 00 00 30 00 00 00 00 00 00 00
|
||||||
|
de 4f 14 00 00 00 00 00 73 23 c8 79 19 e6 97 4d
|
||||||
|
95 17 69 30 c5 38 e2 99 de 4f 14 00 00 00 00 00
|
||||||
|
80 00 00 00 80 00 00 00 5b 6b 8a 65
|
||||||
|
|
||||||
|
It differs by its own CRC and by some of its parameters:
|
||||||
|
Own address is 0x144ffe. The backup lba is 0x01 = Primary GPT header.
|
||||||
|
Partition entries start is 0x144fde
|
||||||
|
(Potential isohybrid.c bug #1:
|
||||||
|
This overlaps with the last usable LBA. The backup GPT must move up by
|
||||||
|
512 bytes.)
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
GRUB2 grub-mkrescue MBR
|
||||||
|
|
||||||
|
Sources:
|
||||||
|
Mailing list conversations with Vladimir Serbinenko.
|
||||||
|
|
||||||
|
|
||||||
|
The MBR file that is used with GRUB2 script grub-mkrescue needs only a
|
||||||
|
partition table entry which describes the image size.
|
||||||
|
|
||||||
|
Byte Range | Value | Meaning
|
||||||
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
0 - 445 | = opaque = | GRUB2 machine code provided by MBR template
|
||||||
|
| |
|
||||||
|
446 - 509 | ========== | Partition table
|
||||||
|
| |
|
||||||
|
446 - 461 | part_entry | Partition table entry 1 describing ISO image size
|
||||||
|
| | Peculiar is the start offset of 1 block.
|
||||||
|
| | This prevents mounting of the partition.
|
||||||
|
| | See above for partition table entry format.
|
||||||
|
| |
|
||||||
|
462 - 509 | 0 | Unused partition entries 2 to 4
|
||||||
|
510 - 511 | 0xaa55 | MBR signature
|
||||||
|
---------- | ---------- | ----------------------------------------------------
|
||||||
|
|
||||||
|
Vladimir Serbinenko about the partition table entry:
|
||||||
|
"Currently we use first and not last entry. You need to:
|
||||||
|
1) Zero-fill 446-510
|
||||||
|
2) Put 0x55, 0xAA into 510-512
|
||||||
|
3) Put 0x80 (for bootable partition), 0, 2, 0 (C/H/S of the start), 0xcd
|
||||||
|
(partition type), [3 bytes of C/H/S end], 0x01, 0x00, 0x00, 0x00 (LBA
|
||||||
|
start in little endian), [LBA end in little endian] at 446-462
|
||||||
|
"
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
>>> Mac and/or PowerPC bootable GRUB2 image with HFS+/FAT, APM,
|
||||||
|
EFI GPT partition, PreP MBR partition, mountable FAT partition
|
||||||
|
|
||||||
|
>>> ? With PC-BIOS MBR x86 Code ?
|
||||||
|
|
||||||
|
This storage layout was mainly defined by Vladimir Serbinenko. It relies much
|
||||||
|
on the embedded HFS+/FAT filesystem for which he provided the code to libisofs.
|
||||||
|
|
||||||
|
Start Blocks (2 KiB):
|
||||||
|
0 System Area
|
||||||
|
16 Volume Descriptors
|
||||||
|
TREE ISO-RR tree, Joliet tree, other trees and meta data, except HFS+/FAT
|
||||||
|
EFI EFI boot image partition (optional)
|
||||||
|
PREP Prep image partition (optional)
|
||||||
|
HFAT HFS+/FAT metadata (optional)
|
||||||
|
DATA Data file content (including El Torito boot images)
|
||||||
|
HFSB HFS superblock backup (if HFS+/FAT metadata)
|
||||||
|
TAIL Further tails and paddings (optional)
|
||||||
|
GPTB GPT backup (if GPT in System Area)
|
||||||
|
END End of ISO image
|
||||||
|
|
||||||
|
System Area may contain simultaneously:
|
||||||
|
MBR (x86 boot code must leave room for 8 bytes mock-up of APM Block0)
|
||||||
|
APM
|
||||||
|
GPT
|
||||||
|
|
||||||
|
MBR Partitions:
|
||||||
|
0xee from 0 to PREP-1, protective partition, announcing presence of GPT
|
||||||
|
0x41 from PREP to HFAT-1, PreP partition
|
||||||
|
0x0c from HFAT to END-1, FAT partition, bootable bit on
|
||||||
|
0x00 Empty partition
|
||||||
|
|
||||||
|
GPT Partitions:
|
||||||
|
The primary GPT itself covers the System Area.
|
||||||
|
Basic Data from 16 to EFI-1, protects first part of ISO image
|
||||||
|
EFI System from EFI to PREP-1, offers EFI image for booting
|
||||||
|
Basic Data from PREP to HFAT-1, protects PreP partition
|
||||||
|
HFS+ from HFAT to TAIL-1, offers HFS+ for mounting
|
||||||
|
Basic Data from TAIL to GPTB-1, protects rest of ISO image (if there is)
|
||||||
|
|
||||||
|
APM Partitions:
|
||||||
|
The range from end of APM to end of System Area stays unprotected.
|
||||||
|
(The primary GPT might sit there.)
|
||||||
|
Apple_partition_map from 1 to 3 or 4, covers the APM itself
|
||||||
|
ISO9660_data from 16 to HFAT-1, covers first part of ISO image
|
||||||
|
Apple_HFS from HFAT to GPTB-1, offers HFS+ for boot and mount
|
||||||
|
ISO9660_data from GPTB to END-1, covers rest of ISO image
|
||||||
|
(might be omitted if empty)
|
||||||
|
|
||||||
|
El Torito:
|
||||||
|
Boot image for 80x86 PC-BIOS
|
||||||
|
Boot image for EFI (usually the same file as the partition EFI to PREP-1).
|
||||||
|
|
||||||
|
If optional components are not present, then their addresses coincide with
|
||||||
|
the address of the next component that is present. E.g. HFAT == DATA if no
|
||||||
|
HFS+/FAT filesystem is present.
|
||||||
|
If no FAT filesystem is present within HFS+/FAT, then the type of the last
|
||||||
|
partition is 0xcd.
|
||||||
|
If neither EFI, nor PreP, nor FAT within HFS+/FAT, are present, then there
|
||||||
|
is only one partition. It has type 0xee, if GPT is present in the System Area.
|
||||||
|
It has type 0xcd and offset 1*512, if no GPT is present.
|
||||||
|
|
||||||
|
Involved -as mkisofs options:
|
||||||
|
-hfsplus
|
||||||
|
-fat
|
||||||
|
-efi-boot-part DISKFILE
|
||||||
|
-prep-boot-part DISKFILE
|
||||||
|
|
||||||
|
|
||||||
|
>>> What boots by what ?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -1143,7 +1143,8 @@ HIDE_UNDOC_RELATIONS = YES
|
|||||||
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
|
# 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 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
|
# 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
|
# 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.
|
||||||
|
|
@ -157,9 +157,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.
|
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
|
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
|
The reserved start bytes of names have the following meaning
|
||||||
0x01 escape reserved character at start of name
|
0x01 escape reserved character at start of name
|
||||||
|
@ -22,6 +22,8 @@ Purpose:
|
|||||||
END is also the block address of the start of the checksum recording
|
END is also the block address of the start of the checksum recording
|
||||||
area in the image.
|
area in the image.
|
||||||
See also isofs.cx .
|
See also isofs.cx .
|
||||||
|
This attribute shall eventually be attached to the root directory entry
|
||||||
|
and be global for the whole image.
|
||||||
|
|
||||||
Format of Value:
|
Format of Value:
|
||||||
START_LEN | START_BYTES | END_LEN | END_BYTES |
|
START_LEN | START_BYTES | END_LEN | END_BYTES |
|
||||||
@ -121,6 +123,55 @@ Registered:
|
|||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Name:
|
||||||
|
isofs.hb
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
Records the IsoHfsplusBlessings blessing of a IsoNode as defined
|
||||||
|
in libisofs.h. At image load time, this info shall 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 shall 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:
|
Name:
|
||||||
isofs.st
|
isofs.st
|
||||||
|
|
||||||
@ -150,7 +201,7 @@ Registered:
|
|||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
This text is under
|
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
|
It shall only be modified in sync with libisofs and other software which
|
||||||
makes use of AAIP. Please mail change requests to mailing list
|
makes use of AAIP. Please mail change requests to mailing list
|
||||||
<libburn-hackers@pykix.org> or to the copyright holder in private.
|
<libburn-hackers@pykix.org> or to the copyright holder in private.
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
To be included by aaip_0_2.c
|
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>
|
#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. 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)
|
||||||
|
{
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------ Getters --------------------------------- */
|
/* ------------------------------ Getters --------------------------------- */
|
||||||
|
|
||||||
/* Obtain the ACL of the given file in long text form.
|
/* 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;
|
continue;
|
||||||
}
|
}
|
||||||
/* Extended Attribute */
|
/* Extended Attribute */
|
||||||
if(!(flag & 4))
|
if(flag & 4)
|
||||||
return(-6);
|
continue;
|
||||||
|
if(!(flag & 8))
|
||||||
|
if(strncmp(names[i], "user.", 5))
|
||||||
|
continue;
|
||||||
|
return(-6);
|
||||||
}
|
}
|
||||||
if(flag & 2)
|
if(flag & 2)
|
||||||
return(-6);
|
return(-6);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
To be included by aaip_0_2.c
|
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+
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -24,15 +24,51 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <errno.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
|
#ifdef Libisofs_with_aaip_acL
|
||||||
#include <sys/acl.h>
|
#include <sys/acl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef Libisofs_with_freebsd_extattR
|
||||||
|
#include <sys/extattr.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* <<< 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. 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_freebsd_extattR
|
||||||
|
if(flag & 2)
|
||||||
|
ret|= 2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------ Getters --------------------------------- */
|
/* ------------------------------ Getters --------------------------------- */
|
||||||
|
|
||||||
@ -137,6 +173,349 @@ 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)
|
||||||
|
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, acl_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;
|
||||||
|
#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++;
|
||||||
|
acl_names= 1;
|
||||||
|
}
|
||||||
|
#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
|
/* Obtain the Extended Attributes and/or the ACLs of the given file in a form
|
||||||
that is ready for aaip_encode().
|
that is ready for aaip_encode().
|
||||||
|
|
||||||
@ -152,20 +531,28 @@ int aaip_get_acl_text(char *path, char **text, int flag)
|
|||||||
bit0= obtain ACL (access and eventually default)
|
bit0= obtain ACL (access and eventually default)
|
||||||
bit1= use numeric ACL qualifiers rather than names
|
bit1= use numeric ACL qualifiers rather than names
|
||||||
bit2= do not encode attributes other than ACL
|
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
|
bit4= do not return trivial ACL that matches st_mode
|
||||||
bit15= free memory of names, value_lengths, values
|
bit15= free memory of names, value_lengths, values
|
||||||
@return >0 ok
|
@return >0 ok
|
||||||
<=0 error
|
<=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,
|
int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
||||||
size_t **value_lengths, char ***values, int flag)
|
size_t **value_lengths, char ***values, int flag)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
ssize_t i, num_names;
|
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;
|
char *acl_text= NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
if(flag & (1 << 15)) { /* Free memory */
|
if(flag & (1 << 15)) { /* Free memory */
|
||||||
{ret= 1; goto ex;}
|
{ret= 1; goto ex;}
|
||||||
@ -211,25 +598,26 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
|||||||
(*names)[*num_attrs]= strdup("");
|
(*names)[*num_attrs]= strdup("");
|
||||||
if((*names)[*num_attrs] == NULL)
|
if((*names)[*num_attrs] == NULL)
|
||||||
{ret= -1; goto ex;}
|
{ret= -1; goto ex;}
|
||||||
(*values)[*num_attrs]= (char *) acl;
|
(*values)[*num_attrs]= (char *) a_acl;
|
||||||
(*value_lengths)[*num_attrs]= acl_len;
|
a_acl= NULL;
|
||||||
|
(*value_lengths)[*num_attrs]= a_acl_len;
|
||||||
(*num_attrs)++;
|
(*num_attrs)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* Libisofs_with_aaip_acL */
|
#endif /* ! Libisofs_with_aaip_acL */
|
||||||
|
|
||||||
ret= 1;
|
ret= 1;
|
||||||
ex:;
|
ex:;
|
||||||
|
#ifdef Libisofs_with_aaip_acL
|
||||||
if(a_acl != NULL)
|
if(a_acl != NULL)
|
||||||
free(a_acl);
|
free(a_acl);
|
||||||
if(d_acl != NULL)
|
|
||||||
free(d_acl);
|
|
||||||
if(acl_text != NULL)
|
if(acl_text != NULL)
|
||||||
aaip_get_acl_text("", &acl_text, 1 << 15); /* free */
|
aaip_get_acl_text("", &acl_text, 1 << 15); /* free */
|
||||||
|
#endif /* Libisofs_with_aaip_acL */
|
||||||
|
|
||||||
if(ret <= 0 || (flag & (1 << 15))) {
|
if(ret <= 0 || (flag & (1 << 15))) {
|
||||||
if(*names != NULL) {
|
if(*names != NULL) {
|
||||||
for(i= 0; i < *num_attrs; i++)
|
for(i= 0; i < (ssize_t) *num_attrs; i++)
|
||||||
free((*names)[i]);
|
free((*names)[i]);
|
||||||
free(*names);
|
free(*names);
|
||||||
}
|
}
|
||||||
@ -238,18 +626,18 @@ ex:;
|
|||||||
free(*value_lengths);
|
free(*value_lengths);
|
||||||
*value_lengths= NULL;
|
*value_lengths= NULL;
|
||||||
if(*values != 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)[i]);
|
||||||
free(*values);
|
free(*values);
|
||||||
}
|
}
|
||||||
if(acl != NULL)
|
|
||||||
free(acl);
|
|
||||||
*values= NULL;
|
*values= NULL;
|
||||||
*num_attrs= 0;
|
*num_attrs= 0;
|
||||||
}
|
}
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* Libisofs_old_freebsd_acl_adapteR */
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------ Setters --------------------------------- */
|
/* ------------------------------ Setters --------------------------------- */
|
||||||
|
|
||||||
@ -259,9 +647,14 @@ ex:;
|
|||||||
@param text The input text (0 terminated, ACL long text form)
|
@param text The input text (0 terminated, ACL long text form)
|
||||||
@param flag Bitfield for control purposes
|
@param flag Bitfield for control purposes
|
||||||
bit0= set default ACL rather than access ACL
|
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
|
@return > 0 ok
|
||||||
|
0 no suitable ACL manipulation adapter available
|
||||||
-1 failure of system ACL service (see errno)
|
-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 resp. with no suitable link target
|
||||||
*/
|
*/
|
||||||
int aaip_set_acl_text(char *path, char *text, int flag)
|
int aaip_set_acl_text(char *path, char *text, int flag)
|
||||||
{
|
{
|
||||||
@ -302,13 +695,200 @@ ex:
|
|||||||
|
|
||||||
#else /* Libisofs_with_aaip_acL */
|
#else /* Libisofs_with_aaip_acL */
|
||||||
|
|
||||||
return(-2);
|
return(0);
|
||||||
|
|
||||||
#endif /* ! Libisofs_with_aaip_acL */
|
#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.
|
/* 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.
|
Note: There are no Extended Attributes in FreeBSD. So only ACL get set.
|
||||||
@ -317,6 +897,9 @@ ex:
|
|||||||
bit0= decode and set ACLs
|
bit0= decode and set ACLs
|
||||||
( bit1= first clear all existing attributes of the file )
|
( bit1= first clear all existing attributes of the file )
|
||||||
( bit2= do not set attributes other than ACLs )
|
( 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
|
@return 1 success
|
||||||
-1 error memory allocation
|
-1 error memory allocation
|
||||||
-2 error with decoding of ACL
|
-2 error with decoding of ACL
|
||||||
@ -338,6 +921,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||||||
continue;
|
continue;
|
||||||
if(names[i][0] == 0) { /* Decode ACLs */
|
if(names[i][0] == 0) { /* Decode ACLs */
|
||||||
/* access ACL */
|
/* access ACL */
|
||||||
|
if(!(flag & 1))
|
||||||
|
continue;
|
||||||
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
||||||
&consumed, NULL, 0, &acl_text_fill, 1);
|
&consumed, NULL, 0, &acl_text_fill, 1);
|
||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
@ -379,8 +964,14 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
{ret= -3; goto ex;}
|
{ret= -3; goto ex;}
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
|
if(flag & 4)
|
||||||
|
continue;
|
||||||
|
if(!(flag & 8))
|
||||||
|
if(strncmp(names[i], "user.", 5))
|
||||||
|
continue;
|
||||||
was_xattr= 1;
|
was_xattr= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ret= 1;
|
ret= 1;
|
||||||
if(was_xattr)
|
if(was_xattr)
|
||||||
@ -393,4 +984,5 @@ ex:;
|
|||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* Libisofs_old_freebsd_acl_adapteR */
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
To be included by aaip_0_2.c
|
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+
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -34,6 +34,40 @@
|
|||||||
#endif
|
#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 --------------------------------- */
|
/* ------------------------------ Getters --------------------------------- */
|
||||||
|
|
||||||
/* Obtain the ACL of the given file in long text form.
|
/* Obtain the ACL of the given file in long text form.
|
||||||
@ -144,21 +178,24 @@ int aaip_get_acl_text(char *path, char **text, int flag)
|
|||||||
bit15= free memory of names, value_lengths, values
|
bit15= free memory of names, value_lengths, values
|
||||||
@return >0 ok
|
@return >0 ok
|
||||||
<=0 error
|
<=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,
|
int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
||||||
size_t **value_lengths, char ***values, int flag)
|
size_t **value_lengths, char ***values, int flag)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char *list= NULL;
|
ssize_t i, num_names= 0;
|
||||||
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
|
#ifdef Libisofs_with_aaip_acL
|
||||||
|
unsigned char *acl= NULL;
|
||||||
|
char *a_acl_text= NULL, *d_acl_text= NULL;
|
||||||
size_t acl_len= 0;
|
size_t acl_len= 0;
|
||||||
#endif
|
#endif
|
||||||
#ifdef Libisofs_with_aaip_xattR
|
#ifdef Libisofs_with_aaip_xattR
|
||||||
ssize_t value_ret, retry= 0;
|
char *list= NULL;
|
||||||
|
ssize_t value_ret, retry= 0, list_size= 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(flag & (1 << 15)) { /* Free memory */
|
if(flag & (1 << 15)) { /* Free memory */
|
||||||
@ -171,39 +208,42 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
|||||||
*values= NULL;
|
*values= NULL;
|
||||||
|
|
||||||
/* Set up arrays */
|
/* Set up arrays */
|
||||||
if(!(flag & 4)) { /* Get xattr names */
|
|
||||||
|
|
||||||
#ifdef Libisofs_with_aaip_xattR
|
#ifdef Libisofs_with_aaip_xattR
|
||||||
|
|
||||||
|
if(!(flag & 4)) { /* Get xattr names */
|
||||||
if(flag & 32)
|
if(flag & 32)
|
||||||
list_size= listxattr(path, list, 0);
|
list_size= listxattr(path, list, 0);
|
||||||
else
|
else
|
||||||
list_size= llistxattr(path, list, 0);
|
list_size= llistxattr(path, list, 0);
|
||||||
if(list_size == -1)
|
if(list_size == -1) {
|
||||||
{ret= -1; goto ex;}
|
if(errno == ENOSYS) /* Function not implemented */
|
||||||
list= calloc(list_size, 1);
|
list_size= 0; /* Handle as if xattr was disabled at compile time */
|
||||||
if(list == NULL)
|
else
|
||||||
{ret= -1; goto ex;}
|
{ret= -1; goto ex;}
|
||||||
if(flag & 32)
|
}
|
||||||
list_size= listxattr(path, list, list_size);
|
if(list_size > 0) {
|
||||||
else
|
list= calloc(list_size, 1);
|
||||||
list_size= llistxattr(path, list, list_size);
|
if(list == NULL)
|
||||||
if(list_size == -1)
|
{ret= -1; goto ex;}
|
||||||
{ret= -1; goto ex;}
|
if(flag & 32)
|
||||||
|
list_size= listxattr(path, list, list_size);
|
||||||
#else /* Libisofs_with_aaip_xattR */
|
else
|
||||||
|
list_size= llistxattr(path, list, list_size);
|
||||||
list= strdup("");
|
if(list_size == -1)
|
||||||
|
{ret= -1; goto ex;}
|
||||||
#endif /* ! Libisofs_with_aaip_xattR */
|
}
|
||||||
|
|
||||||
for(i= 0; i < list_size; i+= strlen(list + i) + 1)
|
for(i= 0; i < list_size; i+= strlen(list + i) + 1)
|
||||||
num_names++;
|
num_names++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* ! Libisofs_with_aaip_xattR */
|
||||||
|
|
||||||
#ifdef Libisofs_with_aaip_acL
|
#ifdef Libisofs_with_aaip_acL
|
||||||
|
|
||||||
if(flag & 1)
|
if(flag & 1)
|
||||||
num_names++;
|
num_names++;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(num_names == 0)
|
if(num_names == 0)
|
||||||
@ -219,8 +259,11 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
|||||||
(*values)[i]= NULL;
|
(*values)[i]= NULL;
|
||||||
(*value_lengths)[i]= 0;
|
(*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) {
|
i+= strlen(list + i) + 1) {
|
||||||
if(!(flag & 8))
|
if(!(flag & 8))
|
||||||
if(strncmp(list + i, "user.", 5))
|
if(strncmp(list + i, "user.", 5))
|
||||||
@ -229,12 +272,7 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
|||||||
if((*names)[(*num_attrs) - 1] == NULL)
|
if((*names)[(*num_attrs) - 1] == NULL)
|
||||||
{ret= -1; goto ex;}
|
{ret= -1; goto ex;}
|
||||||
}
|
}
|
||||||
}
|
for(i= 0; (size_t) i < *num_attrs; i++) {
|
||||||
|
|
||||||
#ifdef Libisofs_with_aaip_xattR
|
|
||||||
|
|
||||||
if(!(flag & 4)) { /* Get xattr values */
|
|
||||||
for(i= 0; i < *num_attrs; i++) {
|
|
||||||
if(!(flag & 8))
|
if(!(flag & 8))
|
||||||
if(strncmp((*names)[i], "user.", 5))
|
if(strncmp((*names)[i], "user.", 5))
|
||||||
continue;
|
continue;
|
||||||
@ -291,15 +329,22 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
|||||||
|
|
||||||
ret= 1;
|
ret= 1;
|
||||||
ex:;
|
ex:;
|
||||||
|
#ifdef Libisofs_with_aaip_acL
|
||||||
if(a_acl_text != NULL)
|
if(a_acl_text != NULL)
|
||||||
aaip_get_acl_text("", &a_acl_text, 1 << 15); /* free */
|
aaip_get_acl_text("", &a_acl_text, 1 << 15); /* free */
|
||||||
if(d_acl_text != NULL)
|
if(d_acl_text != NULL)
|
||||||
aaip_get_acl_text("", &d_acl_text, 1 << 15); /* free */
|
aaip_get_acl_text("", &d_acl_text, 1 << 15); /* free */
|
||||||
|
if(acl != NULL)
|
||||||
|
free(acl);
|
||||||
|
#endif
|
||||||
|
#ifdef Libisofs_with_aaip_xattR
|
||||||
if(list != NULL)
|
if(list != NULL)
|
||||||
free(list);
|
free(list);
|
||||||
|
#endif
|
||||||
|
|
||||||
if(ret <= 0 || (flag & (1 << 15))) {
|
if(ret <= 0 || (flag & (1 << 15))) {
|
||||||
if(*names != NULL) {
|
if(*names != NULL) {
|
||||||
for(i= 0; i < *num_attrs; i++)
|
for(i= 0; (size_t) i < *num_attrs; i++)
|
||||||
free((*names)[i]);
|
free((*names)[i]);
|
||||||
free(*names);
|
free(*names);
|
||||||
}
|
}
|
||||||
@ -308,12 +353,10 @@ ex:;
|
|||||||
free(*value_lengths);
|
free(*value_lengths);
|
||||||
*value_lengths= NULL;
|
*value_lengths= NULL;
|
||||||
if(*values != 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)[i]);
|
||||||
free(*values);
|
free(*values);
|
||||||
}
|
}
|
||||||
if(acl != NULL)
|
|
||||||
free(acl);
|
|
||||||
*values= NULL;
|
*values= NULL;
|
||||||
*num_attrs= 0;
|
*num_attrs= 0;
|
||||||
}
|
}
|
||||||
@ -384,7 +427,9 @@ ex:
|
|||||||
bit3= do not ignore eventual non-user attributes.
|
bit3= do not ignore eventual non-user attributes.
|
||||||
I.e. those with a name which does not begin
|
I.e. those with a name which does not begin
|
||||||
by "user."
|
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 absense of
|
||||||
|
directory default ACL
|
||||||
@return 1 success
|
@return 1 success
|
||||||
-1 error memory allocation
|
-1 error memory allocation
|
||||||
-2 error with decoding of ACL
|
-2 error with decoding of ACL
|
||||||
@ -393,6 +438,8 @@ ex:
|
|||||||
-5 error with deleting attributes
|
-5 error with deleting attributes
|
||||||
-6 support of xattr not enabled at compile time
|
-6 support of xattr not enabled at compile time
|
||||||
-7 support of ACL 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,
|
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||||
size_t *value_lengths, char **values, int flag)
|
size_t *value_lengths, char **values, int flag)
|
||||||
@ -401,7 +448,7 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||||||
size_t i, consumed, acl_text_fill, acl_idx= 0, h_consumed;
|
size_t i, consumed, acl_text_fill, acl_idx= 0, h_consumed;
|
||||||
char *acl_text= NULL, *list= NULL;
|
char *acl_text= NULL, *list= NULL;
|
||||||
#ifdef Libisofs_with_aaip_xattR
|
#ifdef Libisofs_with_aaip_xattR
|
||||||
size_t list_size= 0;
|
ssize_t list_size= 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Libisofs_with_aaip_xattR
|
#ifdef Libisofs_with_aaip_xattR
|
||||||
@ -422,7 +469,7 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||||||
list_size= llistxattr(path, list, list_size);
|
list_size= llistxattr(path, list, list_size);
|
||||||
if(list_size == -1)
|
if(list_size == -1)
|
||||||
{ret= -5; goto ex;}
|
{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(!(flag & 8))
|
||||||
if(strncmp(list + i, "user.", 5))
|
if(strncmp(list + i, "user.", 5))
|
||||||
continue;
|
continue;
|
||||||
@ -447,7 +494,11 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Extended Attribute */
|
/* 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))
|
if(strncmp(names[i], "user.", 5))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -475,6 +526,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||||||
/* "access" ACL */
|
/* "access" ACL */
|
||||||
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
||||||
&consumed, NULL, 0, &acl_text_fill, 1);
|
&consumed, NULL, 0, &acl_text_fill, 1);
|
||||||
|
if(ret < -3)
|
||||||
|
goto ex;
|
||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
{ret= -2; goto ex;}
|
{ret= -2; goto ex;}
|
||||||
acl_text= calloc(acl_text_fill, 1);
|
acl_text= calloc(acl_text_fill, 1);
|
||||||
@ -482,6 +535,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||||||
{ret= -1; goto ex;}
|
{ret= -1; goto ex;}
|
||||||
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
||||||
&consumed, acl_text, acl_text_fill, &acl_text_fill, 0);
|
&consumed, acl_text, acl_text_fill, &acl_text_fill, 0);
|
||||||
|
if(ret < -3)
|
||||||
|
goto ex;
|
||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
{ret= -2; goto ex;}
|
{ret= -2; goto ex;}
|
||||||
has_default_acl= (ret == 2);
|
has_default_acl= (ret == 2);
|
||||||
@ -500,6 +555,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||||||
ret= aaip_decode_acl((unsigned char *) (values[i] + consumed),
|
ret= aaip_decode_acl((unsigned char *) (values[i] + consumed),
|
||||||
value_lengths[i] - consumed, &h_consumed,
|
value_lengths[i] - consumed, &h_consumed,
|
||||||
NULL, 0, &acl_text_fill, 1);
|
NULL, 0, &acl_text_fill, 1);
|
||||||
|
if(ret < -3)
|
||||||
|
goto ex;
|
||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
{ret= -2; goto ex;}
|
{ret= -2; goto ex;}
|
||||||
acl_text= calloc(acl_text_fill, 1);
|
acl_text= calloc(acl_text_fill, 1);
|
||||||
@ -508,11 +565,21 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||||||
ret= aaip_decode_acl((unsigned char *) (values[i] + consumed),
|
ret= aaip_decode_acl((unsigned char *) (values[i] + consumed),
|
||||||
value_lengths[i] - consumed, &h_consumed,
|
value_lengths[i] - consumed, &h_consumed,
|
||||||
acl_text, acl_text_fill, &acl_text_fill, 0);
|
acl_text, acl_text_fill, &acl_text_fill, 0);
|
||||||
|
if(ret < -3)
|
||||||
|
goto ex;
|
||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
{ret= -2; goto ex;}
|
{ret= -2; goto ex;}
|
||||||
ret= aaip_set_acl_text(path, acl_text, 1 | (flag & 32));
|
ret= aaip_set_acl_text(path, acl_text, 1 | (flag & 32));
|
||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
{ret= -3; goto ex;}
|
{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;
|
ret= 1;
|
||||||
ex:;
|
ex:;
|
||||||
|
@ -4,10 +4,10 @@
|
|||||||
Arbitrary Attribute Interchange Protocol , AAIP versions 0.2 , 1.0 , 2.0.
|
Arbitrary Attribute Interchange Protocol , AAIP versions 0.2 , 1.0 , 2.0.
|
||||||
Implementation of encoding and decoding xattr and ACL.
|
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
|
http://libburnia-project.org/wiki/AAIP
|
||||||
|
|
||||||
Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2+
|
Copyright (c) 2009 - 2011 Thomas Schmitt, libburnia project, GPLv2+
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -26,6 +26,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "libisofs.h"
|
#include "libisofs.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#define Aaip_encode_debuG 1
|
#define Aaip_encode_debuG 1
|
||||||
@ -94,8 +95,8 @@ size_t aaip_encode(size_t num_attrs, char **names,
|
|||||||
size_t *value_lengths, char **values,
|
size_t *value_lengths, char **values,
|
||||||
size_t *result_len, unsigned char **result, int flag)
|
size_t *result_len, unsigned char **result, int flag)
|
||||||
{
|
{
|
||||||
size_t mem_size= 0, comp_size;
|
size_t mem_size= 0, comp_size, ret;
|
||||||
unsigned int number_of_fields, i, num_recs, total_recs= 0, ret;
|
unsigned int number_of_fields, i, num_recs;
|
||||||
|
|
||||||
/* Predict memory needs, number of SUSP fields and component records */
|
/* Predict memory needs, number of SUSP fields and component records */
|
||||||
*result_len= 0;
|
*result_len= 0;
|
||||||
@ -105,7 +106,6 @@ size_t aaip_encode(size_t num_attrs, char **names,
|
|||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
return(ret);
|
return(ret);
|
||||||
mem_size+= comp_size;
|
mem_size+= comp_size;
|
||||||
total_recs= num_recs;
|
|
||||||
}
|
}
|
||||||
number_of_fields= mem_size / 250 + !!(mem_size % 250);
|
number_of_fields= mem_size / 250 + !!(mem_size % 250);
|
||||||
mem_size+= number_of_fields * 5;
|
mem_size+= number_of_fields * 5;
|
||||||
@ -158,9 +158,9 @@ size_t aaip_encode(size_t num_attrs, char **names,
|
|||||||
ret= 0;
|
ret= 0;
|
||||||
for(i= 0; i < *result_len; i+= ((unsigned char *) (*result))[i + 2])
|
for(i= 0; i < *result_len; i+= ((unsigned char *) (*result))[i + 2])
|
||||||
ret++;
|
ret++;
|
||||||
if(ret != number_of_fields) {
|
if(ret != (int) number_of_fields) {
|
||||||
fprintf(stderr, "aaip_encode(): WRONG NUMBER OF FIELDS %d <> %d\n",
|
fprintf(stderr, "aaip_encode(): WRONG NUMBER OF FIELDS %d <> %d\n",
|
||||||
number_of_fields, ret);
|
(int) number_of_fields, ret);
|
||||||
}
|
}
|
||||||
#endif /* Aaip_encode_debuG */
|
#endif /* Aaip_encode_debuG */
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ static int aaip_encode_comp(unsigned char *result, size_t *result_fill,
|
|||||||
aaip_encode_byte(result, result_fill, 0);
|
aaip_encode_byte(result, result_fill, 0);
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
for(rpt= data; rpt - data < l;) {
|
for(rpt= data; rpt - data < (ssize_t) l;) {
|
||||||
todo= l - (rpt - data) + (prefix > 0);
|
todo= l - (rpt - data) + (prefix > 0);
|
||||||
aaip_encode_byte(result, result_fill, (todo > 255));
|
aaip_encode_byte(result, result_fill, (todo > 255));
|
||||||
if(todo > 255)
|
if(todo > 255)
|
||||||
@ -198,7 +198,7 @@ static int aaip_encode_comp(unsigned char *result, size_t *result_fill,
|
|||||||
todo--;
|
todo--;
|
||||||
prefix= 0;
|
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));
|
aaip_encode_byte(result, result_fill, *((unsigned char *) rpt));
|
||||||
}
|
}
|
||||||
return(1);
|
return(1);
|
||||||
@ -268,7 +268,11 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
|||||||
bit3= check for completeness of list and eventually
|
bit3= check for completeness of list and eventually
|
||||||
fill up with entries deduced from st_mode
|
fill up with entries deduced from st_mode
|
||||||
@return >0 means ok
|
@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,
|
int aaip_encode_acl(char *acl_text, mode_t st_mode,
|
||||||
size_t *result_len, unsigned char **result, int flag)
|
size_t *result_len, unsigned char **result, int flag)
|
||||||
@ -279,8 +283,10 @@ int aaip_encode_acl(char *acl_text, mode_t st_mode,
|
|||||||
*result_len= 0;
|
*result_len= 0;
|
||||||
bytes= aaip_encode_acl_text(acl_text, st_mode,
|
bytes= aaip_encode_acl_text(acl_text, st_mode,
|
||||||
(size_t) 0, NULL, 1 | (flag & (2 | 4 | 8)));
|
(size_t) 0, NULL, 1 | (flag & (2 | 4 | 8)));
|
||||||
|
if(bytes < -2)
|
||||||
|
return(bytes);
|
||||||
if(bytes < 0)
|
if(bytes < 0)
|
||||||
return(0);
|
return((int) bytes - 1);
|
||||||
if(flag & 1) {
|
if(flag & 1) {
|
||||||
*result_len= bytes;
|
*result_len= bytes;
|
||||||
return(1);
|
return(1);
|
||||||
@ -292,9 +298,13 @@ int aaip_encode_acl(char *acl_text, mode_t st_mode,
|
|||||||
*result_len= bytes;
|
*result_len= bytes;
|
||||||
bytes= aaip_encode_acl_text(acl_text, st_mode, *result_len, *result,
|
bytes= aaip_encode_acl_text(acl_text, st_mode, *result_len, *result,
|
||||||
(flag & (2 | 4 | 8)));
|
(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;
|
*result_len= 0;
|
||||||
return(0);
|
return(-2);
|
||||||
}
|
}
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
@ -341,26 +351,31 @@ static int aaip_make_aaip_perms(int r, int w, int x)
|
|||||||
fill up with entries deduced from st_mode
|
fill up with entries deduced from st_mode
|
||||||
@return >=0 number of bytes produced resp. counted
|
@return >=0 number of bytes produced resp. counted
|
||||||
<0 means error
|
<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,
|
static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
||||||
size_t result_size, unsigned char *result, int flag)
|
size_t result_size, unsigned char *result, int flag)
|
||||||
{
|
{
|
||||||
char *rpt, *npt, *cpt;
|
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;
|
unsigned int has_u= 0, has_g= 0, has_o= 0, has_m= 0, is_trivial= 1;
|
||||||
uid_t uid, huid;
|
uid_t uid, huid;
|
||||||
gid_t gid, hgid;
|
gid_t gid, hgid;
|
||||||
ssize_t count= 0;
|
ssize_t count= 0;
|
||||||
struct passwd *pwd;
|
struct passwd *pwd;
|
||||||
struct group *grp;
|
struct group *grp;
|
||||||
char name[1024];
|
char *name = NULL;
|
||||||
|
int name_size= 1024;
|
||||||
double num;
|
double num;
|
||||||
|
|
||||||
|
LIBISO_ALLOC_MEM(name, char, name_size);
|
||||||
if(flag & 4) {
|
if(flag & 4) {
|
||||||
/* set SWITCH_MARK to indicate a default ACL */;
|
/* set SWITCH_MARK to indicate a default ACL */;
|
||||||
if(!(flag & 1)) {
|
if(!(flag & 1)) {
|
||||||
if(count >= result_size)
|
if((size_t) count >= result_size)
|
||||||
return(-1);
|
{ret= -1; goto ex;}
|
||||||
result[count]= (Aaip_SWITCH_MARK << 4) | Aaip_EXEC;
|
result[count]= (Aaip_SWITCH_MARK << 4) | Aaip_EXEC;
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
@ -384,9 +399,16 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
|||||||
if(strncmp(rpt, "user:", 5) == 0) {
|
if(strncmp(rpt, "user:", 5) == 0) {
|
||||||
if(cpt - rpt == 5) {
|
if(cpt - rpt == 5) {
|
||||||
type= Aaip_ACL_USER_OBJ;
|
type= Aaip_ACL_USER_OBJ;
|
||||||
|
if (has_u) {
|
||||||
|
|
||||||
|
/* >>> Duplicate u:: entry. */;
|
||||||
|
/* >>> ??? If it matches the previous one: ignore */
|
||||||
|
|
||||||
|
return((int) ISO_AAIP_ACL_MULT_OBJ);
|
||||||
|
}
|
||||||
has_u++;
|
has_u++;
|
||||||
} else {
|
} else {
|
||||||
if(cpt - (rpt + 5) >= sizeof(name))
|
if(cpt - (rpt + 5) >= name_size)
|
||||||
continue;
|
continue;
|
||||||
is_trivial= 0;
|
is_trivial= 0;
|
||||||
strncpy(name, rpt + 5, cpt - (rpt + 5));
|
strncpy(name, rpt + 5, cpt - (rpt + 5));
|
||||||
@ -396,8 +418,10 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
|||||||
pwd= getpwnam(name);
|
pwd= getpwnam(name);
|
||||||
if(pwd == NULL) {
|
if(pwd == NULL) {
|
||||||
num= aaip_numeric_id(name, 0);
|
num= aaip_numeric_id(name, 0);
|
||||||
if(num <= 0)
|
if(num <= 0) {
|
||||||
goto user_by_name;
|
/* ACL_USER is not part of AAIP 2.0 */
|
||||||
|
{ret= -2; goto ex;}
|
||||||
|
}
|
||||||
uid= huid= num;
|
uid= huid= num;
|
||||||
} else
|
} else
|
||||||
uid= huid= pwd->pw_uid;
|
uid= huid= pwd->pw_uid;
|
||||||
@ -405,31 +429,44 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
|
|||||||
for(i= 0; huid != 0; i++)
|
for(i= 0; huid != 0; i++)
|
||||||
huid= huid >> 8;
|
huid= huid >> 8;
|
||||||
qualifier_len= i;
|
qualifier_len= i;
|
||||||
|
if(qualifier_len <= 0)
|
||||||
|
qualifier_len= 1;
|
||||||
for(i= 0; i < qualifier_len ; i++)
|
for(i= 0; i < qualifier_len ; i++)
|
||||||
name[i]= uid >> (8 * (qualifier_len - i - 1));
|
name[i]= uid >> (8 * (qualifier_len - i - 1));
|
||||||
} else {
|
} else {
|
||||||
user_by_name:;
|
|
||||||
type= Aaip_ACL_USER;
|
type= Aaip_ACL_USER;
|
||||||
qualifier_len= strlen(name);
|
qualifier_len= strlen(name);
|
||||||
|
if(qualifier_len <= 0)
|
||||||
|
qualifier_len= 1;
|
||||||
}
|
}
|
||||||
qualifier= 1;
|
qualifier= 1;
|
||||||
}
|
}
|
||||||
} else if(strncmp(rpt, "group:", 6) == 0) {
|
} else if(strncmp(rpt, "group:", 6) == 0) {
|
||||||
if(cpt - rpt == 6) {
|
if(cpt - rpt == 6) {
|
||||||
type= Aaip_ACL_GROUP_OBJ;
|
type= Aaip_ACL_GROUP_OBJ;
|
||||||
|
if (has_g) {
|
||||||
|
|
||||||
|
/* >>> Duplicate g:: entry. */;
|
||||||
|
/* >>> ??? If it matches the previous one: ignore */
|
||||||
|
|
||||||
|
return((int) ISO_AAIP_ACL_MULT_OBJ);
|
||||||
|
}
|
||||||
has_g++;
|
has_g++;
|
||||||
} else {
|
} else {
|
||||||
if(cpt - (rpt + 6) >= sizeof(name))
|
if(cpt - (rpt + 6) >= name_size)
|
||||||
continue;
|
continue;
|
||||||
is_trivial= 0;
|
is_trivial= 0;
|
||||||
strncpy(name, rpt + 6, cpt - (rpt + 6));
|
strncpy(name, rpt + 6, cpt - (rpt + 6));
|
||||||
|
name[cpt - (rpt + 6)]= 0;
|
||||||
if(flag & 2) {
|
if(flag & 2) {
|
||||||
type= Aaip_ACL_GROUP_N;
|
type= Aaip_ACL_GROUP_N;
|
||||||
grp= getgrnam(name);
|
grp= getgrnam(name);
|
||||||
if(grp == NULL) {
|
if(grp == NULL) {
|
||||||
num= aaip_numeric_id(name, 0);
|
num= aaip_numeric_id(name, 0);
|
||||||
if(num <= 0)
|
if(num <= 0) {
|
||||||
goto group_by_name;
|
/* ACL_GROUP is not part of AAIP 2.0 */
|
||||||
|
{ret= -2; goto ex;}
|
||||||
|
}
|
||||||
gid= hgid= num;
|
gid= hgid= num;
|
||||||
} else
|
} else
|
||||||
gid= hgid= grp->gr_gid;
|
gid= hgid= grp->gr_gid;
|
||||||
@ -437,18 +474,27 @@ user_by_name:;
|
|||||||
for(i= 0; hgid != 0; i++)
|
for(i= 0; hgid != 0; i++)
|
||||||
hgid= hgid >> 8;
|
hgid= hgid >> 8;
|
||||||
qualifier_len= i;
|
qualifier_len= i;
|
||||||
|
if(qualifier_len <= 0)
|
||||||
|
qualifier_len= 1;
|
||||||
for(i= 0; i < qualifier_len ; i++)
|
for(i= 0; i < qualifier_len ; i++)
|
||||||
name[i]= gid >> (8 * (qualifier_len - i - 1));
|
name[i]= gid >> (8 * (qualifier_len - i - 1));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
group_by_name:;
|
|
||||||
type= Aaip_ACL_GROUP;
|
type= Aaip_ACL_GROUP;
|
||||||
qualifier_len= strlen(name);
|
qualifier_len= strlen(name);
|
||||||
|
if(qualifier_len <= 0)
|
||||||
|
qualifier_len= 1;
|
||||||
}
|
}
|
||||||
qualifier= 1;
|
qualifier= 1;
|
||||||
}
|
}
|
||||||
} else if(strncmp(rpt, "other:", 6) == 0) {
|
} else if(strncmp(rpt, "other:", 6) == 0) {
|
||||||
type= Aaip_ACL_OTHER;
|
type= Aaip_ACL_OTHER;
|
||||||
|
if (has_o) {
|
||||||
|
|
||||||
|
/* >>> Duplicate o:: entry. */;
|
||||||
|
/* >>> ??? If it matches the previous one: ignore */
|
||||||
|
|
||||||
|
return((int) ISO_AAIP_ACL_MULT_OBJ);
|
||||||
|
}
|
||||||
has_o++;
|
has_o++;
|
||||||
} else if(strncmp(rpt, "mask:", 5) == 0) {
|
} else if(strncmp(rpt, "mask:", 5) == 0) {
|
||||||
type= Aaip_ACL_MASK;
|
type= Aaip_ACL_MASK;
|
||||||
@ -461,8 +507,8 @@ group_by_name:;
|
|||||||
perms= aaip_make_aaip_perms(cpt[1] == 'r', cpt[2] == 'w', cpt[3] == 'x');
|
perms= aaip_make_aaip_perms(cpt[1] == 'r', cpt[2] == 'w', cpt[3] == 'x');
|
||||||
|
|
||||||
if(!(flag & 1)) {
|
if(!(flag & 1)) {
|
||||||
if(count >= result_size)
|
if((size_t) count >= result_size)
|
||||||
return(-1);
|
{ret= -1; goto ex;}
|
||||||
result[count]= perms | ((!!qualifier) << 3) | (type << 4);
|
result[count]= perms | ((!!qualifier) << 3) | (type << 4);
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
@ -470,8 +516,8 @@ group_by_name:;
|
|||||||
if(qualifier) {
|
if(qualifier) {
|
||||||
num_recs= (qualifier_len / 127) + !!(qualifier_len % 127);
|
num_recs= (qualifier_len / 127) + !!(qualifier_len % 127);
|
||||||
if(!(flag & 1)) {
|
if(!(flag & 1)) {
|
||||||
if(count + 1 > result_size)
|
if((size_t) (count + 1) > result_size)
|
||||||
return(-1);
|
{ret= -1; goto ex;}
|
||||||
for(i= 0; i < num_recs; i++) {
|
for(i= 0; i < num_recs; i++) {
|
||||||
if(i < num_recs - 1)
|
if(i < num_recs - 1)
|
||||||
result[count++]= 255;
|
result[count++]= 255;
|
||||||
@ -480,8 +526,8 @@ group_by_name:;
|
|||||||
if(result[count - 1] == 0)
|
if(result[count - 1] == 0)
|
||||||
result[count - 1]= 127;
|
result[count - 1]= 127;
|
||||||
}
|
}
|
||||||
if(count + (result[count - 1] & 127) > result_size)
|
if((size_t) (count + (result[count - 1] & 127)) > result_size)
|
||||||
return(-1);
|
{ret= -1; goto ex;}
|
||||||
memcpy(result + count, name + i * 127, result[count - 1] & 127);
|
memcpy(result + count, name + i * 127, result[count - 1] & 127);
|
||||||
count+= result[count - 1] & 127;
|
count+= result[count - 1] & 127;
|
||||||
}
|
}
|
||||||
@ -495,8 +541,8 @@ group_by_name:;
|
|||||||
if(flag & 1)
|
if(flag & 1)
|
||||||
count+= needed;
|
count+= needed;
|
||||||
else {
|
else {
|
||||||
if(count + needed > result_size)
|
if((size_t) (count + needed) > result_size)
|
||||||
return(-1);
|
{ret= -1; goto ex;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((flag & 8) && needed > 0 && !(flag & 1)) {
|
if ((flag & 8) && needed > 0 && !(flag & 1)) {
|
||||||
@ -521,7 +567,10 @@ group_by_name:;
|
|||||||
result[count++]= perms | (Aaip_ACL_MASK << 4);
|
result[count++]= perms | (Aaip_ACL_MASK << 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(count);
|
ret= count;
|
||||||
|
ex:;
|
||||||
|
LIBISO_FREE_MEM(name);
|
||||||
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1120,9 +1169,9 @@ static int aaip_consume_rec_head(struct aaip_state *aaip,
|
|||||||
size_t todo;
|
size_t todo;
|
||||||
|
|
||||||
todo= *num_data;
|
todo= *num_data;
|
||||||
if(todo > aaip->aa_missing)
|
if(todo > (size_t) aaip->aa_missing)
|
||||||
todo= 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;
|
todo= aaip->rec_head_missing;
|
||||||
if(!aaip->recs_invalid)
|
if(!aaip->recs_invalid)
|
||||||
aaip_push_to_recs(aaip, *data, todo, 0);
|
aaip_push_to_recs(aaip, *data, todo, 0);
|
||||||
@ -1144,9 +1193,9 @@ static int aaip_consume_rec_data(struct aaip_state *aaip,
|
|||||||
size_t todo;
|
size_t todo;
|
||||||
|
|
||||||
todo= *num_data;
|
todo= *num_data;
|
||||||
if(todo > aaip->aa_missing)
|
if(todo > (size_t) aaip->aa_missing)
|
||||||
todo= aaip->aa_missing;
|
todo= aaip->aa_missing;
|
||||||
if(todo > aaip->rec_missing)
|
if(todo > (size_t) aaip->rec_missing)
|
||||||
todo= aaip->rec_missing;
|
todo= aaip->rec_missing;
|
||||||
if(!aaip->recs_invalid)
|
if(!aaip->recs_invalid)
|
||||||
aaip_push_to_recs(aaip, *data, todo, 1);
|
aaip_push_to_recs(aaip, *data, todo, 1);
|
||||||
@ -1178,7 +1227,7 @@ static int aaip_consume_aa_head(struct aaip_state *aaip,
|
|||||||
unsigned char aa_head[5];
|
unsigned char aa_head[5];
|
||||||
|
|
||||||
todo= *num_data;
|
todo= *num_data;
|
||||||
if(todo >= aaip->aa_head_missing)
|
if(todo >= (size_t) aaip->aa_head_missing)
|
||||||
todo= aaip->aa_head_missing;
|
todo= aaip->aa_head_missing;
|
||||||
aaip_push_to_recs(aaip, *data, todo, 0);
|
aaip_push_to_recs(aaip, *data, todo, 0);
|
||||||
aaip->aa_head_missing-= todo;
|
aaip->aa_head_missing-= todo;
|
||||||
@ -1225,7 +1274,7 @@ static int aaip_consume_aa_data(struct aaip_state *aaip,
|
|||||||
aaip_push_to_recs(aaip, zero_char, 1, 0);
|
aaip_push_to_recs(aaip, zero_char, 1, 0);
|
||||||
} else {
|
} else {
|
||||||
/* fill in missing btes */
|
/* 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_push_to_recs(aaip, zero_char, 1, 1);
|
||||||
}
|
}
|
||||||
aaip->rec_head_missing= 2;
|
aaip->rec_head_missing= 2;
|
||||||
@ -1696,7 +1745,7 @@ int aaip_decode_attrs(struct aaip_state **handle,
|
|||||||
unsigned char *data, size_t num_data, size_t *consumed,
|
unsigned char *data, size_t num_data, size_t *consumed,
|
||||||
int flag)
|
int flag)
|
||||||
{
|
{
|
||||||
int ret, was_non_aa= 0;
|
int ret;
|
||||||
struct aaip_state *aaip;
|
struct aaip_state *aaip;
|
||||||
size_t h_num, *h_lengths, i, new_mem, pair_consumed= 0;
|
size_t h_num, *h_lengths, i, new_mem, pair_consumed= 0;
|
||||||
char **h_names, **h_values, *hpt;
|
char **h_names, **h_values, *hpt;
|
||||||
@ -1785,7 +1834,6 @@ int aaip_decode_attrs(struct aaip_state **handle,
|
|||||||
return(ret);
|
return(ret);
|
||||||
|
|
||||||
} else if(ret == -1) { /* non-AAIP field detected */
|
} else if(ret == -1) { /* non-AAIP field detected */
|
||||||
was_non_aa= 1;
|
|
||||||
if(pair_consumed <= 0)
|
if(pair_consumed <= 0)
|
||||||
return(-4); /* interpretation did not advance */
|
return(-4); /* interpretation did not advance */
|
||||||
|
|
||||||
@ -1968,14 +2016,16 @@ static int aaip_read_qualifier(unsigned char *data, size_t num_data,
|
|||||||
char *name, size_t name_size, size_t *name_fill,
|
char *name, size_t name_size, size_t *name_fill,
|
||||||
int flag)
|
int flag)
|
||||||
{
|
{
|
||||||
int is_done= 0, rec_len= 0;
|
int is_done= 0;
|
||||||
|
size_t rec_len= 0;
|
||||||
unsigned char *rpt;
|
unsigned char *rpt;
|
||||||
|
|
||||||
*name_fill= 0;
|
*name_fill= 0;
|
||||||
for(rpt= data; !is_done; rpt+= rec_len) {
|
for(rpt= data; !is_done; rpt+= rec_len) {
|
||||||
rec_len= (*rpt) & 127;
|
rec_len= (*rpt) & 127;
|
||||||
is_done= !((*rpt) & 128);
|
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);
|
return(-1);
|
||||||
memcpy(name + *name_fill, rpt + 1, rec_len);
|
memcpy(name + *name_fill, rpt + 1, rec_len);
|
||||||
rpt+= 1 + rec_len;
|
rpt+= 1 + rec_len;
|
||||||
@ -2013,20 +2063,21 @@ int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
|
|||||||
size_t *acl_text_fill, int flag)
|
size_t *acl_text_fill, int flag)
|
||||||
{
|
{
|
||||||
unsigned char *rpt;
|
unsigned char *rpt;
|
||||||
char perm_text[4], *wpt, name[1024];
|
char perm_text[4], *wpt, *name= NULL;
|
||||||
int type, qualifier= 0, perm, ret, i, cnt;
|
int type, qualifier= 0, perm, ret, cnt, name_size= 1024;
|
||||||
size_t w_size, name_fill= 0;
|
size_t w_size, name_fill= 0, i;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
struct passwd *pwd;
|
struct passwd *pwd;
|
||||||
struct group *grp;
|
struct group *grp;
|
||||||
|
|
||||||
|
LIBISO_ALLOC_MEM(name, char, name_size);
|
||||||
cnt= flag & 1;
|
cnt= flag & 1;
|
||||||
*consumed= 0;
|
*consumed= 0;
|
||||||
wpt= acl_text;
|
wpt= acl_text;
|
||||||
w_size= acl_text_size;
|
w_size= acl_text_size;
|
||||||
*acl_text_fill= 0;
|
*acl_text_fill= 0;
|
||||||
for(rpt= data; rpt - data < num_data; ) {
|
for(rpt= data; (size_t) (rpt - data) < num_data; ) {
|
||||||
perm= *rpt;
|
perm= *rpt;
|
||||||
strcpy(perm_text, "---");
|
strcpy(perm_text, "---");
|
||||||
if(perm & Aaip_READ)
|
if(perm & Aaip_READ)
|
||||||
@ -2038,14 +2089,14 @@ int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
|
|||||||
|
|
||||||
type= (*rpt) >> 4;
|
type= (*rpt) >> 4;
|
||||||
if(type == Aaip_FUTURE_VERSION) /* indicate to caller: version mismatch */
|
if(type == Aaip_FUTURE_VERSION) /* indicate to caller: version mismatch */
|
||||||
return(-3);
|
{ret = -3; goto ex;}
|
||||||
|
|
||||||
qualifier= !!((*rpt) & 8);
|
qualifier= !!((*rpt) & 8);
|
||||||
if(qualifier) {
|
if(qualifier) {
|
||||||
ret= aaip_read_qualifier(rpt + 1, num_data - (rpt + 1 - data),
|
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)
|
if(ret <= 0)
|
||||||
return(-1);
|
{ret = -1; goto ex;}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Advance read pointer */
|
/* Advance read pointer */
|
||||||
@ -2086,7 +2137,7 @@ int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
|
|||||||
pwd= getpwuid(uid);
|
pwd= getpwuid(uid);
|
||||||
if(pwd == NULL)
|
if(pwd == NULL)
|
||||||
sprintf(name, "%.f", (double) uid);
|
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);
|
sprintf(name, "%.f", (double) uid);
|
||||||
else
|
else
|
||||||
strcpy(name, pwd->pw_name);
|
strcpy(name, pwd->pw_name);
|
||||||
@ -2100,7 +2151,7 @@ int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
|
|||||||
grp= getgrgid(gid);
|
grp= getgrgid(gid);
|
||||||
if(grp == NULL)
|
if(grp == NULL)
|
||||||
sprintf(name, "%.f", (double) gid);
|
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);
|
sprintf(name, "%.f", (double) gid);
|
||||||
else
|
else
|
||||||
strcpy(name, grp->gr_name);
|
strcpy(name, grp->gr_name);
|
||||||
@ -2108,15 +2159,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);
|
ret= aaip_write_acl_line(&wpt, &w_size, "group", name, perm_text, cnt);
|
||||||
} else {
|
} else {
|
||||||
/* indicate to caller: unknown type */
|
/* indicate to caller: unknown type */
|
||||||
return(-4);
|
{ret = -4; goto ex;}
|
||||||
}
|
}
|
||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
return(-2);
|
{ret = -2; goto ex;}
|
||||||
}
|
}
|
||||||
ret= 1;
|
ret= 1;
|
||||||
ex:;
|
ex:;
|
||||||
|
*acl_text_fill= w_size;
|
||||||
if(flag & 1)
|
if(flag & 1)
|
||||||
*acl_text_fill= w_size + 1;
|
(*acl_text_fill)++;
|
||||||
|
LIBISO_FREE_MEM(name);
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2133,6 +2186,13 @@ ex:;
|
|||||||
|
|
||||||
#include "aaip-os-linux.c"
|
#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
|
#else
|
||||||
|
|
||||||
#include "aaip-os-dummy.c"
|
#include "aaip-os-dummy.c"
|
||||||
|
@ -56,7 +56,11 @@ size_t aaip_encode(size_t num_attrs, char **names,
|
|||||||
bit3= check for completeness of list and eventually
|
bit3= check for completeness of list and eventually
|
||||||
fill up with entries deduced from st_mode
|
fill up with entries deduced from st_mode
|
||||||
@return >0 means ok
|
@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,
|
int aaip_encode_acl(char *acl_text, mode_t st_mode,
|
||||||
size_t *result_len, unsigned char **result, int flag);
|
size_t *result_len, unsigned char **result, int flag);
|
||||||
@ -80,7 +84,7 @@ int aaip_encode_acl(char *acl_text, mode_t st_mode,
|
|||||||
bit3= check for completeness of list and eventually
|
bit3= check for completeness of list and eventually
|
||||||
fill up with entries deduced from st_mode
|
fill up with entries deduced from st_mode
|
||||||
@return >0 means ok
|
@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,
|
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);
|
size_t *result_len, unsigned char **result, int flag);
|
||||||
@ -145,6 +149,24 @@ int aaip_add_acl_st_mode(char *acl_text, mode_t st_mode, int flag);
|
|||||||
|
|
||||||
/* ------ OS interface ------ */
|
/* ------ 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.
|
/* Obtain the ACL of the given file in long text form.
|
||||||
@param path Path to the file
|
@param path Path to the file
|
||||||
@param text Will hold the result. This is a managed object which
|
@param text Will hold the result. This is a managed object which
|
||||||
@ -478,6 +500,8 @@ int aaip_set_acl_text(char *path, char *text, int flag);
|
|||||||
-5 error with deleting attributes
|
-5 error with deleting attributes
|
||||||
-6 support of xattr not enabled at compile time
|
-6 support of xattr not enabled at compile time
|
||||||
-7 support of ACL 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,
|
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||||
size_t *value_lengths, char **values, int flag);
|
size_t *value_lengths, char **values, int 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)
|
int iso_ring_buffer_write(IsoRingBuffer *buf, uint8_t *data, size_t count)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
int bytes_write = 0;
|
size_t bytes_write = 0;
|
||||||
|
|
||||||
if (buf == NULL || data == NULL) {
|
if (buf == NULL || data == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
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)
|
int iso_ring_buffer_read(IsoRingBuffer *buf, uint8_t *dest, size_t count)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
int bytes_read = 0;
|
size_t bytes_read = 0;
|
||||||
|
|
||||||
if (buf == NULL || dest == NULL) {
|
if (buf == NULL || dest == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
|
@ -11,7 +11,14 @@
|
|||||||
#define LIBISO_BUFFER_H_
|
#define LIBISO_BUFFER_H_
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_STDINT_H
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_INTTYPES_H
|
||||||
|
#include <inttypes.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#define BLOCK_SIZE 2048
|
#define BLOCK_SIZE 2048
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* 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
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -20,16 +20,13 @@
|
|||||||
#include "fsource.h"
|
#include "fsource.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
#include "aaip_0_2.h"
|
#include "aaip_0_2.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifndef PATH_MAX
|
|
||||||
#define PATH_MAX Libisofs_default_path_maX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void iso_node_builder_ref(IsoNodeBuilder *builder)
|
void iso_node_builder_ref(IsoNodeBuilder *builder)
|
||||||
@ -75,6 +72,8 @@ int default_create_file(IsoNodeBuilder *builder, IsoImage *image,
|
|||||||
iso_file_source_ref(src);
|
iso_file_source_ref(src);
|
||||||
|
|
||||||
name = iso_file_source_get_name(src);
|
name = iso_file_source_get_name(src);
|
||||||
|
if (strlen(name) > LIBISOFS_NODE_NAME_MAX)
|
||||||
|
name[LIBISOFS_NODE_NAME_MAX] = 0;
|
||||||
ret = iso_node_new_file(name, stream, &node);
|
ret = iso_node_new_file(name, stream, &node);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
iso_stream_unref(stream);
|
iso_stream_unref(stream);
|
||||||
@ -106,9 +105,11 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
|||||||
char *name;
|
char *name;
|
||||||
unsigned char *aa_string = NULL;
|
unsigned char *aa_string = NULL;
|
||||||
char *a_text = NULL, *d_text = NULL;
|
char *a_text = NULL, *d_text = NULL;
|
||||||
|
char *dest = NULL;
|
||||||
|
IsoSymlink *link;
|
||||||
|
|
||||||
if (builder == NULL || src == NULL || node == NULL) {
|
if (builder == NULL || src == NULL || node == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
{ret = ISO_NULL_POINTER; goto ex;}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get info about source */
|
/* get info about source */
|
||||||
@ -118,10 +119,12 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
|||||||
ret = iso_file_source_lstat(src, &info);
|
ret = iso_file_source_lstat(src, &info);
|
||||||
}
|
}
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
goto ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
name = iso_file_source_get_name(src);
|
name = iso_file_source_get_name(src);
|
||||||
|
if (strlen(name) > LIBISOFS_NODE_NAME_MAX)
|
||||||
|
name[LIBISOFS_NODE_NAME_MAX] = 0;
|
||||||
fs = iso_file_source_get_filesystem(src);
|
fs = iso_file_source_get_filesystem(src);
|
||||||
new = NULL;
|
new = NULL;
|
||||||
|
|
||||||
@ -157,10 +160,8 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
|||||||
case S_IFLNK:
|
case S_IFLNK:
|
||||||
{
|
{
|
||||||
/* source is a symbolic link */
|
/* source is a symbolic link */
|
||||||
char dest[PATH_MAX];
|
LIBISO_ALLOC_MEM(dest, char, LIBISOFS_NODE_PATH_MAX);
|
||||||
IsoSymlink *link;
|
ret = iso_file_source_readlink(src, dest, LIBISOFS_NODE_PATH_MAX);
|
||||||
|
|
||||||
ret = iso_file_source_readlink(src, dest, PATH_MAX);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -198,7 +199,7 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
|||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
free(name);
|
free(name);
|
||||||
return ret;
|
goto ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fill fields */
|
/* fill fields */
|
||||||
@ -233,19 +234,25 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
|||||||
if (ret == 1 && aa_string != NULL) {
|
if (ret == 1 && aa_string != NULL) {
|
||||||
ret = iso_node_add_xinfo(new, aaip_xinfo_func, aa_string);
|
ret = iso_node_add_xinfo(new, aaip_xinfo_func, aa_string);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
goto ex;
|
||||||
} else if(aa_string != NULL) {
|
} else if(aa_string != NULL) {
|
||||||
free(aa_string);
|
free(aa_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
*node = new;
|
*node = new;
|
||||||
|
|
||||||
return ISO_SUCCESS;
|
ret = ISO_SUCCESS;
|
||||||
|
ex:;
|
||||||
|
LIBISO_FREE_MEM(dest);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void default_free(IsoNodeBuilder *builder)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* 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
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -15,7 +15,14 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_STDINT_H
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_INTTYPES_H
|
||||||
|
#include <inttypes.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
#define BLOCK_SIZE 2048
|
#define BLOCK_SIZE 2048
|
||||||
@ -63,6 +70,23 @@
|
|||||||
#endif
|
#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
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the options for the image generation.
|
* Holds the options for the image generation.
|
||||||
*/
|
*/
|
||||||
@ -76,6 +100,8 @@ struct iso_write_opts {
|
|||||||
unsigned int rockridge :1;
|
unsigned int rockridge :1;
|
||||||
unsigned int joliet :1;
|
unsigned int joliet :1;
|
||||||
unsigned int iso1999 :1;
|
unsigned int iso1999 :1;
|
||||||
|
unsigned int hfsplus :1;
|
||||||
|
unsigned int fat :1;
|
||||||
|
|
||||||
unsigned int aaip :1; /* whether to write eventual ACL and EAs */
|
unsigned int aaip :1; /* whether to write eventual ACL and EAs */
|
||||||
|
|
||||||
@ -142,6 +168,13 @@ struct iso_write_opts {
|
|||||||
*/
|
*/
|
||||||
unsigned int allow_full_ascii :1;
|
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
|
* Allow all characters to be part of Volume and Volset identifiers on
|
||||||
* the Primary Volume Descriptor. This breaks ISO-9660 contraints, but
|
* the Primary Volume Descriptor. This breaks ISO-9660 contraints, but
|
||||||
@ -154,6 +187,11 @@ struct iso_write_opts {
|
|||||||
*/
|
*/
|
||||||
unsigned int joliet_longer_paths :1;
|
unsigned int joliet_longer_paths :1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow Joliet names up to 103 characters rather than 64.
|
||||||
|
*/
|
||||||
|
unsigned int joliet_long_names :1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write Rock Ridge info as of specification RRIP-1.10 rather than
|
* Write Rock Ridge info as of specification RRIP-1.10 rather than
|
||||||
* RRIP-1.12: signature "RRIP_1991A" rather than "IEEE_1282",
|
* RRIP-1.12: signature "RRIP_1991A" rather than "IEEE_1282",
|
||||||
@ -190,8 +228,27 @@ struct iso_write_opts {
|
|||||||
* to expect that we do have a creation timestamp with the source.
|
* to expect that we do have a creation timestamp with the source.
|
||||||
* mkisofs writes mtimes and the result seems more suitable if mounted
|
* mkisofs writes mtimes and the result seems more suitable if mounted
|
||||||
* without Rock Ridge support.)
|
* 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
|
* Compute MD5 checksum for the whole session and record it as index 0 of
|
||||||
@ -232,6 +289,16 @@ struct iso_write_opts {
|
|||||||
unsigned int replace_uid :2;
|
unsigned int replace_uid :2;
|
||||||
unsigned int replace_gid :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
|
* Extra Caution: This option breaks any assumptions about names that
|
||||||
* are supported by ECMA-119 specifications.
|
* are supported by ECMA-119 specifications.
|
||||||
@ -247,11 +314,6 @@ struct iso_write_opts {
|
|||||||
*/
|
*/
|
||||||
unsigned int untranslated_name_len;
|
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
|
* 0 to use IsoNode timestamps, 1 to use recording time, 2 to use
|
||||||
* values from timestamp field. This has only meaning if RR extensions
|
* values from timestamp field. This has only meaning if RR extensions
|
||||||
@ -390,6 +452,16 @@ struct iso_write_opts {
|
|||||||
*/
|
*/
|
||||||
uint32_t tail_blocks;
|
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;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
/* Eventual disk file paths of prepared images which shall be appended
|
/* Eventual disk file paths of prepared images which shall be appended
|
||||||
after the ISO image and described by partiton table entries in a MBR
|
after the ISO image and described by partiton table entries in a MBR
|
||||||
*/
|
*/
|
||||||
@ -399,12 +471,27 @@ struct iso_write_opts {
|
|||||||
/* Eventual name of the non-ISO aspect of the image. E.g. SUN ASCII label.
|
/* Eventual name of the non-ISO aspect of the image. E.g. SUN ASCII label.
|
||||||
*/
|
*/
|
||||||
char ascii_disc_label[ISO_DISC_LABEL_SIZE];
|
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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ecma119_image Ecma119Image;
|
typedef struct ecma119_image Ecma119Image;
|
||||||
typedef struct ecma119_node Ecma119Node;
|
typedef struct ecma119_node Ecma119Node;
|
||||||
typedef struct joliet_node JolietNode;
|
typedef struct joliet_node JolietNode;
|
||||||
typedef struct iso1999_node Iso1999Node;
|
typedef struct iso1999_node Iso1999Node;
|
||||||
|
typedef struct hfsplus_node HFSPlusNode;
|
||||||
typedef struct Iso_File_Src IsoFileSrc;
|
typedef struct Iso_File_Src IsoFileSrc;
|
||||||
typedef struct Iso_Image_Writer IsoImageWriter;
|
typedef struct Iso_Image_Writer IsoImageWriter;
|
||||||
|
|
||||||
@ -424,6 +511,8 @@ struct ecma119_image
|
|||||||
unsigned int joliet :1;
|
unsigned int joliet :1;
|
||||||
unsigned int eltorito :1;
|
unsigned int eltorito :1;
|
||||||
unsigned int iso1999 :1;
|
unsigned int iso1999 :1;
|
||||||
|
unsigned int hfsplus :1;
|
||||||
|
unsigned int fat :1;
|
||||||
|
|
||||||
unsigned int hardlinks:1; /* see iso_write_opts_set_hardlinks() */
|
unsigned int hardlinks:1; /* see iso_write_opts_set_hardlinks() */
|
||||||
|
|
||||||
@ -441,12 +530,16 @@ struct ecma119_image
|
|||||||
unsigned int no_force_dots :2;
|
unsigned int no_force_dots :2;
|
||||||
unsigned int allow_lowercase :1;
|
unsigned int allow_lowercase :1;
|
||||||
unsigned int allow_full_ascii :1;
|
unsigned int allow_full_ascii :1;
|
||||||
|
unsigned int allow_7bit_ascii :1;
|
||||||
|
|
||||||
unsigned int relaxed_vol_atts : 1;
|
unsigned int relaxed_vol_atts : 1;
|
||||||
|
|
||||||
/** Allow paths on Joliet tree to be larger than 240 bytes */
|
/** Allow paths on Joliet tree to be larger than 240 bytes */
|
||||||
unsigned int joliet_longer_paths :1;
|
unsigned int joliet_longer_paths :1;
|
||||||
|
|
||||||
|
/** Allow Joliet names up to 103 characters rather than 64 */
|
||||||
|
unsigned int joliet_long_names :1;
|
||||||
|
|
||||||
/** Write old fashioned RRIP-1.10 rather than RRIP-1.12 */
|
/** Write old fashioned RRIP-1.10 rather than RRIP-1.12 */
|
||||||
unsigned int rrip_version_1_10 :1;
|
unsigned int rrip_version_1_10 :1;
|
||||||
|
|
||||||
@ -456,8 +549,16 @@ struct ecma119_image
|
|||||||
/* Write AAIP as extension according to SUSP 1.10 rather than SUSP 1.12. */
|
/* Write AAIP as extension according to SUSP 1.10 rather than SUSP 1.12. */
|
||||||
unsigned int aaip_susp_1_10 :1;
|
unsigned int aaip_susp_1_10 :1;
|
||||||
|
|
||||||
/* Store in ECMA-119 timestamp mtime of source */
|
/* Store in ECMA-119, Joliet, ISO 9660:1999 timestamp the mtime of source
|
||||||
unsigned int dir_rec_mtime :1;
|
bit0= ECMA-119, bit1= Joliet, bit2= ISO 9660:1999.
|
||||||
|
*/
|
||||||
|
unsigned int dir_rec_mtime :3;
|
||||||
|
|
||||||
|
/* The ECMA-119 directory where to store Rock Ridge relocated directories.
|
||||||
|
*/
|
||||||
|
char *rr_reloc_dir; /* IsoNode name in root directory */
|
||||||
|
int rr_reloc_flags;
|
||||||
|
Ecma119Node *rr_reloc_node; /* Directory node in ecma119_image */
|
||||||
|
|
||||||
unsigned int md5_session_checksum :1;
|
unsigned int md5_session_checksum :1;
|
||||||
unsigned int md5_file_checksums :2;
|
unsigned int md5_file_checksums :2;
|
||||||
@ -472,14 +573,15 @@ struct ecma119_image
|
|||||||
unsigned int replace_dir_mode :1;
|
unsigned int replace_dir_mode :1;
|
||||||
unsigned int replace_timestamps :1;
|
unsigned int replace_timestamps :1;
|
||||||
|
|
||||||
unsigned int untranslated_name_len;
|
|
||||||
|
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
mode_t file_mode;
|
mode_t file_mode;
|
||||||
mode_t dir_mode;
|
mode_t dir_mode;
|
||||||
time_t timestamp;
|
time_t timestamp;
|
||||||
|
|
||||||
|
unsigned int old_empty :1;
|
||||||
|
unsigned int untranslated_name_len;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* if sort files or not. Sorting is based of the weight of each file
|
* if sort files or not. Sorting is based of the weight of each file
|
||||||
*/
|
*/
|
||||||
@ -488,6 +590,11 @@ struct ecma119_image
|
|||||||
char *input_charset;
|
char *input_charset;
|
||||||
char *output_charset;
|
char *output_charset;
|
||||||
|
|
||||||
|
/* See iso_write_opts and iso_write_opts_set_hfsp_serial_number().
|
||||||
|
* 00...00 means that it shall be generated by libisofs.
|
||||||
|
*/
|
||||||
|
uint8_t hfsp_serial_number[8];
|
||||||
|
|
||||||
unsigned int appendable : 1;
|
unsigned int appendable : 1;
|
||||||
uint32_t ms_block; /**< start block for a ms image */
|
uint32_t ms_block; /**< start block for a ms image */
|
||||||
time_t now; /**< Time at which writing began. */
|
time_t now; /**< Time at which writing began. */
|
||||||
@ -512,6 +619,12 @@ struct ecma119_image
|
|||||||
*/
|
*/
|
||||||
uint32_t empty_file_block;
|
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,
|
* number of dirs in ECMA-119 tree, computed together with dir position,
|
||||||
* and needed for path table computation in a efficient way
|
* and needed for path table computation in a efficient way
|
||||||
@ -530,6 +643,29 @@ struct ecma119_image
|
|||||||
uint32_t joliet_l_path_table_pos;
|
uint32_t joliet_l_path_table_pos;
|
||||||
uint32_t joliet_m_path_table_pos;
|
uint32_t joliet_m_path_table_pos;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
* ISO 9660:1999 related information
|
||||||
*/
|
*/
|
||||||
@ -556,19 +692,36 @@ struct ecma119_image
|
|||||||
*/
|
*/
|
||||||
char *system_area_data;
|
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
|
* Make bytes 446 - 512 of the system area a partition
|
||||||
* table which reserves partition 1 from byte 63*512 to the
|
* table which reserves partition 1 from byte 63*512 to the
|
||||||
* end of the ISO image. Assumed are 63 secs/hed, 255 head/cyl.
|
* end of the ISO image. Assumed are 63 secs/hed, 255 head/cyl.
|
||||||
* (GRUB protective msdos label.)
|
* (GRUB protective msdos label.)
|
||||||
* This works with and without system_area_data.
|
* 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.
|
* Apply isohybrid MBR patching to the system area.
|
||||||
* This works only with system_area_data plus ISOLINUX boot image
|
* This works only with system_area_data plus ISOLINUX boot image
|
||||||
* and only if not bit0 is set.
|
* and only if not bit0 is set.
|
||||||
* bit2-7= System area type
|
* bit2-7= System area type
|
||||||
* 0= DOS MBR
|
* 0= DOS MBR
|
||||||
* 1= MIPS Big Endian Volume Header
|
* 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;
|
int system_area_options;
|
||||||
|
|
||||||
@ -681,6 +834,84 @@ struct ecma119_image
|
|||||||
|
|
||||||
char ascii_disc_label[ISO_DISC_LABEL_SIZE];
|
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.
|
||||||
|
*/
|
||||||
|
/* Blocksize of Apple Partition Map
|
||||||
|
May be defined to 512 or 2048 before writer thread starts.
|
||||||
|
*/
|
||||||
|
int apm_block_size;
|
||||||
|
|
||||||
|
/* Allocation block size of HFS+
|
||||||
|
May be defined to 512 or 2048 before hfsplus_writer_create().
|
||||||
|
*/
|
||||||
|
int hfsp_block_size;
|
||||||
|
int hfsp_cat_node_size; /* 2 * apm_block_size */
|
||||||
|
int hfsp_iso_block_fac; /* 2048 / apm_block_size */
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
char *prep_partition;
|
||||||
|
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;
|
||||||
|
|
||||||
|
char *efi_boot_partition;
|
||||||
|
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().
|
||||||
|
*/
|
||||||
|
/* 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];
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BP(a,b) [(b) - (a) + 1]
|
#define BP(a,b) [(b) - (a) + 1]
|
||||||
@ -811,5 +1042,11 @@ struct ecma119_vol_desc_terminator
|
|||||||
uint8_t reserved BP(8, 2048);
|
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);
|
||||||
|
|
||||||
#endif /*LIBISO_ECMA119_H_*/
|
#endif /*LIBISO_ECMA119_H_*/
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* 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
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -32,7 +32,7 @@
|
|||||||
static
|
static
|
||||||
int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name)
|
int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name)
|
||||||
{
|
{
|
||||||
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 *ascii_name;
|
||||||
char *isoname= NULL;
|
char *isoname= NULL;
|
||||||
|
|
||||||
@ -59,6 +59,8 @@ int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name)
|
|||||||
} else {
|
} else {
|
||||||
relaxed = (int)img->allow_lowercase;
|
relaxed = (int)img->allow_lowercase;
|
||||||
}
|
}
|
||||||
|
if (img->allow_7bit_ascii)
|
||||||
|
relaxed |= 4;
|
||||||
if (iso->type == LIBISO_DIR && !(img->allow_dir_id_ext)) {
|
if (iso->type == LIBISO_DIR && !(img->allow_dir_id_ext)) {
|
||||||
if (img->untranslated_name_len > 0) {
|
if (img->untranslated_name_len > 0) {
|
||||||
if (strlen(ascii_name) > img->untranslated_name_len) {
|
if (strlen(ascii_name) > img->untranslated_name_len) {
|
||||||
@ -73,11 +75,22 @@ needs_transl:;
|
|||||||
} else if (img->max_37_char_filenames) {
|
} else if (img->max_37_char_filenames) {
|
||||||
isoname = iso_r_dirid(ascii_name, 37, relaxed);
|
isoname = iso_r_dirid(ascii_name, 37, relaxed);
|
||||||
} else if (img->iso_level == 1) {
|
} else if (img->iso_level == 1) {
|
||||||
|
|
||||||
|
#ifdef Libisofs_old_ecma119_nameS
|
||||||
|
|
||||||
if (relaxed) {
|
if (relaxed) {
|
||||||
isoname = iso_r_dirid(ascii_name, 8, relaxed);
|
isoname = iso_r_dirid(ascii_name, 8, relaxed);
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
if (relaxed) {
|
if (relaxed) {
|
||||||
isoname = iso_r_dirid(ascii_name, 31, relaxed);
|
isoname = iso_r_dirid(ascii_name, 31, relaxed);
|
||||||
@ -94,7 +107,12 @@ needs_transl:;
|
|||||||
} else if (img->max_37_char_filenames) {
|
} else if (img->max_37_char_filenames) {
|
||||||
isoname = iso_r_fileid(ascii_name, 36, relaxed, force_dots);
|
isoname = iso_r_fileid(ascii_name, 36, relaxed, force_dots);
|
||||||
} else if (img->iso_level == 1) {
|
} else if (img->iso_level == 1) {
|
||||||
if (relaxed || !force_dots) {
|
|
||||||
|
#ifdef Libisofs_old_ecma119_nameS
|
||||||
|
|
||||||
|
int max_len;
|
||||||
|
|
||||||
|
if (relaxed) {
|
||||||
if (strchr(ascii_name, '.') == NULL)
|
if (strchr(ascii_name, '.') == NULL)
|
||||||
max_len = 8;
|
max_len = 8;
|
||||||
else
|
else
|
||||||
@ -102,8 +120,15 @@ needs_transl:;
|
|||||||
isoname = iso_r_fileid(ascii_name, max_len, relaxed,
|
isoname = iso_r_fileid(ascii_name, max_len, relaxed,
|
||||||
force_dots);
|
force_dots);
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
if (relaxed || !force_dots) {
|
if (relaxed || !force_dots) {
|
||||||
isoname = iso_r_fileid(ascii_name, 30, relaxed, force_dots);
|
isoname = iso_r_fileid(ascii_name, 30, relaxed, force_dots);
|
||||||
@ -126,6 +151,15 @@ needs_transl:;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ecma119_is_dedicated_reloc_dir(Ecma119Image *img, Ecma119Node *node)
|
||||||
|
{
|
||||||
|
if (img->rr_reloc_node == node &&
|
||||||
|
node != img->root && node != img->partition_root &&
|
||||||
|
(img->rr_reloc_flags & 2))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int create_ecma119_node(Ecma119Image *img, IsoNode *iso, Ecma119Node **node)
|
int create_ecma119_node(Ecma119Image *img, IsoNode *iso, Ecma119Node **node)
|
||||||
{
|
{
|
||||||
@ -299,7 +333,7 @@ void ecma119_node_free(Ecma119Node *node)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (node->type == ECMA119_DIR) {
|
if (node->type == ECMA119_DIR) {
|
||||||
int i;
|
size_t i;
|
||||||
for (i = 0; i < node->info.dir->nchildren; i++) {
|
for (i = 0; i < node->info.dir->nchildren; i++) {
|
||||||
ecma119_node_free(node->info.dir->children[i]);
|
ecma119_node_free(node->info.dir->children[i]);
|
||||||
}
|
}
|
||||||
@ -434,6 +468,15 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree,
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto ex;
|
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 (image->rr_reloc_dir != NULL)
|
||||||
|
if (image->rr_reloc_dir[0] != 0 &&
|
||||||
|
strcmp(iso->name, image->rr_reloc_dir) == 0)
|
||||||
|
image->rr_reloc_node = node;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ret = ISO_SUCCESS;
|
ret = ISO_SUCCESS;
|
||||||
pos = dir->children;
|
pos = dir->children;
|
||||||
@ -643,7 +686,7 @@ int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
|
|||||||
max = max_file_len - digits;
|
max = max_file_len - digits;
|
||||||
}
|
}
|
||||||
name = full_name;
|
name = full_name;
|
||||||
if (max < strlen(name)) {
|
if ((size_t) max < strlen(name)) {
|
||||||
name[max] = '\0';
|
name[max] = '\0';
|
||||||
}
|
}
|
||||||
/* let ext be an empty string */
|
/* let ext be an empty string */
|
||||||
@ -678,8 +721,11 @@ int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
|
|||||||
ret = ISO_OUT_OF_MEM;
|
ret = ISO_OUT_OF_MEM;
|
||||||
goto mangle_cleanup;
|
goto mangle_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Libisofs_extra_verbose_debuG
|
||||||
iso_msg_debug(img->image->id, "\"%s\" renamed to \"%s\"",
|
iso_msg_debug(img->image->id, "\"%s\" renamed to \"%s\"",
|
||||||
children[k]->iso_name, new);
|
children[k]->iso_name, new);
|
||||||
|
#endif
|
||||||
|
|
||||||
iso_htable_remove_ptr(table, children[k]->iso_name, NULL);
|
iso_htable_remove_ptr(table, children[k]->iso_name, NULL);
|
||||||
free(children[k]->iso_name);
|
free(children[k]->iso_name);
|
||||||
@ -750,7 +796,7 @@ int mangle_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int mangle_tree(Ecma119Image *img, int recurse)
|
int mangle_tree(Ecma119Image *img, Ecma119Node *dir, int recurse)
|
||||||
{
|
{
|
||||||
int max_file, max_dir;
|
int max_file, max_dir;
|
||||||
Ecma119Node *root;
|
Ecma119Node *root;
|
||||||
@ -765,7 +811,9 @@ int mangle_tree(Ecma119Image *img, int recurse)
|
|||||||
} else {
|
} else {
|
||||||
max_file = max_dir = 31;
|
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;
|
root = img->partition_root;
|
||||||
} else {
|
} else {
|
||||||
root = img->root;
|
root = img->root;
|
||||||
@ -887,41 +935,61 @@ int reparent(Ecma119Node *child, Ecma119Node *parent)
|
|||||||
* 1 success, < 0 error
|
* 1 success, < 0 error
|
||||||
*/
|
*/
|
||||||
static
|
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;
|
int ret, level, pathlen, newpathlen;
|
||||||
size_t max_path;
|
size_t max_path, i;
|
||||||
Ecma119Node *root;
|
Ecma119Node *reloc, *child;
|
||||||
|
|
||||||
|
/* might change by relocation */
|
||||||
|
level = dir_level;
|
||||||
|
pathlen = dir_pathlen;
|
||||||
|
|
||||||
max_path = pathlen + 1 + max_child_name_len(dir);
|
max_path = pathlen + 1 + max_child_name_len(dir);
|
||||||
|
|
||||||
if (level > 8 || max_path > 255) {
|
if (level > 8 || max_path > 255) {
|
||||||
if (img->eff_partition_offset > 0) {
|
reloc = img->rr_reloc_node;
|
||||||
root = img->partition_root;
|
if (reloc == NULL) {
|
||||||
} else {
|
if (img->eff_partition_offset > 0) {
|
||||||
root = img->root;
|
reloc = img->partition_root;
|
||||||
|
} else {
|
||||||
|
reloc = img->root;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ret = reparent(dir, root);
|
ret = reparent(dir, reloc);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
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)
|
* 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;
|
return ISO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < dir->info.dir->nchildren; i++) {
|
/* dir is now the relocated Ecma119Node */
|
||||||
Ecma119Node *child = dir->info.dir->children[i];
|
pathlen = 37 + 1; /* The dir name might get longer by mangling */
|
||||||
if (child->type == ECMA119_DIR) {
|
level = 2;
|
||||||
int newpathlen = pathlen + 1 + strlen(child->iso_name);
|
if (img->rr_reloc_dir != NULL) {
|
||||||
ret = reorder_tree(img, child, level + 1, newpathlen);
|
pathlen += strlen(img->rr_reloc_node->iso_name) + 1;
|
||||||
if (ret < 0) {
|
if(img->rr_reloc_dir[0] != 0)
|
||||||
return ret;
|
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;
|
return ISO_SUCCESS;
|
||||||
@ -1074,11 +1142,12 @@ int match_hardlinks(Ecma119Image *img, Ecma119Node *dir, int flag)
|
|||||||
iso_node_get_id(nodes[0]->node, &fs_id, &dev_id, &img_ino, 1);
|
iso_node_get_id(nodes[0]->node, &fs_id, &dev_id, &img_ino, 1);
|
||||||
family_start = 0;
|
family_start = 0;
|
||||||
for (i = 1; i < node_count; i++) {
|
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 */
|
/* Still in same ino family */
|
||||||
if (img_ino == 0) { /* Just in case any member knows its img_ino */
|
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);
|
iso_node_get_id(nodes[0]->node, &fs_id, &dev_id, &img_ino, 1);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
family_set_ino(img, nodes, family_start, i, img_ino, prev_ino, 0);
|
family_set_ino(img, nodes, family_start, i, img_ino, prev_ino, 0);
|
||||||
@ -1124,14 +1193,14 @@ int ecma119_tree_create(Ecma119Image *img)
|
|||||||
sort_tree(root);
|
sort_tree(root);
|
||||||
|
|
||||||
iso_msg_debug(img->image->id, "Mangling names...");
|
iso_msg_debug(img->image->id, "Mangling names...");
|
||||||
ret = mangle_tree(img, 1);
|
ret = mangle_tree(img, NULL, 1);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (img->rockridge && !img->allow_deep_paths) {
|
if (img->rockridge && !img->allow_deep_paths) {
|
||||||
|
|
||||||
/* reorder the tree, acording to RRIP, 4.1.5 */
|
/* Relocate deep directories, acording to RRIP, 4.1.5 */
|
||||||
ret = reorder_tree(img, root, 1, 0);
|
ret = reorder_tree(img, root, 1, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
@ -1139,10 +1208,10 @@ int ecma119_tree_create(Ecma119Image *img)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* and we need to remangle the root directory, as the function
|
* 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.
|
* 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) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* Copyright (c) 2007 Vreixo Formoso
|
||||||
|
* 2012 Thomas Schmitt
|
||||||
*
|
*
|
||||||
* This file is part of the libisofs project; you can redistribute it and/or
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -96,5 +97,11 @@ void ecma119_node_free(Ecma119Node *node);
|
|||||||
*/
|
*/
|
||||||
Ecma119Node *ecma119_search_iso_node(Ecma119Image *img, IsoNode *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);
|
||||||
|
|
||||||
|
|
||||||
#endif /*LIBISO_ECMA119_TREE_H_*/
|
#endif /*LIBISO_ECMA119_TREE_H_*/
|
||||||
|
@ -197,14 +197,14 @@ void el_torito_patch_isolinux_image(ElToritoBootImage *bootimg)
|
|||||||
*/
|
*/
|
||||||
int el_torito_set_isolinux_options(ElToritoBootImage *bootimg, int options, int flag)
|
int el_torito_set_isolinux_options(ElToritoBootImage *bootimg, int options, int flag)
|
||||||
{
|
{
|
||||||
bootimg->isolinux_options = (options & 0x03);
|
bootimg->isolinux_options = (options & 0x01ff);
|
||||||
return ISO_SUCCESS;
|
return ISO_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* API */
|
/* API */
|
||||||
int el_torito_get_isolinux_options(ElToritoBootImage *bootimg, int flag)
|
int el_torito_get_isolinux_options(ElToritoBootImage *bootimg, int flag)
|
||||||
{
|
{
|
||||||
return bootimg->isolinux_options & 0x03;
|
return bootimg->isolinux_options & 0x01ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* API */
|
/* API */
|
||||||
@ -239,6 +239,7 @@ int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot)
|
|||||||
IsoBoot *node;
|
IsoBoot *node;
|
||||||
IsoNode **pos;
|
IsoNode **pos;
|
||||||
time_t now;
|
time_t now;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (parent == NULL || name == NULL || boot == NULL) {
|
if (parent == NULL || name == NULL || boot == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
@ -248,9 +249,9 @@ int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check if the name is valid */
|
/* check if the name is valid */
|
||||||
if (!iso_node_is_valid_name(name)) {
|
ret = iso_node_is_valid_name(name);
|
||||||
return ISO_WRONG_ARG_VALUE;
|
if (ret < 0)
|
||||||
}
|
return ret;
|
||||||
|
|
||||||
/* find place where to insert */
|
/* find place where to insert */
|
||||||
pos = &(parent->children);
|
pos = &(parent->children);
|
||||||
@ -274,6 +275,9 @@ int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot)
|
|||||||
free(node);
|
free(node);
|
||||||
return ISO_OUT_OF_MEM;
|
return ISO_OUT_OF_MEM;
|
||||||
}
|
}
|
||||||
|
node->lba = 0;
|
||||||
|
node->size = 0;
|
||||||
|
node->content = NULL;
|
||||||
|
|
||||||
/* atributes from parent */
|
/* atributes from parent */
|
||||||
node->node.mode = S_IFREG | (parent->node.mode & 0444);
|
node->node.mode = S_IFREG | (parent->node.mode & 0444);
|
||||||
@ -383,14 +387,14 @@ int create_image(IsoImage *image, const char *image_path,
|
|||||||
if (ret != sizeof(mbr)) {
|
if (ret != sizeof(mbr)) {
|
||||||
iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
|
iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
|
||||||
"Can't read MBR from image file.");
|
"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 */
|
/* check valid MBR signature */
|
||||||
if ( mbr.sign1 != 0x55 || mbr.sign2 != 0xAA ) {
|
if ( mbr.sign1 != 0x55 || mbr.sign2 != 0xAA ) {
|
||||||
iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
|
iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
|
||||||
"Invalid MBR. Wrong signature.");
|
"Invalid MBR. Wrong signature.");
|
||||||
return ISO_BOOT_IMAGE_NOT_VALID;
|
return (int) ISO_BOOT_IMAGE_NOT_VALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ensure single partition */
|
/* ensure single partition */
|
||||||
@ -486,7 +490,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'",
|
"Cannot find directory for El Torito boot catalog in ISO image: '%s'",
|
||||||
catdir);
|
catdir);
|
||||||
free(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) {
|
if (p->type != LIBISO_DIR) {
|
||||||
free(catdir);
|
free(catdir);
|
||||||
@ -597,6 +601,30 @@ int iso_image_get_boot_image(IsoImage *image, ElToritoBootImage **boot,
|
|||||||
return ISO_SUCCESS;
|
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,
|
int iso_image_get_all_boot_imgs(IsoImage *image, int *num_boots,
|
||||||
ElToritoBootImage ***boots, IsoFile ***bootnodes, int flag)
|
ElToritoBootImage ***boots, IsoFile ***bootnodes, int flag)
|
||||||
{
|
{
|
||||||
@ -759,7 +787,6 @@ write_validation_entry(uint8_t *buf, uint8_t platform_id,
|
|||||||
static void
|
static void
|
||||||
write_section_header(uint8_t *buf, Ecma119Image *t, int idx, int num_entries)
|
write_section_header(uint8_t *buf, Ecma119Image *t, int idx, int num_entries)
|
||||||
{
|
{
|
||||||
int pi;
|
|
||||||
char *id_string;
|
char *id_string;
|
||||||
|
|
||||||
struct el_torito_section_header *e =
|
struct el_torito_section_header *e =
|
||||||
@ -767,7 +794,7 @@ write_section_header(uint8_t *buf, Ecma119Image *t, int idx, int num_entries)
|
|||||||
|
|
||||||
/* 0x90 = more section headers follow , 0x91 = final section */
|
/* 0x90 = more section headers follow , 0x91 = final section */
|
||||||
e->header_indicator[0] = 0x90 + (idx == t->catalog->num_bootimages - 1);
|
e->header_indicator[0] = 0x90 + (idx == t->catalog->num_bootimages - 1);
|
||||||
pi= e->platform_id[0] = t->catalog->bootimages[idx]->platform_id;
|
e->platform_id[0] = t->catalog->bootimages[idx]->platform_id;
|
||||||
e->num_entries[0] = num_entries & 0xff;
|
e->num_entries[0] = num_entries & 0xff;
|
||||||
e->num_entries[1] = (num_entries >> 8) & 0xff;;
|
e->num_entries[1] = (num_entries >> 8) & 0xff;;
|
||||||
id_string = (char *) e->id_string;
|
id_string = (char *) e->id_string;
|
||||||
@ -836,10 +863,10 @@ int catalog_open(IsoStream *stream)
|
|||||||
for (j = i + 1; j < cat->num_bootimages; j++) {
|
for (j = i + 1; j < cat->num_bootimages; j++) {
|
||||||
if (boots[i]->platform_id != boots[j]->platform_id)
|
if (boots[i]->platform_id != boots[j]->platform_id)
|
||||||
break;
|
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])
|
if (boots[i]->id_string[k] != boots[j]->id_string[k])
|
||||||
break;
|
break;
|
||||||
if (k < sizeof(boots[i]->id_string))
|
if (k < (int) sizeof(boots[i]->id_string))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
num_entries = j - i;
|
num_entries = j - i;
|
||||||
@ -895,7 +922,7 @@ int catalog_read(IsoStream *stream, void *buf, size_t count)
|
|||||||
return ISO_FILE_NOT_OPENED;
|
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);
|
memcpy(buf, data->buffer + data->offset, len);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@ -935,7 +962,11 @@ IsoStreamIface catalog_stream_class = {
|
|||||||
catalog_read,
|
catalog_read,
|
||||||
catalog_is_repeatable,
|
catalog_is_repeatable,
|
||||||
catalog_get_id,
|
catalog_get_id,
|
||||||
catalog_free
|
catalog_free,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1001,7 +1032,7 @@ int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* fill fields */
|
/* 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->checksum_index = 0;
|
||||||
file->nsections = 1;
|
file->nsections = 1;
|
||||||
file->sections = calloc(1, sizeof(struct iso_file_section));
|
file->sections = calloc(1, sizeof(struct iso_file_section));
|
||||||
@ -1071,7 +1102,8 @@ int make_boot_info_table(uint8_t *buf, uint32_t pvd_lba,
|
|||||||
* 1 on success, 0 error (but continue), < 0 error
|
* 1 on success, 0 error (but continue), < 0 error
|
||||||
*/
|
*/
|
||||||
static
|
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;
|
int ret;
|
||||||
|
|
||||||
@ -1085,27 +1117,18 @@ int patch_boot_image(uint8_t *buf, Ecma119Image *t, size_t imgsize, int idx)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
/* Patch the boot images if indicated */
|
||||||
int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
|
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;
|
int ret, idx;
|
||||||
size_t size;
|
size_t size;
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
IsoStream *new = NULL;
|
IsoStream *new = NULL;
|
||||||
IsoStream *original = NULL;
|
IsoStream *original = NULL;
|
||||||
|
|
||||||
if (writer == NULL) {
|
if (t->catalog == NULL)
|
||||||
return ISO_NULL_POINTER;
|
return ISO_SUCCESS;
|
||||||
}
|
|
||||||
|
|
||||||
t = writer->target;
|
|
||||||
|
|
||||||
/* Patch the boot image info tables if indicated */
|
|
||||||
for (idx = 0; idx < t->catalog->num_bootimages; idx++) {
|
for (idx = 0; idx < t->catalog->num_bootimages; idx++) {
|
||||||
if (!(t->catalog->bootimages[idx]->isolinux_options & 0x01))
|
if (!(t->catalog->bootimages[idx]->isolinux_options & 0x01))
|
||||||
continue;
|
continue;
|
||||||
@ -1126,12 +1149,12 @@ int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
|
|||||||
}
|
}
|
||||||
ret = iso_stream_read(original, buf, size);
|
ret = iso_stream_read(original, buf, size);
|
||||||
iso_stream_close(original);
|
iso_stream_close(original);
|
||||||
if (ret != size) {
|
if (ret != (int) size) {
|
||||||
return (ret < 0) ? ret : ISO_FILE_READ_ERROR;
|
return (ret < 0) ? ret : (int) ISO_FILE_READ_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ok, patch the read buffer */
|
/* ok, patch the read buffer */
|
||||||
ret = patch_boot_image(buf, t, size, idx);
|
ret = patch_boot_info_table(buf, t, size, idx);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1148,6 +1171,16 @@ int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
|
|||||||
return ISO_SUCCESS;
|
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)
|
* Write the Boot Record Volume Descriptor (ECMA-119, 8.2)
|
||||||
*/
|
*/
|
||||||
@ -1155,7 +1188,6 @@ static
|
|||||||
int eltorito_writer_write_vol_desc(IsoImageWriter *writer)
|
int eltorito_writer_write_vol_desc(IsoImageWriter *writer)
|
||||||
{
|
{
|
||||||
Ecma119Image *t;
|
Ecma119Image *t;
|
||||||
struct el_torito_boot_catalog *cat;
|
|
||||||
struct ecma119_boot_rec_vol_desc vol;
|
struct ecma119_boot_rec_vol_desc vol;
|
||||||
|
|
||||||
if (writer == NULL) {
|
if (writer == NULL) {
|
||||||
@ -1163,7 +1195,6 @@ int eltorito_writer_write_vol_desc(IsoImageWriter *writer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
t = writer->target;
|
t = writer->target;
|
||||||
cat = t->catalog;
|
|
||||||
iso_msg_debug(t->image->id, "Write El-Torito boot record");
|
iso_msg_debug(t->image->id, "Write El-Torito boot record");
|
||||||
|
|
||||||
memset(&vol, 0, sizeof(struct ecma119_boot_rec_vol_desc));
|
memset(&vol, 0, sizeof(struct ecma119_boot_rec_vol_desc));
|
||||||
@ -1192,7 +1223,7 @@ int eltorito_writer_free_data(IsoImageWriter *writer)
|
|||||||
|
|
||||||
int eltorito_writer_create(Ecma119Image *target)
|
int eltorito_writer_create(Ecma119Image *target)
|
||||||
{
|
{
|
||||||
int ret, idx;
|
int ret, idx, outsource_efi = 0;
|
||||||
IsoImageWriter *writer;
|
IsoImageWriter *writer;
|
||||||
IsoFile *bootimg;
|
IsoFile *bootimg;
|
||||||
IsoFileSrc *src;
|
IsoFileSrc *src;
|
||||||
@ -1224,6 +1255,9 @@ int eltorito_writer_create(Ecma119Image *target)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (target->efi_boot_partition != NULL)
|
||||||
|
if (strcmp(target->efi_boot_partition, "--efi-boot-image") == 0)
|
||||||
|
outsource_efi = 1;
|
||||||
for (idx = 0; idx < target->catalog->num_bootimages; idx++) {
|
for (idx = 0; idx < target->catalog->num_bootimages; idx++) {
|
||||||
bootimg = target->catalog->bootimages[idx]->image;
|
bootimg = target->catalog->bootimages[idx]->image;
|
||||||
ret = iso_file_src_create(target, bootimg, &src);
|
ret = iso_file_src_create(target, bootimg, &src);
|
||||||
@ -1234,12 +1268,35 @@ int eltorito_writer_create(Ecma119Image *target)
|
|||||||
|
|
||||||
/* For patching an image, it needs to be copied always */
|
/* For patching an image, it needs to be copied always */
|
||||||
if (target->catalog->bootimages[idx]->isolinux_options & 0x01) {
|
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 */
|
/* we need the bootable volume descriptor */
|
||||||
target->curblock++;
|
target->curblock++;
|
||||||
|
|
||||||
|
if (outsource_efi) {
|
||||||
|
/* Disable EFI Boot partition and complain */
|
||||||
|
free(target->efi_boot_partition);
|
||||||
|
target->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;
|
return ISO_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,14 @@
|
|||||||
struct Iso_Boot
|
struct Iso_Boot
|
||||||
{
|
{
|
||||||
IsoNode node;
|
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 */
|
/* Not more than 32 so that all entries fit into 2048 bytes */
|
||||||
@ -55,8 +63,14 @@ struct el_torito_boot_image {
|
|||||||
* bit 0 -> whether to patch image
|
* bit 0 -> whether to patch image
|
||||||
* bit 1 -> whether to put built-in isolinux 3.72 isohybrid-MBR into image
|
* bit 1 -> whether to put built-in isolinux 3.72 isohybrid-MBR into image
|
||||||
* System Area (deprecated)
|
* 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 type; /**< The type of image */
|
||||||
unsigned char partition_type; /**< type of partition for HD-emul images */
|
unsigned char partition_type; /**< type of partition for HD-emul images */
|
||||||
short load_seg; /**< Load segment for the initial boot image. */
|
short load_seg; /**< Load segment for the initial boot image. */
|
||||||
@ -67,6 +81,7 @@ struct el_torito_boot_image {
|
|||||||
uint8_t platform_id;
|
uint8_t platform_id;
|
||||||
uint8_t id_string[28];
|
uint8_t id_string[28];
|
||||||
uint8_t selection_crit[20];
|
uint8_t selection_crit[20];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** El-Torito, 2.1 */
|
/** El-Torito, 2.1 */
|
||||||
@ -136,5 +151,8 @@ int eltorito_writer_create(Ecma119Image *target);
|
|||||||
int make_boot_info_table(uint8_t *buf, uint32_t pvd_lba,
|
int make_boot_info_table(uint8_t *buf, uint32_t pvd_lba,
|
||||||
uint32_t boot_lba, uint32_t imgsize);
|
uint32_t boot_lba, uint32_t imgsize);
|
||||||
|
|
||||||
|
/* Patch the boot images if indicated.
|
||||||
|
*/
|
||||||
|
int iso_patch_eltoritos(Ecma119Image *t);
|
||||||
|
|
||||||
#endif /* LIBISO_ELTORITO_H */
|
#endif /* LIBISO_ELTORITO_H */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* 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
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -26,6 +26,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
/* <<< */
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifdef Xorriso_standalonE
|
#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 iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret, i;
|
||||||
IsoFileSrc *fsrc;
|
IsoFileSrc *fsrc;
|
||||||
unsigned int fs_id;
|
unsigned int fs_id;
|
||||||
dev_t dev_id;
|
dev_t dev_id;
|
||||||
@ -86,7 +88,7 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* fill key and other atts */
|
/* fill key and other atts */
|
||||||
fsrc->prev_img = file->from_old_session;
|
fsrc->no_write = (file->from_old_session && img->appendable);
|
||||||
if (file->from_old_session && img->appendable) {
|
if (file->from_old_session && img->appendable) {
|
||||||
/*
|
/*
|
||||||
* On multisession discs we keep file sections from old image.
|
* 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 {
|
} else {
|
||||||
fsrc->nsections = 1;
|
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->sort_weight = file->sort_weight;
|
||||||
fsrc->stream = file->stream;
|
fsrc->stream = file->stream;
|
||||||
@ -212,16 +221,15 @@ static int cmp_by_weight(const void *f1, const void *f2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int is_ms_file(void *arg)
|
int shall_be_written(void *arg)
|
||||||
{
|
{
|
||||||
IsoFileSrc *f = (IsoFileSrc *)arg;
|
IsoFileSrc *f = (IsoFileSrc *)arg;
|
||||||
return f->prev_img ? 0 : 1;
|
return f->no_write ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
int filesrc_writer_pre_compute(IsoImageWriter *writer)
|
||||||
int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
|
|
||||||
{
|
{
|
||||||
size_t i, size;
|
size_t i, size, is_external;
|
||||||
Ecma119Image *t;
|
Ecma119Image *t;
|
||||||
IsoFileSrc **filelist;
|
IsoFileSrc **filelist;
|
||||||
int (*inc_item)(void *);
|
int (*inc_item)(void *);
|
||||||
@ -231,10 +239,17 @@ int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
t = writer->target;
|
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->old_empty)
|
||||||
|
t->filesrc_blocks++;
|
||||||
|
|
||||||
/* on appendable images, ms files shouldn't be included */
|
/* on appendable images, ms files shouldn't be included */
|
||||||
if (t->appendable) {
|
if (t->appendable) {
|
||||||
inc_item = is_ms_file;
|
inc_item = shall_be_written;
|
||||||
} else {
|
} else {
|
||||||
inc_item = NULL;
|
inc_item = NULL;
|
||||||
}
|
}
|
||||||
@ -254,10 +269,18 @@ int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
|
|||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < size; ++i) {
|
||||||
int extent = 0;
|
int extent = 0;
|
||||||
IsoFileSrc *file = filelist[i];
|
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) {
|
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);
|
(ISO_EXTENT_SIZE / BLOCK_SIZE);
|
||||||
file->sections[extent].size = ISO_EXTENT_SIZE;
|
file->sections[extent].size = ISO_EXTENT_SIZE;
|
||||||
section_size -= (off_t) ISO_EXTENT_SIZE;
|
section_size -= (off_t) ISO_EXTENT_SIZE;
|
||||||
@ -267,14 +290,29 @@ int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
|
|||||||
* final section
|
* final section
|
||||||
*/
|
*/
|
||||||
if (section_size <= 0) {
|
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 {
|
} else {
|
||||||
file->sections[extent].block =
|
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;
|
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 */
|
/* the list is only needed by this writer, store locally */
|
||||||
@ -282,6 +320,46 @@ int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
|
|||||||
return ISO_SUCCESS;
|
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
|
static
|
||||||
int filesrc_writer_write_vol_desc(IsoImageWriter *writer)
|
int filesrc_writer_write_vol_desc(IsoImageWriter *writer)
|
||||||
{
|
{
|
||||||
@ -324,123 +402,177 @@ int filesrc_make_md5(Ecma119Image *t, IsoFileSrc *file, char md5[16], int flag)
|
|||||||
return iso_stream_make_md5(file->stream, md5, 0);
|
return iso_stream_make_md5(file->stream, md5, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
/* name must be NULL or offer at least PATH_MAX characters.
|
||||||
int filesrc_writer_write_data(IsoImageWriter *writer)
|
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;
|
int res, ret, was_error;
|
||||||
size_t i, b;
|
char *name_data = NULL;
|
||||||
Ecma119Image *t;
|
char *buffer_data = NULL;
|
||||||
IsoFileSrc *file;
|
size_t b;
|
||||||
IsoFileSrc **filelist;
|
|
||||||
char name[PATH_MAX];
|
|
||||||
char buffer[BLOCK_SIZE];
|
|
||||||
off_t file_size;
|
off_t file_size;
|
||||||
uint32_t nblocks;
|
uint32_t nblocks;
|
||||||
void *ctx= NULL;
|
void *ctx= NULL;
|
||||||
char md5[16], pre_md5[16];
|
char md5[16], pre_md5[16];
|
||||||
int pre_md5_valid = 0;
|
int pre_md5_valid = 0;
|
||||||
|
IsoStream *stream, *inp;
|
||||||
|
|
||||||
#ifdef Libisofs_with_libjtE
|
#ifdef Libisofs_with_libjtE
|
||||||
int jte_begun = 0;
|
int jte_begun = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (writer == NULL) {
|
if (name == NULL) {
|
||||||
return ISO_ASSERT_FAILURE;
|
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;
|
was_error = 0;
|
||||||
filelist = writer->data;
|
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_msg_debug(t->image->id, "Writing Files...");
|
/* Get file name from end of filter chain */
|
||||||
|
for (stream = file->stream; ; stream = inp) {
|
||||||
i = 0;
|
inp = iso_stream_get_input_stream(stream, 0);
|
||||||
while ((file = filelist[i++]) != NULL) {
|
if (inp == NULL)
|
||||||
was_error = 0;
|
break;
|
||||||
file_size = iso_file_src_get_size(file);
|
}
|
||||||
nblocks = DIV_UP(file_size, BLOCK_SIZE);
|
iso_stream_get_file_name(stream, name);
|
||||||
pre_md5_valid = 0;
|
if (res < 0) {
|
||||||
if (file->checksum_index > 0 && (t->md5_file_checksums & 2)) {
|
/*
|
||||||
/* Obtain an MD5 of content by a first read pass */
|
* UPS, very ugly error, the best we can do is just to write
|
||||||
pre_md5_valid = filesrc_make_md5(t, file, pre_md5, 0);
|
* 0's to image
|
||||||
}
|
*/
|
||||||
res = filesrc_open(file);
|
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
|
||||||
iso_stream_get_file_name(file->stream, name);
|
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) {
|
if (res < 0) {
|
||||||
/*
|
ret = res; /* aborted due to error severity */
|
||||||
* UPS, very ugly error, the best we can do is just to write
|
goto ex;
|
||||||
* 0's to image
|
}
|
||||||
*/
|
memset(buffer, 0, BLOCK_SIZE);
|
||||||
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
|
for (b = 0; b < nblocks; ++b) {
|
||||||
was_error = 1;
|
res = iso_write(t, buffer, BLOCK_SIZE);
|
||||||
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) {
|
if (res < 0) {
|
||||||
ret = res; /* aborted due to error severity */
|
/* ko, writer error, we need to go out! */
|
||||||
goto ex;
|
ret = res;
|
||||||
}
|
|
||||||
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 */
|
|
||||||
goto ex;
|
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
|
#ifdef LIBISOFS_VERBOSE_DEBUG
|
||||||
else {
|
else {
|
||||||
iso_msg_debug(t->image->id, "Writing file %s", name);
|
iso_msg_debug(t->image->id, "Writing file %s", name);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* >>> HFS: need to align to allocation block size */;
|
||||||
|
|
||||||
#ifdef Libisofs_with_libjtE
|
#ifdef Libisofs_with_libjtE
|
||||||
if (t->libjte_handle != NULL) {
|
if (t->libjte_handle != NULL) {
|
||||||
res = libjte_begin_data_file(t->libjte_handle, name,
|
res = libjte_begin_data_file(t->libjte_handle, name,
|
||||||
BLOCK_SIZE, file_size);
|
BLOCK_SIZE, file_size);
|
||||||
if (res <= 0) {
|
if (res <= 0) {
|
||||||
res = iso_libjte_forward_msgs(t->libjte_handle, t->image->id,
|
res = iso_libjte_forward_msgs(t->libjte_handle, t->image->id,
|
||||||
ISO_LIBJTE_FILE_FAILED, 0);
|
ISO_LIBJTE_FILE_FAILED, 0);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
filesrc_close(file);
|
filesrc_close(file);
|
||||||
ret = ISO_LIBJTE_FILE_FAILED;
|
ret = ISO_LIBJTE_FILE_FAILED;
|
||||||
goto ex;
|
goto ex;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
jte_begun = 1;
|
|
||||||
}
|
}
|
||||||
|
jte_begun = 1;
|
||||||
|
}
|
||||||
#endif /* Libisofs_with_libjtE */
|
#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) {
|
if (file->checksum_index > 0) {
|
||||||
/* initialize file checksum */
|
/* Add to file checksum */
|
||||||
res = iso_md5_start(&ctx);
|
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)
|
if (res <= 0)
|
||||||
file->checksum_index = 0;
|
file->checksum_index = 0;
|
||||||
}
|
}
|
||||||
/* write file contents to image */
|
}
|
||||||
for (b = 0; b < nblocks; ++b) {
|
|
||||||
int wres;
|
filesrc_close(file);
|
||||||
res = filesrc_read(file, buffer, BLOCK_SIZE);
|
|
||||||
|
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) {
|
if (res < 0) {
|
||||||
/* read error */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
wres = iso_write(t, buffer, BLOCK_SIZE);
|
|
||||||
if (wres < 0) {
|
|
||||||
/* ko, writer error, we need to go out! */
|
/* ko, writer error, we need to go out! */
|
||||||
filesrc_close(file);
|
ret = res;
|
||||||
ret = wres;
|
|
||||||
goto ex;
|
goto ex;
|
||||||
}
|
}
|
||||||
if (file->checksum_index > 0) {
|
if (file->checksum_index > 0) {
|
||||||
@ -454,89 +586,30 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
|||||||
file->checksum_index = 0;
|
file->checksum_index = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
filesrc_close(file);
|
if (file->checksum_index > 0 &&
|
||||||
|
file->checksum_index <= t->checksum_idx_counter) {
|
||||||
if (b < nblocks) {
|
/* Obtain checksum and dispose checksum context */
|
||||||
/* premature end of file, due to error or eof */
|
res = iso_md5_end(&ctx, md5);
|
||||||
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
|
if (res <= 0)
|
||||||
was_error = 1;
|
file->checksum_index = 0;
|
||||||
if (res < 0) {
|
if ((t->md5_file_checksums & 2) && pre_md5_valid > 0 &&
|
||||||
/* error */
|
!was_error) {
|
||||||
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
|
if (! iso_md5_match(md5, pre_md5)) {
|
||||||
"Read error in file %s.", name);
|
/* Issue MISHAP event */
|
||||||
} else {
|
iso_report_errfile(name, ISO_MD5_STREAM_CHANGE, 0, 0);
|
||||||
/* eof */
|
was_error = 1;
|
||||||
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
|
res = iso_msg_submit(t->image->id, ISO_MD5_STREAM_CHANGE,0,
|
||||||
"Premature end of file %s.", name);
|
"Content of file '%s' changed while it was written into the image.",
|
||||||
}
|
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) {
|
if (res < 0) {
|
||||||
/* ko, writer error, we need to go out! */
|
ret = res; /* aborted due to error severity */
|
||||||
ret = res;
|
|
||||||
goto ex;
|
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 &&
|
/* Write md5 into checksum buffer at file->checksum_index */
|
||||||
file->checksum_index <= t->checksum_idx_counter) {
|
memcpy(t->checksum_buffer + 16 * file->checksum_index, md5, 16);
|
||||||
/* 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 */
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ISO_SUCCESS;
|
ret = ISO_SUCCESS;
|
||||||
@ -546,15 +619,75 @@ ex:;
|
|||||||
|
|
||||||
#ifdef Libisofs_with_libjtE
|
#ifdef Libisofs_with_libjtE
|
||||||
if (jte_begun) {
|
if (jte_begun) {
|
||||||
libjte_end_data_file(t->libjte_handle);
|
res = libjte_end_data_file(t->libjte_handle);
|
||||||
iso_libjte_forward_msgs(t->libjte_handle, t->image->id,
|
iso_libjte_forward_msgs(t->libjte_handle, t->image->id,
|
||||||
ISO_LIBJTE_END_FAILED, 0);
|
ISO_LIBJTE_END_FAILED, 0);
|
||||||
|
if (res <= 0 && ret >= 0)
|
||||||
|
ret = ISO_LIBJTE_FILE_FAILED;
|
||||||
}
|
}
|
||||||
#endif /* Libisofs_with_libjtE */
|
#endif /* Libisofs_with_libjtE */
|
||||||
|
|
||||||
|
LIBISO_FREE_MEM(buffer_data);
|
||||||
|
LIBISO_FREE_MEM(name_data);
|
||||||
return ret;
|
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->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
|
static
|
||||||
int filesrc_writer_free_data(IsoImageWriter *writer)
|
int filesrc_writer_free_data(IsoImageWriter *writer)
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* Copyright (c) 2007 Vreixo Formoso
|
||||||
|
* 2012 Thomas Schmitt
|
||||||
*
|
*
|
||||||
* This file is part of the libisofs project; you can redistribute it and/or
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -13,14 +14,41 @@
|
|||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "ecma119.h"
|
#include "ecma119.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_STDINT_H
|
||||||
#include <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
|
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;
|
||||||
|
|
||||||
unsigned int checksum_index :31;
|
unsigned int checksum_index :31;
|
||||||
|
|
||||||
/** File Sections of the file in the image */
|
/** 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;
|
struct iso_file_section *sections;
|
||||||
int nsections;
|
int nsections;
|
||||||
|
|
||||||
@ -87,4 +115,21 @@ off_t iso_file_src_get_size(IsoFileSrc *file);
|
|||||||
*/
|
*/
|
||||||
int iso_file_src_writer_create(Ecma119Image *target);
|
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_*/
|
#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
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -20,6 +20,7 @@
|
|||||||
#include "../libisofs.h"
|
#include "../libisofs.h"
|
||||||
#include "../filter.h"
|
#include "../filter.h"
|
||||||
#include "../fsource.h"
|
#include "../fsource.h"
|
||||||
|
#include "../stream.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
@ -40,7 +41,7 @@
|
|||||||
* for classical pipe filtering.
|
* 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.
|
* 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;
|
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
|
static
|
||||||
int extf_cmp_ino(IsoStream *s1, IsoStream *s2);
|
int extf_cmp_ino(IsoStream *s1, IsoStream *s2);
|
||||||
@ -605,7 +636,7 @@ int extf_cmp_ino(IsoStream *s1, IsoStream *s2);
|
|||||||
|
|
||||||
|
|
||||||
IsoStreamIface extf_stream_class = {
|
IsoStreamIface extf_stream_class = {
|
||||||
3,
|
4,
|
||||||
"extf",
|
"extf",
|
||||||
extf_stream_open,
|
extf_stream_open,
|
||||||
extf_stream_close,
|
extf_stream_close,
|
||||||
@ -616,7 +647,8 @@ IsoStreamIface extf_stream_class = {
|
|||||||
extf_stream_free,
|
extf_stream_free,
|
||||||
extf_update_size,
|
extf_update_size,
|
||||||
extf_get_input_stream,
|
extf_get_input_stream,
|
||||||
extf_cmp_ino
|
extf_cmp_ino,
|
||||||
|
extf_clone_stream
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -25,6 +25,7 @@
|
|||||||
#include "../filter.h"
|
#include "../filter.h"
|
||||||
#include "../fsource.h"
|
#include "../fsource.h"
|
||||||
#include "../util.h"
|
#include "../util.h"
|
||||||
|
#include "../stream.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
@ -153,6 +154,7 @@ static int gzip_compression_level = 6;
|
|||||||
/*
|
/*
|
||||||
* The data payload of an individual Gzip Filter IsoStream
|
* The data payload of an individual Gzip Filter IsoStream
|
||||||
*/
|
*/
|
||||||
|
/* IMPORTANT: Any change must be reflected by gzip_clone_stream() */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
IsoStream *orig;
|
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) {
|
if (cnv_ret == Z_STREAM_ERROR || cnv_ret == Z_BUF_ERROR) {
|
||||||
return (rng->error_ret = ISO_ZLIB_COMPR_ERR);
|
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 */
|
break; /* output is available */
|
||||||
if (strm->avail_in == 0) /* all pending input consumed */
|
if (strm->avail_in == 0) /* all pending input consumed */
|
||||||
break;
|
break;
|
||||||
@ -529,12 +531,51 @@ 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
|
static
|
||||||
int gzip_cmp_ino(IsoStream *s1, IsoStream *s2);
|
int gzip_cmp_ino(IsoStream *s1, IsoStream *s2);
|
||||||
|
|
||||||
|
|
||||||
IsoStreamIface gzip_stream_compress_class = {
|
IsoStreamIface gzip_stream_compress_class = {
|
||||||
3,
|
4,
|
||||||
"gzip",
|
"gzip",
|
||||||
gzip_stream_open,
|
gzip_stream_open,
|
||||||
gzip_stream_close,
|
gzip_stream_close,
|
||||||
@ -545,12 +586,13 @@ IsoStreamIface gzip_stream_compress_class = {
|
|||||||
gzip_stream_free,
|
gzip_stream_free,
|
||||||
gzip_update_size,
|
gzip_update_size,
|
||||||
gzip_get_input_stream,
|
gzip_get_input_stream,
|
||||||
gzip_cmp_ino
|
gzip_cmp_ino,
|
||||||
|
gzip_clone_stream
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
IsoStreamIface gzip_stream_uncompress_class = {
|
IsoStreamIface gzip_stream_uncompress_class = {
|
||||||
3,
|
4,
|
||||||
"pizg",
|
"pizg",
|
||||||
gzip_stream_open,
|
gzip_stream_open,
|
||||||
gzip_stream_close,
|
gzip_stream_close,
|
||||||
@ -561,7 +603,8 @@ IsoStreamIface gzip_stream_uncompress_class = {
|
|||||||
gzip_stream_free,
|
gzip_stream_free,
|
||||||
gzip_update_size,
|
gzip_update_size,
|
||||||
gzip_get_input_stream,
|
gzip_get_input_stream,
|
||||||
gzip_cmp_ino
|
gzip_cmp_ino,
|
||||||
|
gzip_clone_stream
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -22,6 +22,7 @@
|
|||||||
#include "../filter.h"
|
#include "../filter.h"
|
||||||
#include "../fsource.h"
|
#include "../fsource.h"
|
||||||
#include "../util.h"
|
#include "../util.h"
|
||||||
|
#include "../stream.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
@ -167,6 +168,7 @@ static int ziso_compression_level = 6;
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* The common data payload of an individual Zisofs Filter IsoStream
|
* The common data payload of an individual Zisofs Filter IsoStream
|
||||||
|
* IMPORTANT: Any change must be reflected by ziso_clone_stream().
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -183,6 +185,7 @@ typedef struct
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* The data payload of an individual Zisofs Filter Compressor IsoStream
|
* The data payload of an individual Zisofs Filter Compressor IsoStream
|
||||||
|
* IMPORTANT: Any change must be reflected by ziso_clone_stream().
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -198,6 +201,7 @@ typedef struct
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* The data payload of an individual Zisofs Filter Uncompressor IsoStream
|
* The data payload of an individual Zisofs Filter Uncompressor IsoStream
|
||||||
|
* IMPORTANT: Any change must be reflected by ziso_clone_stream().
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -572,7 +576,8 @@ int ziso_stream_uncompress(IsoStream *stream, void *buf, size_t desired)
|
|||||||
rng->block_pointers[i] =
|
rng->block_pointers[i] =
|
||||||
iso_read_lsb((uint8_t *) (rng->block_pointers + i), 4);
|
iso_read_lsb((uint8_t *) (rng->block_pointers + i), 4);
|
||||||
if (i > 0)
|
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)
|
||||||
block_max = rng->block_pointers[i]
|
block_max = rng->block_pointers[i]
|
||||||
- rng->block_pointers[i - 1];
|
- rng->block_pointers[i - 1];
|
||||||
@ -615,7 +620,7 @@ int ziso_stream_uncompress(IsoStream *stream, void *buf, size_t desired)
|
|||||||
if (ret != Z_OK)
|
if (ret != Z_OK)
|
||||||
return (rng->error_ret = ISO_ZLIB_COMPR_ERR);
|
return (rng->error_ret = ISO_ZLIB_COMPR_ERR);
|
||||||
rng->buffer_fill = buf_len;
|
rng->buffer_fill = buf_len;
|
||||||
if (buf_len < rng->block_size &&
|
if ((int) buf_len < rng->block_size &&
|
||||||
i != rng->block_pointer_fill - 1)
|
i != rng->block_pointer_fill - 1)
|
||||||
return (rng->error_ret = ISO_ZISOFS_WRONG_INPUT);
|
return (rng->error_ret = ISO_ZISOFS_WRONG_INPUT);
|
||||||
} else if(ret == 0) {
|
} else if(ret == 0) {
|
||||||
@ -779,13 +784,63 @@ IsoStream *ziso_get_input_stream(IsoStream *stream, int flag)
|
|||||||
return data->orig;
|
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
|
static
|
||||||
int ziso_cmp_ino(IsoStream *s1, IsoStream *s2);
|
int ziso_cmp_ino(IsoStream *s1, IsoStream *s2);
|
||||||
|
|
||||||
|
|
||||||
IsoStreamIface ziso_stream_compress_class = {
|
IsoStreamIface ziso_stream_compress_class = {
|
||||||
3,
|
4,
|
||||||
"ziso",
|
"ziso",
|
||||||
ziso_stream_open,
|
ziso_stream_open,
|
||||||
ziso_stream_close,
|
ziso_stream_close,
|
||||||
@ -796,12 +851,13 @@ IsoStreamIface ziso_stream_compress_class = {
|
|||||||
ziso_stream_free,
|
ziso_stream_free,
|
||||||
ziso_update_size,
|
ziso_update_size,
|
||||||
ziso_get_input_stream,
|
ziso_get_input_stream,
|
||||||
ziso_cmp_ino
|
ziso_cmp_ino,
|
||||||
|
ziso_clone_stream
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
IsoStreamIface ziso_stream_uncompress_class = {
|
IsoStreamIface ziso_stream_uncompress_class = {
|
||||||
3,
|
4,
|
||||||
"osiz",
|
"osiz",
|
||||||
ziso_stream_open,
|
ziso_stream_open,
|
||||||
ziso_stream_close,
|
ziso_stream_close,
|
||||||
@ -812,7 +868,8 @@ IsoStreamIface ziso_stream_uncompress_class = {
|
|||||||
ziso_stream_free,
|
ziso_stream_free,
|
||||||
ziso_update_size,
|
ziso_update_size,
|
||||||
ziso_get_input_stream,
|
ziso_get_input_stream,
|
||||||
ziso_cmp_ino
|
ziso_cmp_ino,
|
||||||
|
ziso_clone_stream
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,11 +141,12 @@ void update_next(IsoDirIter *iter)
|
|||||||
static
|
static
|
||||||
int find_iter_next(IsoDirIter *iter, IsoNode **node)
|
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) {
|
if (iter == NULL || node == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
data = iter->data;
|
||||||
|
|
||||||
if (data->err < 0) {
|
if (data->err < 0) {
|
||||||
return data->err;
|
return data->err;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* 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
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -39,7 +39,7 @@ int iso_file_source_new_lfs(IsoFileSource *parent, const char *name,
|
|||||||
*/
|
*/
|
||||||
IsoFilesystem *lfs= NULL;
|
IsoFilesystem *lfs= NULL;
|
||||||
|
|
||||||
|
/* IMPORTANT: Any change must be reflected by lfs_clone_src() */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
/** reference to the parent (if root it points to itself) */
|
/** reference to the parent (if root it points to itself) */
|
||||||
@ -95,14 +95,14 @@ char* lfs_get_name(IsoFileSource *src)
|
|||||||
static
|
static
|
||||||
int lfs_lstat(IsoFileSource *src, struct stat *info)
|
int lfs_lstat(IsoFileSource *src, struct stat *info)
|
||||||
{
|
{
|
||||||
_LocalFsFileSource *data;
|
|
||||||
char *path;
|
char *path;
|
||||||
|
|
||||||
if (src == NULL || info == NULL) {
|
if (src == NULL || info == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
}
|
}
|
||||||
data = src->data;
|
|
||||||
path = lfs_get_path(src);
|
path = lfs_get_path(src);
|
||||||
|
if (path == NULL)
|
||||||
|
return ISO_OUT_OF_MEM;
|
||||||
|
|
||||||
if (lstat(path, info) != 0) {
|
if (lstat(path, info) != 0) {
|
||||||
int err;
|
int err;
|
||||||
@ -128,6 +128,7 @@ int lfs_lstat(IsoFileSource *src, struct stat *info)
|
|||||||
err = ISO_FILE_ERROR;
|
err = ISO_FILE_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
free(path);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
free(path);
|
free(path);
|
||||||
@ -137,14 +138,14 @@ int lfs_lstat(IsoFileSource *src, struct stat *info)
|
|||||||
static
|
static
|
||||||
int lfs_stat(IsoFileSource *src, struct stat *info)
|
int lfs_stat(IsoFileSource *src, struct stat *info)
|
||||||
{
|
{
|
||||||
_LocalFsFileSource *data;
|
|
||||||
char *path;
|
char *path;
|
||||||
|
|
||||||
if (src == NULL || info == NULL) {
|
if (src == NULL || info == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
}
|
}
|
||||||
data = src->data;
|
|
||||||
path = lfs_get_path(src);
|
path = lfs_get_path(src);
|
||||||
|
if (path == NULL)
|
||||||
|
return ISO_OUT_OF_MEM;
|
||||||
|
|
||||||
if (stat(path, info) != 0) {
|
if (stat(path, info) != 0) {
|
||||||
int err;
|
int err;
|
||||||
@ -170,6 +171,7 @@ int lfs_stat(IsoFileSource *src, struct stat *info)
|
|||||||
err = ISO_FILE_ERROR;
|
err = ISO_FILE_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
free(path);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
free(path);
|
free(path);
|
||||||
@ -180,13 +182,11 @@ static
|
|||||||
int lfs_access(IsoFileSource *src)
|
int lfs_access(IsoFileSource *src)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
_LocalFsFileSource *data;
|
|
||||||
char *path;
|
char *path;
|
||||||
|
|
||||||
if (src == NULL) {
|
if (src == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
}
|
}
|
||||||
data = src->data;
|
|
||||||
path = lfs_get_path(src);
|
path = lfs_get_path(src);
|
||||||
|
|
||||||
ret = iso_eaccess(path);
|
ret = iso_eaccess(path);
|
||||||
@ -412,8 +412,7 @@ int lfs_readdir(IsoFileSource *src, IsoFileSource **child)
|
|||||||
static
|
static
|
||||||
int lfs_readlink(IsoFileSource *src, char *buf, size_t bufsiz)
|
int lfs_readlink(IsoFileSource *src, char *buf, size_t bufsiz)
|
||||||
{
|
{
|
||||||
int size;
|
int size, ret;
|
||||||
_LocalFsFileSource *data;
|
|
||||||
char *path;
|
char *path;
|
||||||
|
|
||||||
if (src == NULL || buf == NULL) {
|
if (src == NULL || buf == NULL) {
|
||||||
@ -424,14 +423,13 @@ int lfs_readlink(IsoFileSource *src, char *buf, size_t bufsiz)
|
|||||||
return ISO_WRONG_ARG_VALUE;
|
return ISO_WRONG_ARG_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = src->data;
|
|
||||||
path = lfs_get_path(src);
|
path = lfs_get_path(src);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* invoke readlink, with bufsiz -1 to reserve an space for
|
* invoke readlink, with bufsiz -1 to reserve an space for
|
||||||
* the NULL character
|
* the NULL character
|
||||||
*/
|
*/
|
||||||
size = readlink(path, buf, bufsiz - 1);
|
size = readlink(path, buf, bufsiz);
|
||||||
free(path);
|
free(path);
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
/* error */
|
/* error */
|
||||||
@ -455,8 +453,13 @@ int lfs_readlink(IsoFileSource *src, char *buf, size_t bufsiz)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* NULL-terminate the buf */
|
/* NULL-terminate the buf */
|
||||||
|
ret = ISO_SUCCESS;
|
||||||
|
if ((size_t) size >= bufsiz) {
|
||||||
|
ret = ISO_RR_PATH_TOO_LONG;
|
||||||
|
size = bufsiz - 1;
|
||||||
|
}
|
||||||
buf[size] = '\0';
|
buf[size] = '\0';
|
||||||
return ISO_SUCCESS;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -492,9 +495,6 @@ int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag)
|
|||||||
size_t num_attrs = 0, *value_lengths = NULL, result_len, sret;
|
size_t num_attrs = 0, *value_lengths = NULL, result_len, sret;
|
||||||
char *path = NULL, **names = NULL, **values = NULL;
|
char *path = NULL, **names = NULL, **values = NULL;
|
||||||
unsigned char *result = NULL;
|
unsigned char *result = NULL;
|
||||||
_LocalFsFileSource *data;
|
|
||||||
|
|
||||||
data = src->data;
|
|
||||||
|
|
||||||
*aa_string = NULL;
|
*aa_string = NULL;
|
||||||
|
|
||||||
@ -506,11 +506,18 @@ int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag)
|
|||||||
to AAIP ACL representation. Clean out st_mode ACL entries.
|
to AAIP ACL representation. Clean out st_mode ACL entries.
|
||||||
*/
|
*/
|
||||||
path = iso_file_source_get_path(src);
|
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,
|
ret = aaip_get_attr_list(path, &num_attrs, &names,
|
||||||
&value_lengths, &values,
|
&value_lengths, &values,
|
||||||
(!(flag & 2)) | 2 | (flag & 4) | 16);
|
(!(flag & 2)) | 2 | (flag & 4) | 16);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
ret = ISO_FILE_ERROR;
|
if (ret == -2)
|
||||||
|
ret = ISO_AAIP_NO_GET_LOCAL;
|
||||||
|
else
|
||||||
|
ret = ISO_FILE_ERROR;
|
||||||
goto ex;
|
goto ex;
|
||||||
}
|
}
|
||||||
if (num_attrs == 0)
|
if (num_attrs == 0)
|
||||||
@ -534,10 +541,56 @@ ex:;
|
|||||||
return ret;
|
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 = {
|
IsoFileSourceIface lfs_class = {
|
||||||
|
|
||||||
1, /* version */
|
2, /* version */
|
||||||
lfs_get_path,
|
lfs_get_path,
|
||||||
lfs_get_name,
|
lfs_get_name,
|
||||||
lfs_lstat,
|
lfs_lstat,
|
||||||
@ -551,7 +604,8 @@ IsoFileSourceIface lfs_class = {
|
|||||||
lfs_get_filesystem,
|
lfs_get_filesystem,
|
||||||
lfs_free,
|
lfs_free,
|
||||||
lfs_lseek,
|
lfs_lseek,
|
||||||
lfs_get_aa_string
|
lfs_get_aa_string,
|
||||||
|
lfs_clone_src
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -765,6 +819,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 iso_local_get_acl_text(char *disk_path, char **text, int flag)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -805,13 +868,19 @@ int iso_local_set_attrs(char *disk_path, size_t num_attrs, char **names,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = aaip_set_attr_list(disk_path, num_attrs, names, value_lengths,
|
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 <= 0) {
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
return ISO_OUT_OF_MEM;
|
return ISO_OUT_OF_MEM;
|
||||||
if (ret == -2)
|
if (ret == -2)
|
||||||
return ISO_AAIP_BAD_AASTRING;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* 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
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -33,9 +33,16 @@
|
|||||||
int iso_local_filesystem_new(IsoFilesystem **fs);
|
int iso_local_filesystem_new(IsoFilesystem **fs);
|
||||||
|
|
||||||
|
|
||||||
/* Rank two IsoFileSource by their eventual old image LBAs.
|
/* Rank two IsoFileSource of ifs_class by their eventual old image LBAs.
|
||||||
Other IsoFileSource classes will be ranked only roughly.
|
Other IsoFileSource classes will be ranked only roughly.
|
||||||
*/
|
*/
|
||||||
int iso_ifs_sections_cmp(IsoFileSource *s1, IsoFileSource *s2, int flag);
|
int iso_ifs_sections_cmp(IsoFileSource *s1, IsoFileSource *s2, 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_*/
|
#endif /*LIBISO_FSOURCE_H_*/
|
||||||
|
1844
libisofs/hfsplus.c
Normal file
1844
libisofs/hfsplus.c
Normal file
File diff suppressed because it is too large
Load Diff
197
libisofs/hfsplus.h
Normal file
197
libisofs/hfsplus.h
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* 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[];
|
||||||
|
|
||||||
|
#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
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* 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
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -32,7 +32,7 @@
|
|||||||
* @param image
|
* @param image
|
||||||
* Location where the image pointer will be stored.
|
* Location where the image pointer will be stored.
|
||||||
* @return
|
* @return
|
||||||
* 1 sucess, < 0 error
|
* 1 success, < 0 error
|
||||||
*/
|
*/
|
||||||
int iso_image_new(const char *name, IsoImage **image)
|
int iso_image_new(const char *name, IsoImage **image)
|
||||||
{
|
{
|
||||||
@ -93,6 +93,9 @@ int iso_image_new(const char *name, IsoImage **image)
|
|||||||
img->checksum_idx_count = 0;
|
img->checksum_idx_count = 0;
|
||||||
img->checksum_array = NULL;
|
img->checksum_array = NULL;
|
||||||
img->generator_is_running = 0;
|
img->generator_is_running = 0;
|
||||||
|
for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++)
|
||||||
|
img->hfsplus_blessed[i] = NULL;
|
||||||
|
|
||||||
*image = img;
|
*image = img;
|
||||||
return ISO_SUCCESS;
|
return ISO_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -112,20 +115,22 @@ void iso_image_ref(IsoImage *image)
|
|||||||
*/
|
*/
|
||||||
void iso_image_unref(IsoImage *image)
|
void iso_image_unref(IsoImage *image)
|
||||||
{
|
{
|
||||||
if (--image->refcount == 0) {
|
int nexcl, i;
|
||||||
int nexcl;
|
|
||||||
|
|
||||||
|
if (--image->refcount == 0) {
|
||||||
/* we need to free the image */
|
/* we need to free the image */
|
||||||
|
|
||||||
if (image->user_data_free != NULL) {
|
if (image->user_data_free != NULL) {
|
||||||
/* free attached data */
|
/* free attached data */
|
||||||
image->user_data_free(image->user_data);
|
image->user_data_free(image->user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (nexcl = 0; nexcl < image->nexcludes; ++nexcl) {
|
for (nexcl = 0; nexcl < image->nexcludes; ++nexcl) {
|
||||||
free(image->excludes[nexcl]);
|
free(image->excludes[nexcl]);
|
||||||
}
|
}
|
||||||
free(image->excludes);
|
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_unref((IsoNode*)image->root);
|
||||||
iso_node_builder_unref(image->builder);
|
iso_node_builder_unref(image->builder);
|
||||||
iso_filesystem_unref(image->fs);
|
iso_filesystem_unref(image->fs);
|
||||||
@ -142,6 +147,8 @@ void iso_image_unref(IsoImage *image)
|
|||||||
free(image->biblio_file_id);
|
free(image->biblio_file_id);
|
||||||
if (image->used_inodes != NULL)
|
if (image->used_inodes != NULL)
|
||||||
free(image->used_inodes);
|
free(image->used_inodes);
|
||||||
|
if (image->system_area_data != NULL)
|
||||||
|
free(image->system_area_data);
|
||||||
iso_image_free_checksums(image, 0);
|
iso_image_free_checksums(image, 0);
|
||||||
free(image);
|
free(image);
|
||||||
}
|
}
|
||||||
@ -655,3 +662,73 @@ int iso_image_give_up_mips_boot(IsoImage *image, int flag)
|
|||||||
image->num_mips_boot_files = 0;
|
image->num_mips_boot_files = 0;
|
||||||
return ISO_SUCCESS;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* 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
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -180,6 +180,13 @@ struct Iso_Image
|
|||||||
*/
|
*/
|
||||||
int generator_is_running;
|
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];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* Copyright (c) 2007 Vreixo Formoso
|
||||||
|
* Copyright (c) 2011-2012 Thomas Schmitt
|
||||||
*
|
*
|
||||||
* This file is part of the libisofs project; you can redistribute it and/or
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -17,6 +18,8 @@
|
|||||||
#include "image.h"
|
#include "image.h"
|
||||||
#include "filesrc.h"
|
#include "filesrc.h"
|
||||||
#include "eltorito.h"
|
#include "eltorito.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "ecma119.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -73,7 +76,7 @@ void iso1999_node_free(Iso1999Node *node)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (node->type == ISO1999_DIR) {
|
if (node->type == ISO1999_DIR) {
|
||||||
int i;
|
size_t i;
|
||||||
for (i = 0; i < node->info.dir->nchildren; i++) {
|
for (i = 0; i < node->info.dir->nchildren; i++) {
|
||||||
iso1999_node_free(node->info.dir->children[i]);
|
iso1999_node_free(node->info.dir->children[i]);
|
||||||
}
|
}
|
||||||
@ -307,7 +310,10 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
|
|||||||
Iso1999Node **children;
|
Iso1999Node **children;
|
||||||
IsoHTable *table;
|
IsoHTable *table;
|
||||||
int need_sort = 0;
|
int need_sort = 0;
|
||||||
|
char *full_name = NULL, *tmp = NULL;
|
||||||
|
|
||||||
|
LIBISO_ALLOC_MEM(full_name, char, 208);
|
||||||
|
LIBISO_ALLOC_MEM(tmp, char, 208);
|
||||||
nchildren = dir->info.dir->nchildren;
|
nchildren = dir->info.dir->nchildren;
|
||||||
children = dir->info.dir->children;
|
children = dir->info.dir->children;
|
||||||
|
|
||||||
@ -315,19 +321,18 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
|
|||||||
ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash,
|
ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash,
|
||||||
(compare_function_t)strcmp, &table);
|
(compare_function_t)strcmp, &table);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
goto ex;
|
||||||
}
|
}
|
||||||
for (i = 0; i < nchildren; ++i) {
|
for (i = 0; i < nchildren; ++i) {
|
||||||
char *name = children[i]->name;
|
char *name = children[i]->name;
|
||||||
ret = iso_htable_add(table, name, name);
|
ret = iso_htable_add(table, name, name);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto mangle_cleanup;
|
goto ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < nchildren; ++i) {
|
for (i = 0; i < nchildren; ++i) {
|
||||||
char *name, *ext;
|
char *name, *ext;
|
||||||
char full_name[208];
|
|
||||||
int max; /* computed max len for name, without extension */
|
int max; /* computed max len for name, without extension */
|
||||||
int j = i;
|
int j = i;
|
||||||
int digits = 1; /* characters to change per name */
|
int digits = 1; /* characters to change per name */
|
||||||
@ -384,7 +389,7 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
|
|||||||
* This can't happen with current limit of digits.
|
* This can't happen with current limit of digits.
|
||||||
*/
|
*/
|
||||||
ret = ISO_ERROR;
|
ret = ISO_ERROR;
|
||||||
goto mangle_cleanup;
|
goto ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* ok, reduce name by digits */
|
/* ok, reduce name by digits */
|
||||||
@ -398,7 +403,7 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
|
|||||||
}
|
}
|
||||||
max = 207 - digits;
|
max = 207 - digits;
|
||||||
name = full_name;
|
name = full_name;
|
||||||
if (max < strlen(name)) {
|
if ((size_t) max < strlen(name)) {
|
||||||
name[max] = '\0';
|
name[max] = '\0';
|
||||||
}
|
}
|
||||||
/* let ext be an empty string */
|
/* let ext be an empty string */
|
||||||
@ -408,7 +413,6 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
|
|||||||
ok = 1;
|
ok = 1;
|
||||||
/* change name of each file */
|
/* change name of each file */
|
||||||
for (k = i; k <= j; ++k) {
|
for (k = i; k <= j; ++k) {
|
||||||
char tmp[208];
|
|
||||||
char fmt[16];
|
char fmt[16];
|
||||||
if (dot != NULL) {
|
if (dot != NULL) {
|
||||||
sprintf(fmt, "%%s%%0%dd.%%s", digits);
|
sprintf(fmt, "%%s%%0%dd.%%s", digits);
|
||||||
@ -431,7 +435,7 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
|
|||||||
char *new = strdup(tmp);
|
char *new = strdup(tmp);
|
||||||
if (new == NULL) {
|
if (new == NULL) {
|
||||||
ret = ISO_OUT_OF_MEM;
|
ret = ISO_OUT_OF_MEM;
|
||||||
goto mangle_cleanup;
|
goto ex;
|
||||||
}
|
}
|
||||||
iso_msg_debug(img->image->id, "\"%s\" renamed to \"%s\"",
|
iso_msg_debug(img->image->id, "\"%s\" renamed to \"%s\"",
|
||||||
children[k]->name, new);
|
children[k]->name, new);
|
||||||
@ -459,7 +463,7 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
|
|||||||
}
|
}
|
||||||
if (digits == 8) {
|
if (digits == 8) {
|
||||||
ret = ISO_MANGLE_TOO_MUCH_FILES;
|
ret = ISO_MANGLE_TOO_MUCH_FILES;
|
||||||
goto mangle_cleanup;
|
goto ex;
|
||||||
}
|
}
|
||||||
i = j;
|
i = j;
|
||||||
}
|
}
|
||||||
@ -473,8 +477,10 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
|
|||||||
|
|
||||||
ret = ISO_SUCCESS;
|
ret = ISO_SUCCESS;
|
||||||
|
|
||||||
mangle_cleanup : ;
|
ex:;
|
||||||
iso_htable_destroy(table, NULL);
|
iso_htable_destroy(table, NULL);
|
||||||
|
LIBISO_FREE_MEM(tmp);
|
||||||
|
LIBISO_FREE_MEM(full_name);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -683,8 +689,9 @@ void write_one_dir_record(Ecma119Image *t, Iso1999Node *node, int file_id,
|
|||||||
: (uint8_t*)node->name;
|
: (uint8_t*)node->name;
|
||||||
|
|
||||||
struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf;
|
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);
|
memcpy(rec->file_id, name, len_fi);
|
||||||
|
|
||||||
@ -714,7 +721,15 @@ void write_one_dir_record(Ecma119Image *t, Iso1999Node *node, int file_id,
|
|||||||
rec->len_dr[0] = len_dr;
|
rec->len_dr[0] = len_dr;
|
||||||
iso_bb(rec->block, block, 4);
|
iso_bb(rec->block, block, 4);
|
||||||
iso_bb(rec->length, len, 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->always_gmt);
|
||||||
|
*/
|
||||||
|
iso= node->node;
|
||||||
|
iso_datetime_7(rec->recording_time,
|
||||||
|
(t->dir_rec_mtime & 4) ? ( t->replace_timestamps ?
|
||||||
|
t->timestamp : iso->mtime )
|
||||||
|
: t->now, t->always_gmt);
|
||||||
|
|
||||||
rec->flags[0] = ((node->type == ISO1999_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0);
|
rec->flags[0] = ((node->type == ISO1999_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0);
|
||||||
iso_bb(rec->vol_seq_number, (uint32_t) 1, 2);
|
iso_bb(rec->vol_seq_number, (uint32_t) 1, 2);
|
||||||
rec->len_fi[0] = len_fi;
|
rec->len_fi[0] = len_fi;
|
||||||
@ -787,10 +802,8 @@ int iso1999_writer_write_vol_desc(IsoImageWriter *writer)
|
|||||||
strncpy_pad((char*)vol.abstract_file_id, abstract_file_id, 37);
|
strncpy_pad((char*)vol.abstract_file_id, abstract_file_id, 37);
|
||||||
strncpy_pad((char*)vol.bibliographic_file_id, biblio_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);
|
ecma119_set_voldescr_times(writer, (struct ecma119_pri_vol_desc *) &vol);
|
||||||
iso_datetime_17(vol.vol_modification_time, t->now, t->always_gmt);
|
vol.file_structure_version[0] = 2;
|
||||||
iso_datetime_17(vol.vol_effective_time, t->now, t->always_gmt);
|
|
||||||
vol.file_structure_version[0] = 1;
|
|
||||||
|
|
||||||
free(vol_id);
|
free(vol_id);
|
||||||
free(volset_id);
|
free(volset_id);
|
||||||
@ -810,15 +823,15 @@ static
|
|||||||
int write_one_dir(Ecma119Image *t, Iso1999Node *dir)
|
int write_one_dir(Ecma119Image *t, Iso1999Node *dir)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
uint8_t buffer[BLOCK_SIZE];
|
uint8_t *buffer = NULL;
|
||||||
size_t i;
|
size_t i;
|
||||||
size_t fi_len, len;
|
size_t fi_len, len;
|
||||||
|
|
||||||
/* buf will point to current write position on buffer */
|
/* buf will point to current write position on buffer */
|
||||||
uint8_t *buf = buffer;
|
uint8_t *buf;
|
||||||
|
|
||||||
/* initialize buffer with 0s */
|
LIBISO_ALLOC_MEM(buffer, uint8_t, BLOCK_SIZE);
|
||||||
memset(buffer, 0, BLOCK_SIZE);
|
buf = buffer;
|
||||||
|
|
||||||
/* write the "." and ".." entries first */
|
/* write the "." and ".." entries first */
|
||||||
write_one_dir_record(t, dir, 0, buf, 1, 0);
|
write_one_dir_record(t, dir, 0, buf, 1, 0);
|
||||||
@ -832,7 +845,7 @@ int write_one_dir(Ecma119Image *t, Iso1999Node *dir)
|
|||||||
|
|
||||||
/* compute len of directory entry */
|
/* compute len of directory entry */
|
||||||
fi_len = strlen(child->name);
|
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;
|
nsections = (child->type == ISO1999_FILE) ? child->info.file->nsections : 1;
|
||||||
for (section = 0; section < nsections; ++section) {
|
for (section = 0; section < nsections; ++section) {
|
||||||
@ -840,7 +853,7 @@ int write_one_dir(Ecma119Image *t, Iso1999Node *dir)
|
|||||||
/* dir doesn't fit in current block */
|
/* dir doesn't fit in current block */
|
||||||
ret = iso_write(t, buffer, BLOCK_SIZE);
|
ret = iso_write(t, buffer, BLOCK_SIZE);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
goto ex;
|
||||||
}
|
}
|
||||||
memset(buffer, 0, BLOCK_SIZE);
|
memset(buffer, 0, BLOCK_SIZE);
|
||||||
buf = buffer;
|
buf = buffer;
|
||||||
@ -853,6 +866,8 @@ int write_one_dir(Ecma119Image *t, Iso1999Node *dir)
|
|||||||
|
|
||||||
/* write the last block */
|
/* write the last block */
|
||||||
ret = iso_write(t, buffer, BLOCK_SIZE);
|
ret = iso_write(t, buffer, BLOCK_SIZE);
|
||||||
|
ex:;
|
||||||
|
LIBISO_FREE_MEM(buffer);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -885,13 +900,17 @@ static
|
|||||||
int write_path_table(Ecma119Image *t, Iso1999Node **pathlist, int l_type)
|
int write_path_table(Ecma119Image *t, Iso1999Node **pathlist, int l_type)
|
||||||
{
|
{
|
||||||
size_t i, len;
|
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;
|
struct ecma119_path_table_record *rec;
|
||||||
void (*write_int)(uint8_t*, uint32_t, int);
|
void (*write_int)(uint8_t*, uint32_t, int);
|
||||||
Iso1999Node *dir;
|
Iso1999Node *dir;
|
||||||
uint32_t path_table_size;
|
uint32_t path_table_size;
|
||||||
int parent = 0;
|
int parent = 0;
|
||||||
int ret= ISO_SUCCESS;
|
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;
|
path_table_size = 0;
|
||||||
write_int = l_type ? iso_lsb : iso_msb;
|
write_int = l_type ? iso_lsb : iso_msb;
|
||||||
@ -918,7 +937,7 @@ int write_path_table(Ecma119Image *t, Iso1999Node **pathlist, int l_type)
|
|||||||
ret = iso_write(t, buf, len);
|
ret = iso_write(t, buf, len);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
/* error */
|
/* error */
|
||||||
return ret;
|
goto ex;
|
||||||
}
|
}
|
||||||
path_table_size += len;
|
path_table_size += len;
|
||||||
}
|
}
|
||||||
@ -926,11 +945,14 @@ int write_path_table(Ecma119Image *t, Iso1999Node **pathlist, int l_type)
|
|||||||
/* we need to fill the last block with zeros */
|
/* we need to fill the last block with zeros */
|
||||||
path_table_size %= BLOCK_SIZE;
|
path_table_size %= BLOCK_SIZE;
|
||||||
if (path_table_size) {
|
if (path_table_size) {
|
||||||
uint8_t zeros[BLOCK_SIZE];
|
LIBISO_ALLOC_MEM(zeros, uint8_t, BLOCK_SIZE);
|
||||||
len = BLOCK_SIZE - path_table_size;
|
len = BLOCK_SIZE - path_table_size;
|
||||||
memset(zeros, 0, len);
|
memset(zeros, 0, len);
|
||||||
ret = iso_write(t, zeros, len);
|
ret = iso_write(t, zeros, len);
|
||||||
}
|
}
|
||||||
|
ex:;
|
||||||
|
LIBISO_FREE_MEM(zeros);
|
||||||
|
LIBISO_FREE_MEM(buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* Copyright (c) 2007 Vreixo Formoso
|
||||||
* Copyright (c) 2007 Mario Danic
|
* Copyright (c) 2007 Mario Danic
|
||||||
|
* Copyright (c) 2011-2012 Thomas Schmitt
|
||||||
*
|
*
|
||||||
* This file is part of the libisofs project; you can redistribute it and/or
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -19,6 +20,8 @@
|
|||||||
#include "filesrc.h"
|
#include "filesrc.h"
|
||||||
#include "eltorito.h"
|
#include "eltorito.h"
|
||||||
#include "libisofs.h"
|
#include "libisofs.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "ecma119.h"
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -42,12 +45,11 @@ int get_joliet_name(Ecma119Image *t, IsoNode *iso, uint16_t **name)
|
|||||||
iso_msg_debug(t->image->id, "Can't convert %s", iso->name);
|
iso_msg_debug(t->image->id, "Can't convert %s", iso->name);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO #00022 : support relaxed constraints in joliet filenames */
|
|
||||||
if (iso->type == LIBISO_DIR) {
|
if (iso->type == LIBISO_DIR) {
|
||||||
jname = iso_j_dir_id(ucs_name);
|
jname = iso_j_dir_id(ucs_name, t->joliet_long_names << 1);
|
||||||
} else {
|
} else {
|
||||||
jname = iso_j_file_id(ucs_name, !!(t->no_force_dots & 2));
|
jname = iso_j_file_id(ucs_name,
|
||||||
|
(t->joliet_long_names << 1) | !!(t->no_force_dots & 2));
|
||||||
}
|
}
|
||||||
free(ucs_name);
|
free(ucs_name);
|
||||||
if (jname != NULL) {
|
if (jname != NULL) {
|
||||||
@ -69,7 +71,7 @@ void joliet_node_free(JolietNode *node)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (node->type == JOLIET_DIR) {
|
if (node->type == JOLIET_DIR) {
|
||||||
int i;
|
size_t i;
|
||||||
for (i = 0; i < node->info.dir->nchildren; i++) {
|
for (i = 0; i < node->info.dir->nchildren; i++) {
|
||||||
joliet_node_free(node->info.dir->children[i]);
|
joliet_node_free(node->info.dir->children[i]);
|
||||||
}
|
}
|
||||||
@ -303,8 +305,15 @@ int joliet_create_mangled_name(uint16_t *dest, uint16_t *src, int digits,
|
|||||||
int ret, pos;
|
int ret, pos;
|
||||||
uint16_t *ucsnumber;
|
uint16_t *ucsnumber;
|
||||||
char fmt[16];
|
char fmt[16];
|
||||||
char nstr[72]; /* The only caller of this function allocates dest with 66
|
char nstr[72];
|
||||||
elements and limits digits to < 8 */
|
/* 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(fmt, "%%0%dd", digits);
|
||||||
sprintf(nstr, fmt, number);
|
sprintf(nstr, fmt, number);
|
||||||
@ -324,11 +333,12 @@ int joliet_create_mangled_name(uint16_t *dest, uint16_t *src, int digits,
|
|||||||
|
|
||||||
if (ext[0] != (uint16_t)0) {
|
if (ext[0] != (uint16_t)0) {
|
||||||
size_t extlen = ucslen(ext);
|
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);
|
ucsncpy(dest + pos, ext, extlen);
|
||||||
pos += extlen;
|
pos += extlen;
|
||||||
}
|
}
|
||||||
dest[pos] = (uint16_t)0;
|
iso_msb((uint8_t *) (dest + pos), 0, 2);
|
||||||
free(ucsnumber);
|
free(ucsnumber);
|
||||||
return ISO_SUCCESS;
|
return ISO_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -337,19 +347,26 @@ static
|
|||||||
int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int i, nchildren;
|
int i, nchildren, maxchar = 64;
|
||||||
JolietNode **children;
|
JolietNode **children;
|
||||||
IsoHTable *table;
|
IsoHTable *table;
|
||||||
int need_sort = 0;
|
int need_sort = 0;
|
||||||
|
uint16_t *full_name = NULL;
|
||||||
|
uint16_t *tmp = NULL;
|
||||||
|
|
||||||
|
LIBISO_ALLOC_MEM(full_name, uint16_t, LIBISO_JOLIET_NAME_MAX);
|
||||||
|
LIBISO_ALLOC_MEM(tmp, uint16_t, LIBISO_JOLIET_NAME_MAX);
|
||||||
nchildren = dir->info.dir->nchildren;
|
nchildren = dir->info.dir->nchildren;
|
||||||
children = dir->info.dir->children;
|
children = dir->info.dir->children;
|
||||||
|
|
||||||
|
if (t->joliet_long_names)
|
||||||
|
maxchar = 103;
|
||||||
|
|
||||||
/* a hash table will temporary hold the names, for fast searching */
|
/* a hash table will temporary hold the names, for fast searching */
|
||||||
ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash,
|
ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash,
|
||||||
(compare_function_t)ucscmp, &table);
|
(compare_function_t)ucscmp, &table);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
goto ex;
|
||||||
}
|
}
|
||||||
for (i = 0; i < nchildren; ++i) {
|
for (i = 0; i < nchildren; ++i) {
|
||||||
uint16_t *name = children[i]->name;
|
uint16_t *name = children[i]->name;
|
||||||
@ -361,7 +378,6 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
|||||||
|
|
||||||
for (i = 0; i < nchildren; ++i) {
|
for (i = 0; i < nchildren; ++i) {
|
||||||
uint16_t *name, *ext;
|
uint16_t *name, *ext;
|
||||||
uint16_t full_name[66];
|
|
||||||
int max; /* computed max len for name, without extension */
|
int max; /* computed max len for name, without extension */
|
||||||
int j = i;
|
int j = i;
|
||||||
int digits = 1; /* characters to change per name */
|
int digits = 1; /* characters to change per name */
|
||||||
@ -380,7 +396,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
|||||||
* A max of 7 characters is good enought, it allows handling up to
|
* A max of 7 characters is good enought, it allows handling up to
|
||||||
* 9,999,999 files with same name.
|
* 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) {
|
while (digits < 8) {
|
||||||
int ok, k;
|
int ok, k;
|
||||||
@ -403,7 +419,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
|||||||
ext = dot + 1;
|
ext = dot + 1;
|
||||||
|
|
||||||
extlen = ucslen(ext);
|
extlen = ucslen(ext);
|
||||||
max = 65 - extlen - 1 - digits;
|
max = maxchar + 1 - extlen - 1 - digits;
|
||||||
if (max <= 0) {
|
if (max <= 0) {
|
||||||
/* this can happen if extension is too long */
|
/* this can happen if extension is too long */
|
||||||
if (extlen + max > 3) {
|
if (extlen + max > 3) {
|
||||||
@ -413,7 +429,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
|||||||
*/
|
*/
|
||||||
extlen = extlen + max - 1;
|
extlen = extlen + max - 1;
|
||||||
ext[extlen] = 0;
|
ext[extlen] = 0;
|
||||||
max = 66 - extlen - 1 - digits;
|
max = maxchar + 2 - extlen - 1 - digits;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* error, we don't support extensions < 3
|
* error, we don't support extensions < 3
|
||||||
@ -430,13 +446,13 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
|||||||
} else {
|
} else {
|
||||||
/* Directory, or file without extension */
|
/* Directory, or file without extension */
|
||||||
if (children[i]->type == JOLIET_DIR) {
|
if (children[i]->type == JOLIET_DIR) {
|
||||||
max = 65 - digits;
|
max = maxchar + 1 - digits;
|
||||||
dot = NULL; /* dots have no meaning in dirs */
|
dot = NULL; /* dots have no meaning in dirs */
|
||||||
} else {
|
} else {
|
||||||
max = 65 - digits;
|
max = maxchar + 1 - digits;
|
||||||
}
|
}
|
||||||
name = full_name;
|
name = full_name;
|
||||||
if (max < ucslen(name)) {
|
if ((size_t) max < ucslen(name)) {
|
||||||
name[max] = 0;
|
name[max] = 0;
|
||||||
}
|
}
|
||||||
/* let ext be an empty string */
|
/* let ext be an empty string */
|
||||||
@ -446,7 +462,6 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
|||||||
ok = 1;
|
ok = 1;
|
||||||
/* change name of each file */
|
/* change name of each file */
|
||||||
for (k = i; k <= j; ++k) {
|
for (k = i; k <= j; ++k) {
|
||||||
uint16_t tmp[66];
|
|
||||||
while (1) {
|
while (1) {
|
||||||
ret = joliet_create_mangled_name(tmp, name, digits,
|
ret = joliet_create_mangled_name(tmp, name, digits,
|
||||||
change, ext);
|
change, ext);
|
||||||
@ -508,7 +523,10 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
|||||||
ret = ISO_SUCCESS;
|
ret = ISO_SUCCESS;
|
||||||
|
|
||||||
mangle_cleanup : ;
|
mangle_cleanup : ;
|
||||||
|
ex:;
|
||||||
iso_htable_destroy(table, NULL);
|
iso_htable_destroy(table, NULL);
|
||||||
|
LIBISO_FREE_MEM(tmp);
|
||||||
|
LIBISO_FREE_MEM(full_name);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -742,8 +760,9 @@ void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id,
|
|||||||
: (uint8_t*)node->name;
|
: (uint8_t*)node->name;
|
||||||
|
|
||||||
struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf;
|
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);
|
memcpy(rec->file_id, name, len_fi);
|
||||||
|
|
||||||
@ -781,7 +800,15 @@ void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id,
|
|||||||
rec->len_dr[0] = len_dr;
|
rec->len_dr[0] = len_dr;
|
||||||
iso_bb(rec->block, block - t->eff_partition_offset, 4);
|
iso_bb(rec->block, block - t->eff_partition_offset, 4);
|
||||||
iso_bb(rec->length, len, 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->always_gmt);
|
||||||
|
*/
|
||||||
|
iso= node->node;
|
||||||
|
iso_datetime_7(rec->recording_time,
|
||||||
|
(t->dir_rec_mtime & 2) ? ( t->replace_timestamps ?
|
||||||
|
t->timestamp : iso->mtime )
|
||||||
|
: t->now, t->always_gmt);
|
||||||
|
|
||||||
rec->flags[0] = ((node->type == JOLIET_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0);
|
rec->flags[0] = ((node->type == JOLIET_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0);
|
||||||
iso_bb(rec->vol_seq_number, (uint32_t) 1, 2);
|
iso_bb(rec->vol_seq_number, (uint32_t) 1, 2);
|
||||||
rec->len_fi[0] = len_fi;
|
rec->len_fi[0] = len_fi;
|
||||||
@ -886,9 +913,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.abstract_file_id, abstract_file_id, 37);
|
||||||
ucsncpy_pad((uint16_t*)vol.bibliographic_file_id, biblio_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);
|
ecma119_set_voldescr_times(writer, (struct ecma119_pri_vol_desc *) &vol);
|
||||||
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;
|
vol.file_structure_version[0] = 1;
|
||||||
|
|
||||||
free(vol_id);
|
free(vol_id);
|
||||||
@ -909,15 +934,16 @@ static
|
|||||||
int write_one_dir(Ecma119Image *t, JolietNode *dir)
|
int write_one_dir(Ecma119Image *t, JolietNode *dir)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
uint8_t buffer[BLOCK_SIZE];
|
uint8_t *buffer = NULL;
|
||||||
size_t i;
|
size_t i;
|
||||||
size_t fi_len, len;
|
size_t fi_len, len;
|
||||||
|
|
||||||
/* buf will point to current write position on buffer */
|
/* buf will point to current write position on buffer */
|
||||||
uint8_t *buf = buffer;
|
uint8_t *buf;
|
||||||
|
|
||||||
/* initialize buffer with 0s */
|
/* 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 the "." and ".." entries first */
|
||||||
write_one_dir_record(t, dir, 0, buf, 1, 0);
|
write_one_dir_record(t, dir, 0, buf, 1, 0);
|
||||||
@ -944,7 +970,7 @@ int write_one_dir(Ecma119Image *t, JolietNode *dir)
|
|||||||
/* dir doesn't fit in current block */
|
/* dir doesn't fit in current block */
|
||||||
ret = iso_write(t, buffer, BLOCK_SIZE);
|
ret = iso_write(t, buffer, BLOCK_SIZE);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
goto ex;
|
||||||
}
|
}
|
||||||
memset(buffer, 0, BLOCK_SIZE);
|
memset(buffer, 0, BLOCK_SIZE);
|
||||||
buf = buffer;
|
buf = buffer;
|
||||||
@ -957,6 +983,8 @@ int write_one_dir(Ecma119Image *t, JolietNode *dir)
|
|||||||
|
|
||||||
/* write the last block */
|
/* write the last block */
|
||||||
ret = iso_write(t, buffer, BLOCK_SIZE);
|
ret = iso_write(t, buffer, BLOCK_SIZE);
|
||||||
|
ex:;
|
||||||
|
LIBISO_FREE_MEM(buffer);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -989,14 +1017,18 @@ static
|
|||||||
int write_path_table(Ecma119Image *t, JolietNode **pathlist, int l_type)
|
int write_path_table(Ecma119Image *t, JolietNode **pathlist, int l_type)
|
||||||
{
|
{
|
||||||
size_t i, len;
|
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;
|
struct ecma119_path_table_record *rec;
|
||||||
void (*write_int)(uint8_t*, uint32_t, int);
|
void (*write_int)(uint8_t*, uint32_t, int);
|
||||||
JolietNode *dir;
|
JolietNode *dir;
|
||||||
uint32_t path_table_size;
|
uint32_t path_table_size;
|
||||||
int parent = 0;
|
int parent = 0;
|
||||||
int ret= ISO_SUCCESS;
|
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;
|
path_table_size = 0;
|
||||||
write_int = l_type ? iso_lsb : iso_msb;
|
write_int = l_type ? iso_lsb : iso_msb;
|
||||||
|
|
||||||
@ -1023,7 +1055,7 @@ int write_path_table(Ecma119Image *t, JolietNode **pathlist, int l_type)
|
|||||||
ret = iso_write(t, buf, len);
|
ret = iso_write(t, buf, len);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
/* error */
|
/* error */
|
||||||
return ret;
|
goto ex;
|
||||||
}
|
}
|
||||||
path_table_size += len;
|
path_table_size += len;
|
||||||
}
|
}
|
||||||
@ -1031,11 +1063,13 @@ int write_path_table(Ecma119Image *t, JolietNode **pathlist, int l_type)
|
|||||||
/* we need to fill the last block with zeros */
|
/* we need to fill the last block with zeros */
|
||||||
path_table_size %= BLOCK_SIZE;
|
path_table_size %= BLOCK_SIZE;
|
||||||
if (path_table_size) {
|
if (path_table_size) {
|
||||||
uint8_t zeros[BLOCK_SIZE];
|
|
||||||
len = BLOCK_SIZE - path_table_size;
|
len = BLOCK_SIZE - path_table_size;
|
||||||
memset(zeros, 0, len);
|
memset(zeros, 0, len);
|
||||||
ret = iso_write(t, zeros, len);
|
ret = iso_write(t, zeros, len);
|
||||||
}
|
}
|
||||||
|
ex:;
|
||||||
|
LIBISO_FREE_MEM(zeros);
|
||||||
|
LIBISO_FREE_MEM(buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,10 @@
|
|||||||
#include "libisofs.h"
|
#include "libisofs.h"
|
||||||
#include "ecma119.h"
|
#include "ecma119.h"
|
||||||
|
|
||||||
|
/* was formerly 66 = 64 + 2. Now 105 = 103 + 2.
|
||||||
|
*/
|
||||||
|
#define LIBISO_JOLIET_NAME_MAX 105
|
||||||
|
|
||||||
enum joliet_node_type {
|
enum joliet_node_type {
|
||||||
JOLIET_FILE,
|
JOLIET_FILE,
|
||||||
JOLIET_DIR
|
JOLIET_DIR
|
||||||
|
@ -288,7 +288,7 @@ int libiso_msgs__sev_to_text(int severity, char **severity_name,
|
|||||||
int flag)
|
int flag)
|
||||||
{
|
{
|
||||||
if(flag&1) {
|
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);
|
return(1);
|
||||||
}
|
}
|
||||||
*severity_name= "";
|
*severity_name= "";
|
||||||
|
@ -316,7 +316,7 @@ int libiso_msgs_submit(struct libiso_msgs *m, int origin, int error_code,
|
|||||||
|
|
||||||
/** Convert a registered severity number into a severity name
|
/** Convert a registered severity number into a severity name
|
||||||
@param flag Bitfield for control purposes:
|
@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
|
@return >0 success, <=0 failure
|
||||||
*/
|
*/
|
||||||
int libiso_msgs__sev_to_text(int severity, char **severity_name,
|
int libiso_msgs__sev_to_text(int severity, char **severity_name,
|
||||||
|
1336
libisofs/libisofs.h
1336
libisofs/libisofs.h
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,6 @@
|
|||||||
LIBISOFS6 {
|
LIBISOFS6 {
|
||||||
global:
|
global:
|
||||||
|
aaip_xinfo_cloner;
|
||||||
aaip_xinfo_func;
|
aaip_xinfo_func;
|
||||||
el_torito_get_bootable;
|
el_torito_get_bootable;
|
||||||
el_torito_get_boot_media_type;
|
el_torito_get_boot_media_type;
|
||||||
@ -64,9 +65,12 @@ iso_file_source_unref;
|
|||||||
iso_filesystem_ref;
|
iso_filesystem_ref;
|
||||||
iso_filesystem_unref;
|
iso_filesystem_unref;
|
||||||
iso_finish;
|
iso_finish;
|
||||||
|
iso_fs_global_id;
|
||||||
iso_get_local_charset;
|
iso_get_local_charset;
|
||||||
iso_get_messenger;
|
iso_get_messenger;
|
||||||
iso_gzip_get_refcounts;
|
iso_gzip_get_refcounts;
|
||||||
|
iso_hfsplus_xinfo_func;
|
||||||
|
iso_hfsplus_xinfo_new;
|
||||||
iso_image_add_boot_image;
|
iso_image_add_boot_image;
|
||||||
iso_image_add_mips_boot_file;
|
iso_image_add_mips_boot_file;
|
||||||
iso_image_attach_data;
|
iso_image_attach_data;
|
||||||
@ -87,6 +91,7 @@ iso_image_get_all_boot_imgs;
|
|||||||
iso_image_get_application_id;
|
iso_image_get_application_id;
|
||||||
iso_image_get_attached_data;
|
iso_image_get_attached_data;
|
||||||
iso_image_get_biblio_file_id;
|
iso_image_get_biblio_file_id;
|
||||||
|
iso_image_get_bootcat;
|
||||||
iso_image_get_boot_image;
|
iso_image_get_boot_image;
|
||||||
iso_image_get_copyright_file_id;
|
iso_image_get_copyright_file_id;
|
||||||
iso_image_get_data_preparer_id;
|
iso_image_get_data_preparer_id;
|
||||||
@ -100,6 +105,8 @@ iso_image_get_system_id;
|
|||||||
iso_image_get_volset_id;
|
iso_image_get_volset_id;
|
||||||
iso_image_get_volume_id;
|
iso_image_get_volume_id;
|
||||||
iso_image_give_up_mips_boot;
|
iso_image_give_up_mips_boot;
|
||||||
|
iso_image_hfsplus_bless;
|
||||||
|
iso_image_hfsplus_get_blessed;
|
||||||
iso_image_import;
|
iso_image_import;
|
||||||
iso_image_new;
|
iso_image_new;
|
||||||
iso_image_ref;
|
iso_image_ref;
|
||||||
@ -123,6 +130,7 @@ iso_init;
|
|||||||
iso_init_with_flag;
|
iso_init_with_flag;
|
||||||
iso_lib_is_compatible;
|
iso_lib_is_compatible;
|
||||||
iso_lib_version;
|
iso_lib_version;
|
||||||
|
iso_local_attr_support;
|
||||||
iso_local_get_acl_text;
|
iso_local_get_acl_text;
|
||||||
iso_local_get_attrs;
|
iso_local_get_attrs;
|
||||||
iso_local_get_perms_wo_acl;
|
iso_local_get_perms_wo_acl;
|
||||||
@ -156,6 +164,7 @@ iso_node_get_hidden;
|
|||||||
iso_node_get_mode;
|
iso_node_get_mode;
|
||||||
iso_node_get_mtime;
|
iso_node_get_mtime;
|
||||||
iso_node_get_name;
|
iso_node_get_name;
|
||||||
|
iso_node_get_next_xinfo;
|
||||||
iso_node_get_old_image_lba;
|
iso_node_get_old_image_lba;
|
||||||
iso_node_get_parent;
|
iso_node_get_parent;
|
||||||
iso_node_get_permissions;
|
iso_node_get_permissions;
|
||||||
@ -166,6 +175,8 @@ iso_node_get_xinfo;
|
|||||||
iso_node_lookup_attr;
|
iso_node_lookup_attr;
|
||||||
iso_node_ref;
|
iso_node_ref;
|
||||||
iso_node_remove;
|
iso_node_remove;
|
||||||
|
iso_node_remove_all_xinfo;
|
||||||
|
iso_node_remove_tree;
|
||||||
iso_node_remove_xinfo;
|
iso_node_remove_xinfo;
|
||||||
iso_node_set_acl_text;
|
iso_node_set_acl_text;
|
||||||
iso_node_set_atime;
|
iso_node_set_atime;
|
||||||
@ -180,6 +191,8 @@ iso_node_set_sort_weight;
|
|||||||
iso_node_set_uid;
|
iso_node_set_uid;
|
||||||
iso_node_take;
|
iso_node_take;
|
||||||
iso_node_unref;
|
iso_node_unref;
|
||||||
|
iso_node_xinfo_get_cloner;
|
||||||
|
iso_node_xinfo_make_clonable;
|
||||||
iso_node_zf_by_magic;
|
iso_node_zf_by_magic;
|
||||||
iso_obtain_msgs;
|
iso_obtain_msgs;
|
||||||
iso_read_image_features_destroy;
|
iso_read_image_features_destroy;
|
||||||
@ -210,6 +223,7 @@ iso_set_local_charset;
|
|||||||
iso_set_msgs_severities;
|
iso_set_msgs_severities;
|
||||||
iso_sev_to_text;
|
iso_sev_to_text;
|
||||||
iso_special_get_dev;
|
iso_special_get_dev;
|
||||||
|
iso_stream_clone;
|
||||||
iso_stream_close;
|
iso_stream_close;
|
||||||
iso_stream_cmp_ino;
|
iso_stream_cmp_ino;
|
||||||
iso_stream_get_external_filter;
|
iso_stream_get_external_filter;
|
||||||
@ -235,6 +249,7 @@ iso_tree_add_new_node;
|
|||||||
iso_tree_add_new_special;
|
iso_tree_add_new_special;
|
||||||
iso_tree_add_new_symlink;
|
iso_tree_add_new_symlink;
|
||||||
iso_tree_add_node;
|
iso_tree_add_node;
|
||||||
|
iso_tree_clone;
|
||||||
iso_tree_get_follow_symlinks;
|
iso_tree_get_follow_symlinks;
|
||||||
iso_tree_get_ignore_hidden;
|
iso_tree_get_ignore_hidden;
|
||||||
iso_tree_get_ignore_special;
|
iso_tree_get_ignore_special;
|
||||||
@ -242,6 +257,7 @@ iso_tree_get_node_path;
|
|||||||
iso_tree_get_replace_mode;
|
iso_tree_get_replace_mode;
|
||||||
iso_tree_path_to_node;
|
iso_tree_path_to_node;
|
||||||
iso_tree_remove_exclude;
|
iso_tree_remove_exclude;
|
||||||
|
iso_tree_resolve_symlink;
|
||||||
iso_tree_set_follow_symlinks;
|
iso_tree_set_follow_symlinks;
|
||||||
iso_tree_set_ignore_hidden;
|
iso_tree_set_ignore_hidden;
|
||||||
iso_tree_set_ignore_special;
|
iso_tree_set_ignore_special;
|
||||||
@ -255,6 +271,7 @@ iso_write_opts_get_data_start;
|
|||||||
iso_write_opts_new;
|
iso_write_opts_new;
|
||||||
iso_write_opts_set_aaip;
|
iso_write_opts_set_aaip;
|
||||||
iso_write_opts_set_aaip_susp_1_10;
|
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_deep_paths;
|
||||||
iso_write_opts_set_allow_dir_id_ext;
|
iso_write_opts_set_allow_dir_id_ext;
|
||||||
iso_write_opts_set_allow_full_ascii;
|
iso_write_opts_set_allow_full_ascii;
|
||||||
@ -269,26 +286,35 @@ iso_write_opts_set_default_timestamp;
|
|||||||
iso_write_opts_set_default_uid;
|
iso_write_opts_set_default_uid;
|
||||||
iso_write_opts_set_dir_rec_mtime;
|
iso_write_opts_set_dir_rec_mtime;
|
||||||
iso_write_opts_set_disc_label;
|
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_fifo_size;
|
||||||
iso_write_opts_set_hardlinks;
|
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_iso1999;
|
||||||
iso_write_opts_set_iso_level;
|
iso_write_opts_set_iso_level;
|
||||||
iso_write_opts_set_joliet;
|
iso_write_opts_set_joliet;
|
||||||
|
iso_write_opts_set_joliet_long_names;
|
||||||
iso_write_opts_set_joliet_longer_paths;
|
iso_write_opts_set_joliet_longer_paths;
|
||||||
iso_write_opts_set_max_37_char_filenames;
|
iso_write_opts_set_max_37_char_filenames;
|
||||||
iso_write_opts_set_ms_block;
|
iso_write_opts_set_ms_block;
|
||||||
iso_write_opts_set_no_force_dots;
|
iso_write_opts_set_no_force_dots;
|
||||||
|
iso_write_opts_set_old_empty;
|
||||||
iso_write_opts_set_omit_version_numbers;
|
iso_write_opts_set_omit_version_numbers;
|
||||||
iso_write_opts_set_output_charset;
|
iso_write_opts_set_output_charset;
|
||||||
iso_write_opts_set_overwrite_buf;
|
iso_write_opts_set_overwrite_buf;
|
||||||
iso_write_opts_set_part_offset;
|
iso_write_opts_set_part_offset;
|
||||||
iso_write_opts_set_partition_img;
|
iso_write_opts_set_partition_img;
|
||||||
|
iso_write_opts_set_prep_img;
|
||||||
iso_write_opts_set_pvd_times;
|
iso_write_opts_set_pvd_times;
|
||||||
iso_write_opts_set_record_md5;
|
iso_write_opts_set_record_md5;
|
||||||
iso_write_opts_set_relaxed_vol_atts;
|
iso_write_opts_set_relaxed_vol_atts;
|
||||||
iso_write_opts_set_replace_mode;
|
iso_write_opts_set_replace_mode;
|
||||||
iso_write_opts_set_replace_timestamps;
|
iso_write_opts_set_replace_timestamps;
|
||||||
iso_write_opts_set_rockridge;
|
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_1_10_px_ino;
|
||||||
iso_write_opts_set_rrip_version_1_10;
|
iso_write_opts_set_rrip_version_1_10;
|
||||||
iso_write_opts_set_scdbackup_tag;
|
iso_write_opts_set_scdbackup_tag;
|
||||||
@ -300,5 +326,6 @@ iso_write_opts_set_will_cancel;
|
|||||||
iso_zisofs_get_params;
|
iso_zisofs_get_params;
|
||||||
iso_zisofs_get_refcounts;
|
iso_zisofs_get_refcounts;
|
||||||
iso_zisofs_set_params;
|
iso_zisofs_set_params;
|
||||||
|
serial_id;
|
||||||
local: *;
|
local: *;
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,15 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_STDINT_H
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_INTTYPES_H
|
||||||
|
#include <inttypes.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -15,6 +23,11 @@
|
|||||||
/* for gettimeofday() */
|
/* for gettimeofday() */
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include "filesrc.h"
|
||||||
|
#include "ecma119.h"
|
||||||
|
#include "eltorito.h"
|
||||||
|
#include "system_area.h"
|
||||||
|
|
||||||
|
|
||||||
/* This code stems from syslinux-3.72/utils/isohybrid, a perl script
|
/* This code stems from syslinux-3.72/utils/isohybrid, a perl script
|
||||||
under GPL which is Copyright 2002-2008 H. Peter Anvin.
|
under GPL which is Copyright 2002-2008 H. Peter Anvin.
|
||||||
@ -37,7 +50,7 @@ license from above stem licenses, typically from LGPL.
|
|||||||
In case its generosity is needed, here is the 2-clause BSD license:
|
In case its generosity is needed, here is the 2-clause BSD license:
|
||||||
|
|
||||||
make_isohybrid_mbr.c is copyright 2002-2008 H. Peter Anvin
|
make_isohybrid_mbr.c is copyright 2002-2008 H. Peter Anvin
|
||||||
and 2008-2010 Thomas Schmitt
|
and 2008-2012 Thomas Schmitt
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
this list of conditions and the following disclaimer.
|
this list of conditions and the following disclaimer.
|
||||||
@ -127,7 +140,7 @@ int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag)
|
|||||||
|
|
||||||
static int h = 64, s = 32;
|
static int h = 64, s = 32;
|
||||||
|
|
||||||
int i, warn_size = 0, id;
|
int i, id;
|
||||||
char *wpt;
|
char *wpt;
|
||||||
off_t imgsize, cylsize, frac, padding, c, cc;
|
off_t imgsize, cylsize, frac, padding, c, cc;
|
||||||
|
|
||||||
@ -156,7 +169,6 @@ int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag)
|
|||||||
*img_blocks = imgsize / (off_t) 2048;
|
*img_blocks = imgsize / (off_t) 2048;
|
||||||
c = imgsize / cylsize;
|
c = imgsize / cylsize;
|
||||||
if (c > 1024) {
|
if (c > 1024) {
|
||||||
warn_size = 1;
|
|
||||||
cc = 1024;
|
cc = 1024;
|
||||||
} else
|
} else
|
||||||
cc = c;
|
cc = c;
|
||||||
@ -346,6 +358,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
|
static
|
||||||
int lba512chs_to_buf(char **wpt, off_t lba, int head_count, int sector_count)
|
int lba512chs_to_buf(char **wpt, off_t lba, int head_count, int sector_count)
|
||||||
{
|
{
|
||||||
@ -370,29 +388,210 @@ 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
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
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) {
|
||||||
|
if (*gpt_count < 128)
|
||||||
|
gpt_idx[*gpt_count]= i;
|
||||||
|
(*gpt_count)++;
|
||||||
|
if ((flag & 1) && t->bootsrc[i] != NULL) {
|
||||||
|
/* 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;
|
||||||
|
block_count = 0;
|
||||||
|
for (j = 0; j < t->bootsrc[i]->nsections; j++)
|
||||||
|
block_count += t->bootsrc[i]->sections[j].size / 2048;
|
||||||
|
ret = iso_quick_gpt_entry(
|
||||||
|
t, t->bootsrc[i]->sections[0].block,
|
||||||
|
block_count, uuid, zero_uuid, gpt_flags,
|
||||||
|
(uint8_t *) gpt_name);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ilx_opts & 256) {
|
||||||
|
(*apm_count)++;
|
||||||
|
if ((flag & 1) && t->bootsrc[i] != NULL) {
|
||||||
|
/* Register APM entry */
|
||||||
|
block_count = 0;
|
||||||
|
for (j = 0; j < t->bootsrc[i]->nsections; j++)
|
||||||
|
block_count += t->bootsrc[i]->sections[j].size / 2048;
|
||||||
|
ret = iso_quick_apm_entry(t, t->bootsrc[i]->sections[0].block,
|
||||||
|
block_count, "EFI", "Apple_HFS");
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
/* Prevent gap filling */
|
||||||
|
t->apm_req_flags |= 2;
|
||||||
|
t->apm_block_size = 2048;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((flag & 1) && *gpt_count > 0) {
|
||||||
|
/* 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, (uint32_t) 0, block_count,
|
||||||
|
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;
|
||||||
|
off_t hd_blocks;
|
||||||
|
static uint8_t dummy_chs[3] = {
|
||||||
|
0xfe, 0xff, 0xff,
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @param flag bit0= make own random MBR Id from current time
|
* @param flag bit0= make own random MBR Id from current time
|
||||||
*/
|
*/
|
||||||
int make_isolinux_mbr(int32_t *img_blocks, uint32_t boot_lba,
|
int make_isolinux_mbr(int32_t *img_blocks, Ecma119Image *t,
|
||||||
uint32_t mbr_id, int head_count, int sector_count,
|
|
||||||
int part_offset, int part_number, int fs_type,
|
int part_offset, int part_number, int fs_type,
|
||||||
uint8_t *buf, int flag)
|
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;
|
off_t hd_img_blocks, hd_boot_lba;
|
||||||
char *wpt;
|
char *wpt;
|
||||||
|
uint32_t boot_lba, mbr_id;
|
||||||
|
int head_count, sector_count, ret;
|
||||||
|
int gpt_count = 0, gpt_idx[128], apm_count = 0, gpt_cursor;
|
||||||
/* For generating a weak random number */
|
/* For generating a weak random number */
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
struct timezone tz;
|
struct timezone tz;
|
||||||
|
|
||||||
/* 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;
|
hd_img_blocks = ((off_t) *img_blocks) * (off_t) 4;
|
||||||
if (hd_img_blocks % spc) {
|
|
||||||
hd_img_blocks += spc - (hd_img_blocks % spc);
|
boot_lba = t->bootsrc[0]->sections[0].block;
|
||||||
*img_blocks = hd_img_blocks / 4 + !!(hd_img_blocks % 4);
|
mbr_id = 0;
|
||||||
}
|
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;
|
wpt = (char *) buf + 432;
|
||||||
|
|
||||||
@ -417,10 +616,21 @@ int make_isolinux_mbr(int32_t *img_blocks, uint32_t boot_lba,
|
|||||||
|
|
||||||
/* # Offset 446
|
/* # Offset 446
|
||||||
*/
|
*/
|
||||||
|
gpt_cursor= 0;
|
||||||
for (part = 1 ; part <= 4; part++) {
|
for (part = 1 ; part <= 4; part++) {
|
||||||
if (part != part_number) {
|
if ((int) part != part_number) {
|
||||||
/* if this_partition != partition_number: write 16 zero bytes */
|
/* 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);
|
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;
|
wpt+= 16;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
103
libisofs/md5.c
103
libisofs/md5.c
@ -12,7 +12,14 @@
|
|||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_STDINT_H
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_INTTYPES_H
|
||||||
|
#include <inttypes.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.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,
|
static int md5_update(libisofs_md5_ctx *ctx, unsigned char *data,
|
||||||
int datalen, int flag)
|
int datalen, int flag)
|
||||||
{
|
{
|
||||||
unsigned int i, index, partlen;
|
int i, index, partlen;
|
||||||
|
|
||||||
/* Compute number of bytes mod 64 */
|
/* Compute number of bytes mod 64 */
|
||||||
index = (unsigned int)((ctx->count[0] >> 3) & 0x3F);
|
index = ((ctx->count[0] >> 3) & 0x3F);
|
||||||
/* Update number of bits */
|
/* Update number of bits */
|
||||||
if ((ctx->count[0] += ((uint32_t) datalen << 3)) <
|
if ((ctx->count[0] += ((uint32_t) datalen << 3)) <
|
||||||
((uint32_t) datalen << 3))
|
((uint32_t) datalen << 3))
|
||||||
@ -417,6 +424,22 @@ int checksum_cx_xinfo_func(void *data, int flag)
|
|||||||
return 1;
|
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
|
/* Function to identify and manage md5 sums of unspecified providence stored
|
||||||
* directly in this xinfo.
|
* directly in this xinfo.
|
||||||
@ -429,6 +452,24 @@ int checksum_md5_xinfo_func(void *data, int flag)
|
|||||||
return 1;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
/* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
@ -580,11 +621,6 @@ int checksum_writer_write_data(IsoImageWriter *writer)
|
|||||||
void *ctx = NULL;
|
void *ctx = NULL;
|
||||||
char md5[16];
|
char md5[16];
|
||||||
|
|
||||||
#ifdef NIX
|
|
||||||
char tag_block[2048];
|
|
||||||
int l;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (writer == NULL) {
|
if (writer == NULL) {
|
||||||
return ISO_ASSERT_FAILURE;
|
return ISO_ASSERT_FAILURE;
|
||||||
}
|
}
|
||||||
@ -683,15 +719,16 @@ int iso_md5_write_scdbackup_tag(Ecma119Image *t, char *tag_block, int flag)
|
|||||||
{
|
{
|
||||||
void *ctx = NULL;
|
void *ctx = NULL;
|
||||||
off_t pos = 0, line_start;
|
off_t pos = 0, line_start;
|
||||||
int record_len, block_len, res, i;
|
int record_len, block_len, ret, i;
|
||||||
char postext[40], md5[16], record[160];
|
char postext[40], md5[16], *record = NULL;
|
||||||
|
|
||||||
|
LIBISO_ALLOC_MEM(record, char, 160);
|
||||||
line_start = strlen(tag_block);
|
line_start = strlen(tag_block);
|
||||||
iso_md5_compute(t->checksum_ctx, tag_block, line_start);
|
iso_md5_compute(t->checksum_ctx, tag_block, line_start);
|
||||||
res = iso_md5_clone(t->checksum_ctx, &ctx);
|
ret = iso_md5_clone(t->checksum_ctx, &ctx);
|
||||||
if (res < 0)
|
if (ret < 0)
|
||||||
goto ex;
|
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;
|
pos = (off_t) t->checksum_tag_pos * (off_t) 2048 + line_start;
|
||||||
if(pos >= 1000000000)
|
if(pos >= 1000000000)
|
||||||
@ -706,8 +743,8 @@ int iso_md5_write_scdbackup_tag(Ecma119Image *t, char *tag_block, int flag)
|
|||||||
"%2.2x", ((unsigned char *) md5)[i]);
|
"%2.2x", ((unsigned char *) md5)[i]);
|
||||||
record_len += 32;
|
record_len += 32;
|
||||||
|
|
||||||
res = iso_md5_start(&ctx);
|
ret = iso_md5_start(&ctx);
|
||||||
if (res < 0)
|
if (ret < 0)
|
||||||
goto ex;
|
goto ex;
|
||||||
iso_md5_compute(ctx, record, record_len);
|
iso_md5_compute(ctx, record, record_len);
|
||||||
iso_md5_end(&ctx, md5);
|
iso_md5_end(&ctx, md5);
|
||||||
@ -724,11 +761,12 @@ int iso_md5_write_scdbackup_tag(Ecma119Image *t, char *tag_block, int flag)
|
|||||||
if (t->scdbackup_tag_written != NULL)
|
if (t->scdbackup_tag_written != NULL)
|
||||||
strncpy(t->scdbackup_tag_written, tag_block + line_start,
|
strncpy(t->scdbackup_tag_written, tag_block + line_start,
|
||||||
block_len - line_start);
|
block_len - line_start);
|
||||||
res = ISO_SUCCESS;
|
ret = ISO_SUCCESS;
|
||||||
ex:;
|
ex:;
|
||||||
if (ctx != NULL)
|
if (ctx != NULL)
|
||||||
iso_md5_end(&ctx, md5);
|
iso_md5_end(&ctx, md5);
|
||||||
return res;
|
LIBISO_FREE_MEM(record);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -742,20 +780,20 @@ ex:;
|
|||||||
*/
|
*/
|
||||||
int iso_md5_write_tag(Ecma119Image *t, int flag)
|
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;
|
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;
|
uint32_t size = 0, pos = 0, start;
|
||||||
|
|
||||||
|
LIBISO_ALLOC_MEM(tag_block, char, 2048);
|
||||||
start = t->checksum_range_start;
|
start = t->checksum_range_start;
|
||||||
memset(tag_block, 0, 2048);
|
|
||||||
mode = flag & 255;
|
mode = flag & 255;
|
||||||
if (mode < 1 || mode > 4)
|
if (mode < 1 || mode > 4)
|
||||||
return ISO_WRONG_ARG_VALUE;
|
{ret = ISO_WRONG_ARG_VALUE; goto ex;}
|
||||||
res = iso_md5_clone(t->checksum_ctx, &ctx);
|
ret = iso_md5_clone(t->checksum_ctx, &ctx);
|
||||||
if (res < 0)
|
if (ret < 0)
|
||||||
return res;
|
goto ex;
|
||||||
res = iso_md5_end(&ctx, md5);
|
ret = iso_md5_end(&ctx, md5);
|
||||||
if (mode == 1) {
|
if (mode == 1) {
|
||||||
size = t->checksum_range_size;
|
size = t->checksum_range_size;
|
||||||
pos = t->checksum_tag_pos;
|
pos = t->checksum_tag_pos;
|
||||||
@ -770,7 +808,7 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
|
|||||||
}
|
}
|
||||||
size = pos - start;
|
size = pos - start;
|
||||||
}
|
}
|
||||||
if (res < 0)
|
if (ret < 0)
|
||||||
goto ex;
|
goto ex;
|
||||||
|
|
||||||
iso_util_tag_magic(mode, &tag_id, &tag_id_len, 0);
|
iso_util_tag_magic(mode, &tag_id, &tag_id_len, 0);
|
||||||
@ -792,8 +830,8 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
|
|||||||
((unsigned char *) md5)[i]);
|
((unsigned char *) md5)[i]);
|
||||||
l+= 32;
|
l+= 32;
|
||||||
|
|
||||||
res = iso_md5_start(&ctx);
|
ret = iso_md5_start(&ctx);
|
||||||
if (res > 0) {
|
if (ret > 0) {
|
||||||
iso_md5_compute(ctx, tag_block, l);
|
iso_md5_compute(ctx, tag_block, l);
|
||||||
iso_md5_end(&ctx, md5);
|
iso_md5_end(&ctx, md5);
|
||||||
strcpy(tag_block + l, " self=");
|
strcpy(tag_block + l, " self=");
|
||||||
@ -808,8 +846,8 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
|
|||||||
if (t->ms_block > 0) {
|
if (t->ms_block > 0) {
|
||||||
iso_msg_submit(t->image->id, ISO_SCDBACKUP_TAG_NOT_0, 0, NULL);
|
iso_msg_submit(t->image->id, ISO_SCDBACKUP_TAG_NOT_0, 0, NULL);
|
||||||
} else {
|
} else {
|
||||||
res = iso_md5_write_scdbackup_tag(t, tag_block, 0);
|
ret = iso_md5_write_scdbackup_tag(t, tag_block, 0);
|
||||||
if (res < 0)
|
if (ret < 0)
|
||||||
goto ex;
|
goto ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -820,16 +858,17 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
|
|||||||
} else {
|
} else {
|
||||||
wres = iso_write(t, tag_block, 2048);
|
wres = iso_write(t, tag_block, 2048);
|
||||||
if (wres < 0) {
|
if (wres < 0) {
|
||||||
res = wres;
|
ret = wres;
|
||||||
goto ex;
|
goto ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res = ISO_SUCCESS;
|
ret = ISO_SUCCESS;
|
||||||
ex:;
|
ex:;
|
||||||
if (ctx != NULL)
|
if (ctx != NULL)
|
||||||
iso_md5_end(&ctx, md5);
|
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) 2007 Vreixo Formoso
|
||||||
|
* Copyright (c) 2009 - 2011 Thomas Schmitt
|
||||||
*
|
*
|
||||||
* This file is part of the libisofs project; you can redistribute it and/or
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -36,6 +37,7 @@
|
|||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "node.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -79,11 +81,76 @@ int abort_threshold = LIBISO_MSGS_SEV_FAILURE;
|
|||||||
struct libiso_msgs *libiso_msgr = NULL;
|
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);
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------- End of xinfo clone functions list ----------- */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@param flag bit0= do not set up locale by LC_* environment variables
|
@param flag bit0= do not set up locale by LC_* environment variables
|
||||||
*/
|
*/
|
||||||
int iso_init_with_flag(int flag)
|
int iso_init_with_flag(int flag)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
#ifdef Libisofs_with_libjtE
|
#ifdef Libisofs_with_libjtE
|
||||||
|
|
||||||
@ -119,7 +186,6 @@ LIBJTE_MISCONFIGURATION_ = 0;
|
|||||||
|
|
||||||
#endif /* Libisofs_with_libjtE */
|
#endif /* Libisofs_with_libjtE */
|
||||||
|
|
||||||
|
|
||||||
if (! (flag & 1)) {
|
if (! (flag & 1)) {
|
||||||
iso_init_locale(0);
|
iso_init_locale(0);
|
||||||
}
|
}
|
||||||
@ -129,10 +195,33 @@ LIBJTE_MISCONFIGURATION_ = 0;
|
|||||||
}
|
}
|
||||||
libiso_msgs_set_severities(libiso_msgr, LIBISO_MSGS_SEV_NEVER,
|
libiso_msgs_set_severities(libiso_msgr, LIBISO_MSGS_SEV_NEVER,
|
||||||
LIBISO_MSGS_SEV_FATAL, "libisofs: ", 0);
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int iso_init()
|
int iso_init()
|
||||||
{
|
{
|
||||||
return iso_init_with_flag(0);
|
return iso_init_with_flag(0);
|
||||||
@ -141,6 +230,7 @@ int iso_init()
|
|||||||
void iso_finish()
|
void iso_finish()
|
||||||
{
|
{
|
||||||
libiso_msgs_destroy(&libiso_msgr, 0);
|
libiso_msgs_destroy(&libiso_msgr, 0);
|
||||||
|
iso_node_xinfo_dispose_cloners(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int iso_set_abort_severity(char *severity)
|
int iso_set_abort_severity(char *severity)
|
||||||
@ -159,15 +249,18 @@ int iso_set_abort_severity(char *severity)
|
|||||||
|
|
||||||
void iso_msg_debug(int imgid, const char *fmt, ...)
|
void iso_msg_debug(int imgid, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
char msg[MAX_MSG_LEN];
|
char *msg = NULL;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
|
LIBISO_ALLOC_MEM_VOID(msg, char, MAX_MSG_LEN);
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vsnprintf(msg, MAX_MSG_LEN, fmt, ap);
|
vsnprintf(msg, MAX_MSG_LEN, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
libiso_msgs_submit(libiso_msgr, imgid, 0x00000002, LIBISO_MSGS_SEV_DEBUG,
|
libiso_msgs_submit(libiso_msgr, imgid, 0x00000002, LIBISO_MSGS_SEV_DEBUG,
|
||||||
LIBISO_MSGS_PRIO_ZERO, msg, 0, 0);
|
LIBISO_MSGS_PRIO_ZERO, msg, 0, 0);
|
||||||
|
ex:;
|
||||||
|
LIBISO_FREE_MEM(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *iso_error_to_msg(int errcode)
|
const char *iso_error_to_msg(int errcode)
|
||||||
@ -358,11 +451,55 @@ const char *iso_error_to_msg(int errcode)
|
|||||||
case ISO_BAD_PARTITION_FILE:
|
case ISO_BAD_PARTITION_FILE:
|
||||||
return "Cannot open data file for appended partition";
|
return "Cannot open data file for appended partition";
|
||||||
case ISO_NON_MBR_SYS_AREA:
|
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:
|
case ISO_DISPLACE_ROLLOVER:
|
||||||
return "Displacement offset leads outside 32 bit range";
|
return "Displacement offset leads outside 32 bit range";
|
||||||
case ISO_NAME_NEEDS_TRANSL:
|
case ISO_NAME_NEEDS_TRANSL:
|
||||||
return "File name cannot be written into ECMA-119 untranslated";
|
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";
|
||||||
default:
|
default:
|
||||||
return "Unknown error";
|
return "Unknown error";
|
||||||
}
|
}
|
||||||
@ -382,7 +519,7 @@ int iso_msg_submit(int imgid, int errcode, int causedby, const char *fmt, ...)
|
|||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
/* when called with ISO_CANCELED, we don't need to submit any message */
|
/* 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;
|
return ISO_CANCELED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
281
libisofs/node.c
281
libisofs/node.c
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* 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
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -19,6 +19,7 @@
|
|||||||
#include "aaip_0_2.h"
|
#include "aaip_0_2.h"
|
||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "eltorito.h"
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -28,11 +29,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
#ifndef PATH_MAX
|
|
||||||
#define PATH_MAX Libisofs_default_path_maX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
struct dir_iter_data
|
struct dir_iter_data
|
||||||
{
|
{
|
||||||
/* points to the last visited child, to NULL before start */
|
/* 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)
|
void iso_node_unref(IsoNode *node)
|
||||||
{
|
{
|
||||||
|
if (node == NULL)
|
||||||
|
return;
|
||||||
if (--node->refcount == 0) {
|
if (--node->refcount == 0) {
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
case LIBISO_DIR:
|
case LIBISO_DIR:
|
||||||
@ -83,6 +81,14 @@ void iso_node_unref(IsoNode *node)
|
|||||||
IsoSymlink *link = (IsoSymlink*) node;
|
IsoSymlink *link = (IsoSymlink*) node;
|
||||||
free(link->dest);
|
free(link->dest);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case LIBISO_BOOT:
|
||||||
|
{
|
||||||
|
IsoBoot *bootcat = (IsoBoot *) node;
|
||||||
|
if (bootcat->content != NULL)
|
||||||
|
free(bootcat->content);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* other kind of nodes does not need to delete anything here */
|
/* other kind of nodes does not need to delete anything here */
|
||||||
break;
|
break;
|
||||||
@ -226,6 +232,89 @@ int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data)
|
|||||||
return 0;
|
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.
|
* Get the type of an IsoNode.
|
||||||
*/
|
*/
|
||||||
@ -242,6 +331,7 @@ enum IsoNodeType iso_node_get_type(IsoNode *node)
|
|||||||
int iso_node_set_name(IsoNode *node, const char *name)
|
int iso_node_set_name(IsoNode *node, const char *name)
|
||||||
{
|
{
|
||||||
char *new;
|
char *new;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if ((IsoNode*)node->parent == node) {
|
if ((IsoNode*)node->parent == node) {
|
||||||
/* you can't change name of the root node */
|
/* you can't change name of the root node */
|
||||||
@ -249,9 +339,9 @@ int iso_node_set_name(IsoNode *node, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check if the name is valid */
|
/* check if the name is valid */
|
||||||
if (!iso_node_is_valid_name(name)) {
|
ret = iso_node_is_valid_name(name);
|
||||||
return ISO_WRONG_ARG_VALUE;
|
if (ret < 0)
|
||||||
}
|
return ret;
|
||||||
|
|
||||||
if (node->parent != NULL) {
|
if (node->parent != NULL) {
|
||||||
/* check if parent already has a node with same name */
|
/* check if parent already has a node with same name */
|
||||||
@ -651,6 +741,9 @@ int iso_node_take(IsoNode *node)
|
|||||||
if (dir == NULL) {
|
if (dir == NULL) {
|
||||||
return ISO_NODE_NOT_ADDED_TO_DIR;
|
return ISO_NODE_NOT_ADDED_TO_DIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* >>> Do not take root directory ! (dir == node) ? */;
|
||||||
|
|
||||||
pos = iso_dir_find_node(dir, node);
|
pos = iso_dir_find_node(dir, node);
|
||||||
if (pos == NULL) {
|
if (pos == NULL) {
|
||||||
/* should never occur */
|
/* should never occur */
|
||||||
@ -686,6 +779,44 @@ int iso_node_remove(IsoNode *node)
|
|||||||
return ret;
|
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
|
* 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
|
* returned directory, you must take your ref. with iso_node_ref() if you
|
||||||
@ -881,10 +1012,11 @@ const char *iso_symlink_get_dest(const IsoSymlink *link)
|
|||||||
int iso_symlink_set_dest(IsoSymlink *link, const char *dest)
|
int iso_symlink_set_dest(IsoSymlink *link, const char *dest)
|
||||||
{
|
{
|
||||||
char *d;
|
char *d;
|
||||||
if (!iso_node_is_valid_link_dest(dest)) {
|
int ret;
|
||||||
/* guard against null or empty dest */
|
|
||||||
return ISO_WRONG_ARG_VALUE;
|
ret = iso_node_is_valid_link_dest(dest);
|
||||||
}
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
d = strdup(dest);
|
d = strdup(dest);
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
return ISO_OUT_OF_MEM;
|
return ISO_OUT_OF_MEM;
|
||||||
@ -1035,22 +1167,23 @@ int iso_node_is_valid_name(const char *name)
|
|||||||
{
|
{
|
||||||
/* a name can't be NULL */
|
/* a name can't be NULL */
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
return 0;
|
return ISO_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* guard against the empty string or big names... */
|
/* guard against the empty string or big names... */
|
||||||
if (name[0] == '\0' || strlen(name) > 255) {
|
if (name[0] == '\0')
|
||||||
return 0;
|
return ISO_RR_NAME_RESERVED;
|
||||||
}
|
if (strlen(name) > LIBISOFS_NODE_NAME_MAX)
|
||||||
|
return ISO_RR_NAME_TOO_LONG;
|
||||||
|
|
||||||
/* ...against "." and ".." names... */
|
/* ...against "." and ".." names... */
|
||||||
if (!strcmp(name, ".") || !strcmp(name, "..")) {
|
if (!strcmp(name, ".") || !strcmp(name, "..")) {
|
||||||
return 0;
|
return ISO_RR_NAME_RESERVED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ...and against names with '/' */
|
/* ...and against names with '/' */
|
||||||
if (strchr(name, '/') != NULL) {
|
if (strchr(name, '/') != NULL) {
|
||||||
return 0;
|
return ISO_RR_NAME_RESERVED;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1068,13 +1201,14 @@ int iso_node_is_valid_link_dest(const char *dest)
|
|||||||
|
|
||||||
/* a dest can't be NULL */
|
/* a dest can't be NULL */
|
||||||
if (dest == NULL) {
|
if (dest == NULL) {
|
||||||
return 0;
|
return ISO_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* guard against the empty string or big dest... */
|
/* guard against the empty string or big dest... */
|
||||||
if (dest[0] == '\0' || strlen(dest) > PATH_MAX) {
|
if (dest[0] == '\0')
|
||||||
return 0;
|
return ISO_RR_NAME_RESERVED;
|
||||||
}
|
if (strlen(dest) > LIBISOFS_NODE_PATH_MAX)
|
||||||
|
return ISO_RR_PATH_TOO_LONG;
|
||||||
|
|
||||||
/* check that all components are valid */
|
/* check that all components are valid */
|
||||||
if (!strcmp(dest, "/")) {
|
if (!strcmp(dest, "/")) {
|
||||||
@ -1084,7 +1218,7 @@ int iso_node_is_valid_link_dest(const char *dest)
|
|||||||
|
|
||||||
ptr = strdup(dest);
|
ptr = strdup(dest);
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
return 0;
|
return ISO_OUT_OF_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
@ -1092,7 +1226,7 @@ int iso_node_is_valid_link_dest(const char *dest)
|
|||||||
while (component) {
|
while (component) {
|
||||||
if (strcmp(component, ".") && strcmp(component, "..")) {
|
if (strcmp(component, ".") && strcmp(component, "..")) {
|
||||||
ret = iso_node_is_valid_name(component);
|
ret = iso_node_is_valid_name(component);
|
||||||
if (ret == 0) {
|
if (ret < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1251,15 +1385,16 @@ int iso_node_new_root(IsoDir **root)
|
|||||||
int iso_node_new_dir(char *name, IsoDir **dir)
|
int iso_node_new_dir(char *name, IsoDir **dir)
|
||||||
{
|
{
|
||||||
IsoDir *new;
|
IsoDir *new;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (dir == NULL || name == NULL) {
|
if (dir == NULL || name == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if the name is valid */
|
/* check if the name is valid */
|
||||||
if (!iso_node_is_valid_name(name)) {
|
ret = iso_node_is_valid_name(name);
|
||||||
return ISO_WRONG_ARG_VALUE;
|
if (ret < 0)
|
||||||
}
|
return ret;
|
||||||
|
|
||||||
new = calloc(1, sizeof(IsoDir));
|
new = calloc(1, sizeof(IsoDir));
|
||||||
if (new == NULL) {
|
if (new == NULL) {
|
||||||
@ -1276,15 +1411,16 @@ int iso_node_new_dir(char *name, IsoDir **dir)
|
|||||||
int iso_node_new_file(char *name, IsoStream *stream, IsoFile **file)
|
int iso_node_new_file(char *name, IsoStream *stream, IsoFile **file)
|
||||||
{
|
{
|
||||||
IsoFile *new;
|
IsoFile *new;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (file == NULL || name == NULL || stream == NULL) {
|
if (file == NULL || name == NULL || stream == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if the name is valid */
|
/* check if the name is valid */
|
||||||
if (!iso_node_is_valid_name(name)) {
|
ret = iso_node_is_valid_name(name);
|
||||||
return ISO_WRONG_ARG_VALUE;
|
if (ret < 0)
|
||||||
}
|
return ret;
|
||||||
|
|
||||||
new = calloc(1, sizeof(IsoFile));
|
new = calloc(1, sizeof(IsoFile));
|
||||||
if (new == NULL) {
|
if (new == NULL) {
|
||||||
@ -1304,21 +1440,21 @@ int iso_node_new_file(char *name, IsoStream *stream, IsoFile **file)
|
|||||||
int iso_node_new_symlink(char *name, char *dest, IsoSymlink **link)
|
int iso_node_new_symlink(char *name, char *dest, IsoSymlink **link)
|
||||||
{
|
{
|
||||||
IsoSymlink *new;
|
IsoSymlink *new;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (link == NULL || name == NULL || dest == NULL) {
|
if (link == NULL || name == NULL || dest == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if the name is valid */
|
/* check if the name is valid */
|
||||||
if (!iso_node_is_valid_name(name)) {
|
ret = iso_node_is_valid_name(name);
|
||||||
return ISO_WRONG_ARG_VALUE;
|
if (ret < 0)
|
||||||
}
|
return ret;
|
||||||
|
|
||||||
/* check if destination is valid */
|
/* check if destination is valid */
|
||||||
if (!iso_node_is_valid_link_dest(dest)) {
|
ret = iso_node_is_valid_link_dest(dest);
|
||||||
/* guard against null or empty dest */
|
if (ret < 0)
|
||||||
return ISO_WRONG_ARG_VALUE;
|
return ret;
|
||||||
}
|
|
||||||
|
|
||||||
new = calloc(1, sizeof(IsoSymlink));
|
new = calloc(1, sizeof(IsoSymlink));
|
||||||
if (new == NULL) {
|
if (new == NULL) {
|
||||||
@ -1340,6 +1476,7 @@ int iso_node_new_special(char *name, mode_t mode, dev_t dev,
|
|||||||
IsoSpecial **special)
|
IsoSpecial **special)
|
||||||
{
|
{
|
||||||
IsoSpecial *new;
|
IsoSpecial *new;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (special == NULL || name == NULL) {
|
if (special == NULL || name == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
@ -1349,9 +1486,9 @@ int iso_node_new_special(char *name, mode_t mode, dev_t dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check if the name is valid */
|
/* check if the name is valid */
|
||||||
if (!iso_node_is_valid_name(name)) {
|
ret = iso_node_is_valid_name(name);
|
||||||
return ISO_WRONG_ARG_VALUE;
|
if (ret < 0)
|
||||||
}
|
return ret;
|
||||||
|
|
||||||
new = calloc(1, sizeof(IsoSpecial));
|
new = calloc(1, sizeof(IsoSpecial));
|
||||||
if (new == NULL) {
|
if (new == NULL) {
|
||||||
@ -1447,7 +1584,7 @@ int iso_aa_get_attrs(unsigned char *aa_string, size_t *num_attrs,
|
|||||||
goto ex;
|
goto ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rpt - aa_string != len) {
|
if ((size_t) (rpt - aa_string) != len) {
|
||||||
/* aaip_decode_attrs() returns 2 but still bytes are left */
|
/* aaip_decode_attrs() returns 2 but still bytes are left */
|
||||||
ret = ISO_AAIP_BAD_AASTRING;
|
ret = ISO_AAIP_BAD_AASTRING;
|
||||||
goto ex;
|
goto ex;
|
||||||
@ -1489,13 +1626,15 @@ int iso_aa_lookup_attr(unsigned char *aa_string, char *name,
|
|||||||
|
|
||||||
ret = iso_aa_get_attrs(aa_string, &num_attrs, &names,
|
ret = iso_aa_get_attrs(aa_string, &num_attrs, &names,
|
||||||
&value_lengths, &values, 0);
|
&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))
|
if (strcmp(names[i], name))
|
||||||
continue;
|
continue;
|
||||||
*value_length = value_lengths[i];
|
*value_length = value_lengths[i];
|
||||||
*value = calloc(*value_length + 1, 1);
|
*value = calloc(*value_length + 1, 1);
|
||||||
if (*value == NULL) {
|
if (*value == NULL) {
|
||||||
ret = ISO_OUT_OF_MEM;
|
found = ISO_OUT_OF_MEM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (*value_length > 0)
|
if (*value_length > 0)
|
||||||
@ -1588,6 +1727,7 @@ int attr_enlarge_list(char ***names, size_t **value_lengths, char ***values,
|
|||||||
bit2= delete the given names rather than overwrite
|
bit2= delete the given names rather than overwrite
|
||||||
their content
|
their content
|
||||||
bit4= do not overwrite value of empty name
|
bit4= do not overwrite value of empty name
|
||||||
|
bit5= do not overwrite isofs attributes
|
||||||
bit15= release memory and return 1
|
bit15= release memory and return 1
|
||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
@ -1636,6 +1776,8 @@ int iso_node_merge_xattr(IsoNode *node, size_t num_attrs, char **names,
|
|||||||
continue;
|
continue;
|
||||||
if (names[i][0] == 0 && (flag & 16))
|
if (names[i][0] == 0 && (flag & 16))
|
||||||
continue;
|
continue;
|
||||||
|
if ((flag & 32) && strncmp(names[i], "isofs.", 6) == 0)
|
||||||
|
continue;
|
||||||
for (j = 0; j < *m_num_attrs; j++) {
|
for (j = 0; j < *m_num_attrs; j++) {
|
||||||
if ((*m_names)[j] == NULL)
|
if ((*m_names)[j] == NULL)
|
||||||
continue;
|
continue;
|
||||||
@ -1681,6 +1823,8 @@ int iso_node_merge_xattr(IsoNode *node, size_t num_attrs, char **names,
|
|||||||
continue;
|
continue;
|
||||||
if (names[i][0] == 0 && (flag & 16))
|
if (names[i][0] == 0 && (flag & 16))
|
||||||
continue;
|
continue;
|
||||||
|
if ((flag & 32) && strncmp(names[i], "isofs.", 6) == 0)
|
||||||
|
continue;
|
||||||
for (j = 0; j < *m_num_attrs; j++) {
|
for (j = 0; j < *m_num_attrs; j++) {
|
||||||
if ((*m_names)[j] == NULL)
|
if ((*m_names)[j] == NULL)
|
||||||
continue;
|
continue;
|
||||||
@ -1731,13 +1875,13 @@ int iso_node_set_attrs(IsoNode *node, size_t num_attrs, char **names,
|
|||||||
for (i = 0; i < num_attrs; i++)
|
for (i = 0; i < num_attrs; i++)
|
||||||
if (strncmp(names[i], "user.", 5) != 0 && names[i][0] != 0)
|
if (strncmp(names[i], "user.", 5) != 0 && names[i][0] != 0)
|
||||||
return ISO_AAIP_NON_USER_NAME;
|
return ISO_AAIP_NON_USER_NAME;
|
||||||
|
if ((flag & (2 | 4 | 16)) || !(flag & 8)) {
|
||||||
if ((flag & (2 | 4)) || !(flag & 8)) {
|
|
||||||
/* Merge old and new lists */
|
/* Merge old and new lists */
|
||||||
ret = iso_node_merge_xattr(
|
ret = iso_node_merge_xattr(
|
||||||
node, num_attrs, names, value_lengths, values,
|
node, num_attrs, names, value_lengths, values,
|
||||||
&m_num, &m_names, &m_value_lengths, &m_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)
|
if (ret < 0)
|
||||||
goto ex;
|
goto ex;
|
||||||
num_attrs = m_num;
|
num_attrs = m_num;
|
||||||
@ -2012,10 +2156,12 @@ 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,
|
ret = aaip_encode_both_acl(access_text, default_text, st_mode,
|
||||||
&acl_len, &acl, 2 | 8);
|
&acl_len, &acl, 2 | 8);
|
||||||
}
|
}
|
||||||
if (ret <= 0) {
|
if (ret == -1)
|
||||||
ret = ISO_OUT_OF_MEM;
|
ret = ISO_OUT_OF_MEM;
|
||||||
|
else if (ret <= 0 && ret >= -3)
|
||||||
|
ret = ISO_AAIP_BAD_ACL_TEXT;
|
||||||
|
if (ret <= 0)
|
||||||
goto ex;
|
goto ex;
|
||||||
}
|
|
||||||
|
|
||||||
if(acl == NULL) { /* Delete whole ACL attribute */
|
if(acl == NULL) { /* Delete whole ACL attribute */
|
||||||
/* Update S_IRWXG by eventual "group::" ACL entry.
|
/* Update S_IRWXG by eventual "group::" ACL entry.
|
||||||
@ -2068,6 +2214,8 @@ int iso_node_set_acl_text(IsoNode *node, char *access_text, char *default_text,
|
|||||||
}
|
}
|
||||||
ret = aaip_encode_both_acl(access_text, default_text,
|
ret = aaip_encode_both_acl(access_text, default_text,
|
||||||
st_mode, &acl_len, &acl, 2 | 8);
|
st_mode, &acl_len, &acl, 2 | 8);
|
||||||
|
if (ret < -3)
|
||||||
|
goto ex;
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
ret = ISO_AAIP_BAD_ACL_TEXT;
|
ret = ISO_AAIP_BAD_ACL_TEXT;
|
||||||
goto ex;
|
goto ex;
|
||||||
@ -2153,6 +2301,23 @@ int zisofs_zf_xinfo_func(void *data, int flag)
|
|||||||
return 1;
|
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
|
/* 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.
|
* marks this by a struct zisofs_zf_info as xinfo of the file node.
|
||||||
@ -2274,6 +2439,21 @@ int iso_px_ino_xinfo_func(void *data, int flag)
|
|||||||
return 1;
|
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
|
* @param flag
|
||||||
@ -2364,7 +2544,6 @@ int iso_node_set_ino_xinfo(IsoNode *node, ino_t ino, int flag)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int iso_node_set_ino(IsoNode *node, ino_t ino, int flag)
|
int iso_node_set_ino(IsoNode *node, ino_t ino, int flag)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -2693,7 +2872,7 @@ int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag)
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
goto ex;
|
goto ex;
|
||||||
}
|
}
|
||||||
for (i = 0; i < value_len; i++)
|
for (i = 0; i < (int) value_len; i++)
|
||||||
idx = (idx << 8) | ((unsigned char *) value)[i];
|
idx = (idx << 8) | ((unsigned char *) value)[i];
|
||||||
if (idx == 0 || idx > image->checksum_idx_count - 1) {
|
if (idx == 0 || idx > image->checksum_idx_count - 1) {
|
||||||
/* (last index is not MD5 of a file) */
|
/* (last index is not MD5 of a file) */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* 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
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -20,7 +20,38 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_STDINT_H
|
||||||
#include <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
|
* The extended information is a way to attach additional information to each
|
||||||
@ -113,6 +144,7 @@ struct Iso_Dir
|
|||||||
IsoNode *children; /**< list of children. ptr to first child */
|
IsoNode *children; /**< list of children. ptr to first child */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* IMPORTANT: Any change must be reflected by iso_tree_clone_file. */
|
||||||
struct Iso_File
|
struct Iso_File
|
||||||
{
|
{
|
||||||
IsoNode node;
|
IsoNode node;
|
||||||
@ -277,7 +309,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.
|
* Check if a given name is valid for an iso node.
|
||||||
*
|
*
|
||||||
* @return
|
* @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);
|
int iso_node_is_valid_name(const char *name);
|
||||||
|
|
||||||
@ -473,4 +505,35 @@ int iso_root_get_isofsca(IsoNode *node, uint32_t *start_lba, uint32_t *end_lba,
|
|||||||
int flag);
|
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);
|
||||||
|
|
||||||
|
|
||||||
#endif /*LIBISO_NODE_H_*/
|
#endif /*LIBISO_NODE_H_*/
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* Copyright (c) 2007 Vreixo Formoso
|
||||||
* Copyright (c) 2007 Mario Danic
|
* Copyright (c) 2007 Mario Danic
|
||||||
* 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
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -337,7 +337,12 @@ static
|
|||||||
int rrip_add_NM(Ecma119Image *t, struct susp_info *susp, char *name, int size,
|
int rrip_add_NM(Ecma119Image *t, struct susp_info *susp, char *name, int size,
|
||||||
int flags, int ce)
|
int flags, int ce)
|
||||||
{
|
{
|
||||||
uint8_t *NM = malloc(size + 5);
|
uint8_t *NM;
|
||||||
|
|
||||||
|
if (size > 250)
|
||||||
|
return ISO_ASSERT_FAILURE;
|
||||||
|
|
||||||
|
NM = malloc(size + 5);
|
||||||
if (NM == NULL) {
|
if (NM == NULL) {
|
||||||
return ISO_OUT_OF_MEM;
|
return ISO_OUT_OF_MEM;
|
||||||
}
|
}
|
||||||
@ -401,12 +406,15 @@ int rrip_SL_append_comp(size_t *n, uint8_t ***comps, char *s, int size, char fl)
|
|||||||
#ifdef Libisofs_with_rrip_rR
|
#ifdef Libisofs_with_rrip_rR
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add to the given tree node a RR System Use Entry. This is an obsolete
|
* Add a RR System Use Entry to the given tree node. This is an obsolete
|
||||||
* entry from before RRIP-1.10. Nevertheless mkisofs produces it and there
|
* entry from before RRIP-1.10. Nevertheless mkisofs produces it. There
|
||||||
* is the suspicion that Solaris takes it as indication for Rock Ridge.
|
* is the suspicion that some operating systems could take it as indication
|
||||||
|
* for Rock Ridge.
|
||||||
*
|
*
|
||||||
* I once saw a copy of a RRIP spec which mentioned RR. Here i just use
|
* The meaning of the payload byte is documented e.g. in
|
||||||
* the same constant 5 bytes as produced by mkisofs.
|
* /usr/src/linux/fs/isofs/rock.h
|
||||||
|
* It announces the presence of entries PX, PN, SL, NM, CL, PL, RE, TF
|
||||||
|
* by payload byte bits 0 to 7.
|
||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
int rrip_add_RR(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp)
|
int rrip_add_RR(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp)
|
||||||
@ -421,7 +429,14 @@ int rrip_add_RR(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp)
|
|||||||
RR[1] = 'R';
|
RR[1] = 'R';
|
||||||
RR[2] = 5;
|
RR[2] = 5;
|
||||||
RR[3] = 1;
|
RR[3] = 1;
|
||||||
RR[4] = 0201;
|
|
||||||
|
/* <<< ts B20307 : Not all directories have NM, many files have more entries */
|
||||||
|
RR[4] = 0x89; /* TF, NM , PX */
|
||||||
|
|
||||||
|
/* >>> ts B20307 : find out whether n carries
|
||||||
|
PX, PN, SL, NM, CL, PL, RE, TF and mark by bit0 to bit7 in RR[4]
|
||||||
|
*/
|
||||||
|
|
||||||
return susp_append(t, susp, RR);
|
return susp_append(t, susp, RR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,8 +460,8 @@ static
|
|||||||
int rrip_add_SL(Ecma119Image *t, struct susp_info *susp, uint8_t **comp,
|
int rrip_add_SL(Ecma119Image *t, struct susp_info *susp, uint8_t **comp,
|
||||||
size_t n, int ce)
|
size_t n, int ce)
|
||||||
{
|
{
|
||||||
int ret, i, j;
|
int ret;
|
||||||
|
size_t i, j;
|
||||||
int total_comp_len = 0;
|
int total_comp_len = 0;
|
||||||
size_t pos, written = 0;
|
size_t pos, written = 0;
|
||||||
|
|
||||||
@ -905,7 +920,7 @@ int add_zf_field(Ecma119Image *t, Ecma119Node *n, struct susp_info *info,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* API */
|
||||||
int aaip_xinfo_func(void *data, int flag)
|
int aaip_xinfo_func(void *data, int flag)
|
||||||
{
|
{
|
||||||
if (flag & 1) {
|
if (flag & 1) {
|
||||||
@ -914,6 +929,23 @@ int aaip_xinfo_func(void *data, int flag)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* API */
|
||||||
|
int aaip_xinfo_cloner(void *old_data, void **new_data, int flag)
|
||||||
|
{
|
||||||
|
size_t aa_size;
|
||||||
|
|
||||||
|
*new_data = NULL;
|
||||||
|
if (old_data == NULL)
|
||||||
|
return 0;
|
||||||
|
aa_size = aaip_count_bytes((unsigned char *) old_data, 0);
|
||||||
|
if (aa_size <= 0)
|
||||||
|
return ISO_AAIP_BAD_AASTRING;
|
||||||
|
*new_data = calloc(1, aa_size);
|
||||||
|
if (*new_data == NULL)
|
||||||
|
return ISO_OUT_OF_MEM;
|
||||||
|
memcpy(*new_data, old_data, aa_size);
|
||||||
|
return (int) aa_size;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute SUA length and eventual Continuation Area length of field NM and
|
* Compute SUA length and eventual Continuation Area length of field NM and
|
||||||
@ -928,6 +960,7 @@ int aaip_xinfo_func(void *data, int flag)
|
|||||||
* (*su_size and *ce stay unaltered in this case)
|
* (*su_size and *ce stay unaltered in this case)
|
||||||
* <0= error:
|
* <0= error:
|
||||||
* -1= not enough SUA space for 28 bytes of CE entry
|
* -1= not enough SUA space for 28 bytes of CE entry
|
||||||
|
* -2= out of memory
|
||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
|
int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
|
||||||
@ -964,6 +997,12 @@ int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
|
|||||||
if (!(flag & 1))
|
if (!(flag & 1))
|
||||||
goto unannounced_ca;
|
goto unannounced_ca;
|
||||||
namelen = namelen - (space - *su_size - 5);
|
namelen = namelen - (space - *su_size - 5);
|
||||||
|
|
||||||
|
/* >>> SUPER_LONG_RR: Need to handle CA part lengths > 250
|
||||||
|
(This cannot happen with name lengths <= 256, as a part
|
||||||
|
of the name will always fit into the directory entry.)
|
||||||
|
*/;
|
||||||
|
|
||||||
*ce = 5 + namelen;
|
*ce = 5 + namelen;
|
||||||
*su_size = space;
|
*su_size = space;
|
||||||
}
|
}
|
||||||
@ -976,6 +1015,8 @@ int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
|
|||||||
int cew = (*ce != 0); /* are we writing to CA ? */
|
int cew = (*ce != 0); /* are we writing to CA ? */
|
||||||
|
|
||||||
dest = get_rr_fname(t, ((IsoSymlink*)n->node)->dest);
|
dest = get_rr_fname(t, ((IsoSymlink*)n->node)->dest);
|
||||||
|
if (dest == NULL)
|
||||||
|
return -2;
|
||||||
prev = dest;
|
prev = dest;
|
||||||
cur = strchr(prev, '/');
|
cur = strchr(prev, '/');
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -1004,8 +1045,10 @@ int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
|
|||||||
* TODO this can be handled better, but for now SL
|
* TODO this can be handled better, but for now SL
|
||||||
* will be completelly moved into the CA
|
* will be completelly moved into the CA
|
||||||
*/
|
*/
|
||||||
if (!(flag & 1))
|
if (!(flag & 1)) {
|
||||||
|
free(dest);
|
||||||
goto unannounced_ca;
|
goto unannounced_ca;
|
||||||
|
}
|
||||||
cew = 1;
|
cew = 1;
|
||||||
} else {
|
} else {
|
||||||
sl_len += clen;
|
sl_len += clen;
|
||||||
@ -1024,8 +1067,8 @@ int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
|
|||||||
* First, we check how many bytes fit in current
|
* First, we check how many bytes fit in current
|
||||||
* SL field
|
* SL field
|
||||||
*/
|
*/
|
||||||
int fit = 255 - sl_len - 2;
|
ssize_t fit = 255 - sl_len - 2;
|
||||||
if (clen - 250 <= fit) {
|
if ((ssize_t) (clen - 250) <= fit) {
|
||||||
/*
|
/*
|
||||||
* the component can be divided between this
|
* the component can be divided between this
|
||||||
* and another SL entry
|
* and another SL entry
|
||||||
@ -1105,6 +1148,44 @@ unannounced_ca:;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* @param flag bit0= Do not add data but only count sua_free and ce_len
|
||||||
|
param info may be NULL in this case
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
int add_aa_string(Ecma119Image *t, Ecma119Node *n, struct susp_info *info,
|
||||||
|
size_t *sua_free, size_t *ce_len, int flag)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint8_t *aapt;
|
||||||
|
void *xipt;
|
||||||
|
size_t num_aapt= 0;
|
||||||
|
|
||||||
|
if (!t->aaip)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
ret = iso_node_get_xinfo(n->node, aaip_xinfo_func, &xipt);
|
||||||
|
if (ret == 1) {
|
||||||
|
num_aapt = aaip_count_bytes((unsigned char *) xipt, 0);
|
||||||
|
if (num_aapt > 0) {
|
||||||
|
if (flag & 1) {
|
||||||
|
ret = aaip_add_AL(t, NULL,NULL, num_aapt, sua_free, ce_len, 1);
|
||||||
|
} else {
|
||||||
|
aapt = malloc(num_aapt);
|
||||||
|
if (aapt == NULL)
|
||||||
|
return ISO_OUT_OF_MEM;
|
||||||
|
memcpy(aapt, xipt, num_aapt);
|
||||||
|
ret = aaip_add_AL(t, info, &aapt, num_aapt, sua_free, ce_len,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
/* aapt is NULL now and the memory is owned by t */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the length needed for write all RR and SUSP entries for a given
|
* Compute the length needed for write all RR and SUSP entries for a given
|
||||||
* node.
|
* node.
|
||||||
@ -1124,6 +1205,7 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t used_up,
|
|||||||
{
|
{
|
||||||
size_t su_size, space;
|
size_t su_size, space;
|
||||||
int ret;
|
int ret;
|
||||||
|
size_t aaip_sua_free= 0, aaip_len= 0;
|
||||||
|
|
||||||
/* Directory record length must be even (ECMA-119, 9.1.13). Maximum is 254.
|
/* Directory record length must be even (ECMA-119, 9.1.13). Maximum is 254.
|
||||||
*/
|
*/
|
||||||
@ -1164,6 +1246,10 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t used_up,
|
|||||||
/* we need to add a RE entry */
|
/* we need to add a RE entry */
|
||||||
su_size += 4;
|
su_size += 4;
|
||||||
}
|
}
|
||||||
|
} else if(ecma119_is_dedicated_reloc_dir(t, n) &&
|
||||||
|
(t->rr_reloc_flags & 1)) {
|
||||||
|
/* The dedicated relocation directory shall be marked by RE */
|
||||||
|
su_size += 4;
|
||||||
}
|
}
|
||||||
} else if (n->type == ECMA119_SPECIAL) {
|
} else if (n->type == ECMA119_SPECIAL) {
|
||||||
if (S_ISBLK(n->node->mode) || S_ISCHR(n->node->mode)) {
|
if (S_ISBLK(n->node->mode) || S_ISCHR(n->node->mode)) {
|
||||||
@ -1180,13 +1266,16 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t used_up,
|
|||||||
/* Try without CE */
|
/* Try without CE */
|
||||||
ret = susp_calc_nm_sl_al(t, n, space, &su_size, ce, 0);
|
ret = susp_calc_nm_sl_al(t, n, space, &su_size, ce, 0);
|
||||||
if (ret == 0) /* Retry with CE */
|
if (ret == 0) /* Retry with CE */
|
||||||
susp_calc_nm_sl_al(t, n, space, &su_size, ce, 1);
|
ret = susp_calc_nm_sl_al(t, n, space, &su_size, ce, 1);
|
||||||
|
if (ret == -2)
|
||||||
|
return ISO_OUT_OF_MEM;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* "." or ".." entry */
|
/* "." or ".." entry */
|
||||||
|
|
||||||
su_size += 5; /* NM field */
|
if (!t->rrip_version_1_10)
|
||||||
|
su_size += 5; /* NM field */
|
||||||
|
|
||||||
if (type == 1 && n->parent == NULL) {
|
if (type == 1 && n->parent == NULL) {
|
||||||
/*
|
/*
|
||||||
@ -1201,9 +1290,15 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t used_up,
|
|||||||
} else {
|
} else {
|
||||||
*ce = 182;
|
*ce = 182;
|
||||||
}
|
}
|
||||||
if (t->aaip) {
|
if (t->aaip && !t->aaip_susp_1_10) {
|
||||||
*ce += 160; /* ER of AAIP */
|
*ce += 160; /* ER of AAIP */
|
||||||
}
|
}
|
||||||
|
/* Compute length of AAIP string of root node */
|
||||||
|
aaip_sua_free= 0;
|
||||||
|
ret = add_aa_string(t, n, NULL, &aaip_sua_free, &aaip_len, 1);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
*ce += aaip_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1235,43 +1330,6 @@ void susp_info_free(struct susp_info* susp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* @param flag bit0= Do not add data but only count sua_free and ce_len
|
|
||||||
*/
|
|
||||||
static
|
|
||||||
int add_aa_string(Ecma119Image *t, Ecma119Node *n, struct susp_info *info,
|
|
||||||
size_t *sua_free, size_t *ce_len, int flag)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
uint8_t *aapt;
|
|
||||||
void *xipt;
|
|
||||||
size_t num_aapt= 0;
|
|
||||||
|
|
||||||
if (!t->aaip)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
ret = iso_node_get_xinfo(n->node, aaip_xinfo_func, &xipt);
|
|
||||||
if (ret == 1) {
|
|
||||||
num_aapt = aaip_count_bytes((unsigned char *) xipt, 0);
|
|
||||||
if (num_aapt > 0) {
|
|
||||||
if (flag & 1) {
|
|
||||||
ret = aaip_add_AL(t, NULL,NULL, num_aapt, sua_free, ce_len, 1);
|
|
||||||
} else {
|
|
||||||
aapt = malloc(num_aapt);
|
|
||||||
if (aapt == NULL)
|
|
||||||
return ISO_OUT_OF_MEM;
|
|
||||||
memcpy(aapt, xipt, num_aapt);
|
|
||||||
ret = aaip_add_AL(t, info, &aapt, num_aapt, sua_free, ce_len,
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
/* aapt is NULL now and the memory is owned by t */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill a struct susp_info with the RR/SUSP entries needed for a given
|
* Fill a struct susp_info with the RR/SUSP entries needed for a given
|
||||||
* node.
|
* node.
|
||||||
@ -1302,7 +1360,7 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
|
|||||||
size_t su_size_pd, ce_len_pd; /* predicted sizes of SUA and CA */
|
size_t su_size_pd, ce_len_pd; /* predicted sizes of SUA and CA */
|
||||||
int ce_is_predicted = 0;
|
int ce_is_predicted = 0;
|
||||||
size_t aaip_sua_free= 0, aaip_len= 0;
|
size_t aaip_sua_free= 0, aaip_len= 0;
|
||||||
size_t space;
|
int space;
|
||||||
|
|
||||||
if (t == NULL || n == NULL || info == NULL) {
|
if (t == NULL || n == NULL || info == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
@ -1314,7 +1372,7 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
|
|||||||
if (type < 0 || type > 2 || space < ISO_ROCKRIDGE_IN_DIR_REC) {
|
if (type < 0 || type > 2 || space < ISO_ROCKRIDGE_IN_DIR_REC) {
|
||||||
iso_msg_submit(t->image->id, ISO_ASSERT_FAILURE, 0,
|
iso_msg_submit(t->image->id, ISO_ASSERT_FAILURE, 0,
|
||||||
"Unknown node type %d or short RR space %d < %d in directory record",
|
"Unknown node type %d or short RR space %d < %d in directory record",
|
||||||
type, (int) space, ISO_ROCKRIDGE_IN_DIR_REC);
|
type, space, ISO_ROCKRIDGE_IN_DIR_REC);
|
||||||
return ISO_ASSERT_FAILURE;
|
return ISO_ASSERT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1378,6 +1436,12 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
|
|||||||
goto add_susp_cleanup;
|
goto add_susp_cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if(ecma119_is_dedicated_reloc_dir(t, n) &&
|
||||||
|
(t->rr_reloc_flags & 1)) {
|
||||||
|
/* The dedicated relocation directory shall be marked by RE */
|
||||||
|
ret = rrip_add_RE(t, node, info);
|
||||||
|
if (ret < 0)
|
||||||
|
goto add_susp_cleanup;
|
||||||
}
|
}
|
||||||
} else if (n->type == ECMA119_SPECIAL) {
|
} else if (n->type == ECMA119_SPECIAL) {
|
||||||
if (S_ISBLK(n->node->mode) || S_ISCHR(n->node->mode)) {
|
if (S_ISBLK(n->node->mode) || S_ISCHR(n->node->mode)) {
|
||||||
@ -1398,7 +1462,7 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
|
|||||||
if (info->suf_len + 28 > space) {
|
if (info->suf_len + 28 > space) {
|
||||||
iso_msg_submit(t->image->id, ISO_ASSERT_FAILURE, 0,
|
iso_msg_submit(t->image->id, ISO_ASSERT_FAILURE, 0,
|
||||||
"Directory Record overflow. name='%s' , suf_len=%d > space=%d - 28\n",
|
"Directory Record overflow. name='%s' , suf_len=%d > space=%d - 28\n",
|
||||||
node->iso_name, (int) info->suf_len, (int) space);
|
node->iso_name, (int) info->suf_len, space);
|
||||||
return ISO_ASSERT_FAILURE;
|
return ISO_ASSERT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1420,12 +1484,18 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
|
|||||||
/* Try whether NM, SL, AL will fit into SUA */
|
/* Try whether NM, SL, AL will fit into SUA */
|
||||||
su_size_pd = info->suf_len;
|
su_size_pd = info->suf_len;
|
||||||
ce_len_pd = ce_len;
|
ce_len_pd = ce_len;
|
||||||
ret = susp_calc_nm_sl_al(t, n, space, &su_size_pd, &ce_len_pd, 0);
|
ret = susp_calc_nm_sl_al(t, n, (size_t) space,
|
||||||
|
&su_size_pd, &ce_len_pd, 0);
|
||||||
if (ret == 0) { /* Have to use CA. 28 bytes of CE are necessary */
|
if (ret == 0) { /* Have to use CA. 28 bytes of CE are necessary */
|
||||||
susp_calc_nm_sl_al(t, n, space, &su_size_pd, &ce_len_pd, 1);
|
ret = susp_calc_nm_sl_al(t, n, (size_t) space,
|
||||||
|
&su_size_pd, &ce_len_pd, 1);
|
||||||
sua_free -= 28;
|
sua_free -= 28;
|
||||||
ce_is_predicted = 1;
|
ce_is_predicted = 1;
|
||||||
}
|
}
|
||||||
|
if (ret == -2) {
|
||||||
|
ret = ISO_OUT_OF_MEM;
|
||||||
|
goto add_susp_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* NM entry */
|
/* NM entry */
|
||||||
if (5 + namelen <= sua_free) {
|
if (5 + namelen <= sua_free) {
|
||||||
@ -1510,8 +1580,8 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
|
|||||||
* First, we check how many bytes fit in current
|
* First, we check how many bytes fit in current
|
||||||
* SL field
|
* SL field
|
||||||
*/
|
*/
|
||||||
int fit = 255 - sl_len - 2;
|
ssize_t fit = 255 - sl_len - 2;
|
||||||
if (clen - 250 <= fit) {
|
if ((ssize_t) (clen - 250) <= fit) {
|
||||||
/*
|
/*
|
||||||
* the component can be divided between this
|
* the component can be divided between this
|
||||||
* and another SL entry
|
* and another SL entry
|
||||||
@ -1623,6 +1693,12 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
|
|||||||
/*
|
/*
|
||||||
* ..and the part that goes to continuation area.
|
* ..and the part that goes to continuation area.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* >>> SUPER_LONG_RR : Need a loop to handle CA lengths > 250
|
||||||
|
(This cannot happen with name lengths <= 256, as a part
|
||||||
|
of the name will always fit into the directory entry.)
|
||||||
|
*/;
|
||||||
|
|
||||||
ret = rrip_add_NM(t, info, name + namelen, strlen(name + namelen),
|
ret = rrip_add_NM(t, info, name + namelen, strlen(name + namelen),
|
||||||
0, 1);
|
0, 1);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -1664,9 +1740,36 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
|
|||||||
/* "." or ".." entry */
|
/* "." or ".." entry */
|
||||||
|
|
||||||
/* write the NM entry */
|
/* write the NM entry */
|
||||||
ret = rrip_add_NM(t, info, NULL, 0, 1 << type, 0);
|
if (t->rrip_version_1_10) {
|
||||||
if (ret < 0) {
|
/* RRIP-1.10:
|
||||||
goto add_susp_cleanup;
|
"NM" System Use Fields recorded for the ISO 9660 directory
|
||||||
|
records with names (00) and (01), used to designate the
|
||||||
|
current and parent directories, respectively, should be
|
||||||
|
ignored. Instead, the receiving system should convert these
|
||||||
|
names to the appropriate receiving system-dependent
|
||||||
|
designations for the current and parent directories.
|
||||||
|
*/
|
||||||
|
/* mkisofs obviously writes no NM for '.' and '..' .
|
||||||
|
Program isoinfo shows empty names with records as of RRIP-1.12
|
||||||
|
*/
|
||||||
|
/* no op */;
|
||||||
|
} else {
|
||||||
|
/* RRIP-1.12:
|
||||||
|
If the ISO 9660 Directory Record File Identifier is (00), then
|
||||||
|
the CURRENT bit of the "NM" Flags field [...], if present, shall
|
||||||
|
be set to ONE. If the ISO 9660 Directory Record File Identifier
|
||||||
|
is (01), then the PARENT bit of the "NM" Flags field [...],
|
||||||
|
if present, shall be set to ONE.
|
||||||
|
[...]
|
||||||
|
"BP 3 - Length (LEN_NM)" shall specify as an 8-bit number the
|
||||||
|
length in bytes [...]. If bit position 1, 2, or 5 of the "NM"
|
||||||
|
Flags is set to ONE, the value of this field shall be 5 and no
|
||||||
|
Name Content shall be recorded.
|
||||||
|
[The CURRENT bit has position 1. The PARENT bit has position 2.]
|
||||||
|
*/
|
||||||
|
ret = rrip_add_NM(t, info, NULL, 0, 1 << type, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
goto add_susp_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == 1 && n->parent == NULL) {
|
if (type == 1 && n->parent == NULL) {
|
||||||
@ -1688,7 +1791,7 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
|
|||||||
|
|
||||||
/* Compute length of AAIP string of root node */
|
/* Compute length of AAIP string of root node */
|
||||||
aaip_sua_free= 0;
|
aaip_sua_free= 0;
|
||||||
ret = add_aa_string(t, n, info, &aaip_sua_free, &aaip_len, 1);
|
ret = add_aa_string(t, n, NULL, &aaip_sua_free, &aaip_len, 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto add_susp_cleanup;
|
goto add_susp_cleanup;
|
||||||
|
|
||||||
@ -1774,12 +1877,13 @@ void rrip_write_susp_fields(Ecma119Image *t, struct susp_info *info,
|
|||||||
int rrip_write_ce_fields(Ecma119Image *t, struct susp_info *info)
|
int rrip_write_ce_fields(Ecma119Image *t, struct susp_info *info)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
uint8_t padding[BLOCK_SIZE];
|
uint8_t *padding = NULL;
|
||||||
int ret= ISO_SUCCESS;
|
int ret= ISO_SUCCESS;
|
||||||
|
|
||||||
if (info->n_ce_susp_fields == 0) {
|
if (info->n_ce_susp_fields == 0) {
|
||||||
return ret;
|
goto ex;
|
||||||
}
|
}
|
||||||
|
LIBISO_ALLOC_MEM(padding, uint8_t, BLOCK_SIZE);
|
||||||
|
|
||||||
for (i = 0; i < info->n_ce_susp_fields; i++) {
|
for (i = 0; i < info->n_ce_susp_fields; i++) {
|
||||||
ret = iso_write(t, info->ce_susp_fields[i],
|
ret = iso_write(t, info->ce_susp_fields[i],
|
||||||
@ -1805,6 +1909,8 @@ int rrip_write_ce_fields(Ecma119Image *t, struct susp_info *info)
|
|||||||
info->ce_susp_fields = NULL;
|
info->ce_susp_fields = NULL;
|
||||||
info->n_ce_susp_fields = 0;
|
info->n_ce_susp_fields = 0;
|
||||||
info->ce_len = 0;
|
info->ce_len = 0;
|
||||||
|
ex:;
|
||||||
|
LIBISO_FREE_MEM(padding);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,8 +81,7 @@ int susp_iter_next(SuspIterator *iter, struct susp_sys_user_entry **sue)
|
|||||||
* (IEEE 1281, SUSP. section 4)
|
* (IEEE 1281, SUSP. section 4)
|
||||||
*/
|
*/
|
||||||
if (iter->ce_len) {
|
if (iter->ce_len) {
|
||||||
uint32_t block;
|
uint32_t block, nblocks;
|
||||||
int nblocks;
|
|
||||||
|
|
||||||
/* A CE has found, there is another continuation area */
|
/* A CE has found, there is another continuation area */
|
||||||
nblocks = DIV_UP(iter->ce_off + iter->ce_len, BLOCK_SIZE);
|
nblocks = DIV_UP(iter->ce_off + iter->ce_len, BLOCK_SIZE);
|
||||||
@ -443,7 +442,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,
|
int read_aaip_AA(struct susp_sys_user_entry *sue,
|
||||||
unsigned char **aa_string, size_t *aa_size, size_t *aa_len,
|
unsigned char **aa_string, size_t *aa_size, size_t *aa_len,
|
||||||
@ -514,7 +513,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,
|
int read_aaip_AL(struct susp_sys_user_entry *sue,
|
||||||
unsigned char **aa_string, size_t *aa_size, size_t *aa_len,
|
unsigned char **aa_string, size_t *aa_size, size_t *aa_len,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* 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
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -16,6 +16,7 @@
|
|||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "fsource.h"
|
#include "fsource.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "node.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -157,8 +158,65 @@ int fsrc_update_size(IsoStream *stream)
|
|||||||
return ISO_SUCCESS;
|
return ISO_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
IsoStream *fsrc_get_input_stream(IsoStream *stream, int flag)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int fsrc_cmp_ino(IsoStream *s1, IsoStream *s2)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = iso_stream_cmp_ino(s1, s2, 1);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fsrc_clone_stream(IsoStream *old_stream, IsoStream **new_stream,
|
||||||
|
int flag)
|
||||||
|
{
|
||||||
|
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 = {
|
IsoStreamIface fsrc_stream_class = {
|
||||||
1, /* update_size is defined for this stream */
|
4, /* version */
|
||||||
"fsrc",
|
"fsrc",
|
||||||
fsrc_open,
|
fsrc_open,
|
||||||
fsrc_close,
|
fsrc_close,
|
||||||
@ -167,7 +225,10 @@ IsoStreamIface fsrc_stream_class = {
|
|||||||
fsrc_is_repeatable,
|
fsrc_is_repeatable,
|
||||||
fsrc_get_id,
|
fsrc_get_id,
|
||||||
fsrc_free,
|
fsrc_free,
|
||||||
fsrc_update_size
|
fsrc_update_size,
|
||||||
|
fsrc_get_input_stream,
|
||||||
|
fsrc_cmp_ino,
|
||||||
|
fsrc_clone_stream
|
||||||
};
|
};
|
||||||
|
|
||||||
int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream)
|
int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream)
|
||||||
@ -338,7 +399,7 @@ static
|
|||||||
int cut_out_read(IsoStream *stream, void *buf, size_t count)
|
int cut_out_read(IsoStream *stream, void *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct cut_out_stream *data = stream->data;
|
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) {
|
if (count == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -375,11 +436,77 @@ void cut_out_free(IsoStream *stream)
|
|||||||
free(data);
|
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_cmp_ino(IsoStream *s1, IsoStream *s2)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = iso_stream_cmp_ino(s1, s2, 1);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int cut_out_clone_stream(IsoStream *old_stream, IsoStream **new_stream,
|
||||||
|
int flag)
|
||||||
|
{
|
||||||
|
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.
|
* TODO update cut out streams to deal with update_size(). Seems hard.
|
||||||
*/
|
*/
|
||||||
|
static
|
||||||
IsoStreamIface cut_out_stream_class = {
|
IsoStreamIface cut_out_stream_class = {
|
||||||
0,
|
4, /* version */
|
||||||
"cout",
|
"cout",
|
||||||
cut_out_open,
|
cut_out_open,
|
||||||
cut_out_close,
|
cut_out_close,
|
||||||
@ -387,7 +514,12 @@ IsoStreamIface cut_out_stream_class = {
|
|||||||
cut_out_read,
|
cut_out_read,
|
||||||
cut_out_is_repeatable,
|
cut_out_is_repeatable,
|
||||||
cut_out_get_id,
|
cut_out_get_id,
|
||||||
cut_out_free
|
cut_out_free,
|
||||||
|
cut_out_update_size,
|
||||||
|
cut_out_get_input_stream,
|
||||||
|
cut_out_cmp_ino,
|
||||||
|
cut_out_clone_stream
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
|
int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
|
||||||
@ -517,7 +649,7 @@ int mem_read(IsoStream *stream, void *buf, size_t count)
|
|||||||
return ISO_FILE_NOT_OPENED;
|
return ISO_FILE_NOT_OPENED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->offset >= data->size) {
|
if (data->offset >= (ssize_t) data->size) {
|
||||||
return 0; /* EOF */
|
return 0; /* EOF */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,12 +681,78 @@ void mem_free(IsoStream *stream)
|
|||||||
{
|
{
|
||||||
MemStreamData *data;
|
MemStreamData *data;
|
||||||
data = (MemStreamData*)stream->data;
|
data = (MemStreamData*)stream->data;
|
||||||
free(data->buf);
|
if (data->buf != NULL)
|
||||||
|
free(data->buf);
|
||||||
free(data);
|
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_cmp_ino(IsoStream *s1, IsoStream *s2)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = iso_stream_cmp_ino(s1, s2, 1);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int mem_clone_stream(IsoStream *old_stream, IsoStream **new_stream,
|
||||||
|
int flag)
|
||||||
|
{
|
||||||
|
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 = {
|
IsoStreamIface mem_stream_class = {
|
||||||
0,
|
4, /* version */
|
||||||
"mem ",
|
"mem ",
|
||||||
mem_open,
|
mem_open,
|
||||||
mem_close,
|
mem_close,
|
||||||
@ -562,7 +760,12 @@ IsoStreamIface mem_stream_class = {
|
|||||||
mem_read,
|
mem_read,
|
||||||
mem_is_repeatable,
|
mem_is_repeatable,
|
||||||
mem_get_id,
|
mem_get_id,
|
||||||
mem_free
|
mem_free,
|
||||||
|
mem_update_size,
|
||||||
|
mem_get_input_stream,
|
||||||
|
mem_cmp_ino,
|
||||||
|
mem_clone_stream
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -570,7 +773,7 @@ IsoStreamIface mem_stream_class = {
|
|||||||
* When the Stream refcount reach 0, the buffer is free(3).
|
* When the Stream refcount reach 0, the buffer is free(3).
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* 1 sucess, < 0 error
|
* 1 success, < 0 error
|
||||||
*/
|
*/
|
||||||
int iso_memory_stream_new(unsigned char *buf, size_t size, IsoStream **stream)
|
int iso_memory_stream_new(unsigned char *buf, size_t size, IsoStream **stream)
|
||||||
{
|
{
|
||||||
@ -669,7 +872,12 @@ void iso_stream_get_file_name(IsoStream *stream, char *name)
|
|||||||
if (!strncmp(type, "fsrc", 4)) {
|
if (!strncmp(type, "fsrc", 4)) {
|
||||||
FSrcStreamData *data = stream->data;
|
FSrcStreamData *data = stream->data;
|
||||||
char *path = iso_file_source_get_path(data->src);
|
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);
|
free(path);
|
||||||
} else if (!strncmp(type, "boot", 4)) {
|
} else if (!strncmp(type, "boot", 4)) {
|
||||||
strcpy(name, "BOOT CATALOG");
|
strcpy(name, "BOOT CATALOG");
|
||||||
@ -875,14 +1083,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 iso_stream_make_md5(IsoStream *stream, char md5[16], int flag)
|
||||||
{
|
{
|
||||||
int res, is_open = 0;
|
int ret, is_open = 0;
|
||||||
char buffer[2048];
|
char * buffer = NULL;
|
||||||
void *ctx= NULL;
|
void *ctx= NULL;
|
||||||
off_t file_size;
|
off_t file_size;
|
||||||
uint32_t b, nblocks;
|
uint32_t b, nblocks;
|
||||||
size_t got_bytes;
|
size_t got_bytes;
|
||||||
IsoStream *input_stream;
|
IsoStream *input_stream;
|
||||||
|
|
||||||
|
LIBISO_ALLOC_MEM(buffer, char, 2048);
|
||||||
if (flag & 1) {
|
if (flag & 1) {
|
||||||
while(1) {
|
while(1) {
|
||||||
input_stream = iso_stream_get_input_stream(stream, 0);
|
input_stream = iso_stream_get_input_stream(stream, 0);
|
||||||
@ -893,34 +1102,74 @@ int iso_stream_make_md5(IsoStream *stream, char md5[16], int flag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (! iso_stream_is_repeatable(stream))
|
if (! iso_stream_is_repeatable(stream))
|
||||||
return 0;
|
{ret = 0; goto ex;}
|
||||||
res = iso_md5_start(&ctx);
|
ret = iso_md5_start(&ctx);
|
||||||
if (res < 0)
|
if (ret < 0)
|
||||||
return res;
|
goto ex;
|
||||||
res = iso_stream_open(stream);
|
ret = iso_stream_open(stream);
|
||||||
if (res < 0)
|
if (ret < 0)
|
||||||
return 0;
|
goto ex;
|
||||||
is_open = 1;
|
is_open = 1;
|
||||||
file_size = iso_stream_get_size(stream);
|
file_size = iso_stream_get_size(stream);
|
||||||
nblocks = DIV_UP(file_size, 2048);
|
nblocks = DIV_UP(file_size, 2048);
|
||||||
for (b = 0; b < nblocks; ++b) {
|
for (b = 0; b < nblocks; ++b) {
|
||||||
res = iso_stream_read_buffer(stream, buffer, 2048, &got_bytes);
|
ret = iso_stream_read_buffer(stream, buffer, 2048, &got_bytes);
|
||||||
if (res < 0) {
|
if (ret < 0) {
|
||||||
res = 0;
|
ret = 0;
|
||||||
goto ex;
|
goto ex;
|
||||||
}
|
}
|
||||||
/* Do not use got_bytes to stay closer to IsoFileSrc processing */
|
/* Do not use got_bytes to stay closer to IsoFileSrc processing */
|
||||||
if (file_size - b * 2048 > 2048)
|
if (file_size - b * 2048 > 2048)
|
||||||
res = 2048;
|
ret = 2048;
|
||||||
else
|
else
|
||||||
res = file_size - b * 2048;
|
ret = file_size - b * 2048;
|
||||||
iso_md5_compute(ctx, buffer, res);
|
iso_md5_compute(ctx, buffer, ret);
|
||||||
}
|
}
|
||||||
res = 1;
|
ret = 1;
|
||||||
ex:;
|
ex:;
|
||||||
if (is_open)
|
if (is_open)
|
||||||
iso_stream_close(stream);
|
iso_stream_close(stream);
|
||||||
if (ctx != NULL)
|
if (ctx != NULL)
|
||||||
iso_md5_end(&ctx, md5);
|
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) 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
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "fsource.h"
|
#include "fsource.h"
|
||||||
|
|
||||||
|
/* IMPORTANT: Any change must be reflected by fsrc_clone_stream */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
IsoFileSource *src;
|
IsoFileSource *src;
|
||||||
@ -28,7 +29,8 @@ typedef struct
|
|||||||
/**
|
/**
|
||||||
* Get an identifier for the file of the source, for debug purposes
|
* Get an identifier for the file of the source, for debug purposes
|
||||||
* @param name
|
* @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);
|
void iso_stream_get_file_name(IsoStream *stream, char *name);
|
||||||
|
|
||||||
@ -94,5 +96,20 @@ 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 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);
|
||||||
|
|
||||||
#endif /*STREAM_H_*/
|
#endif /*STREAM_H_*/
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Vreixo Formoso
|
* Copyright (c) 2008 Vreixo Formoso
|
||||||
|
* Copyright (c) 2012 Thomas Schmitt
|
||||||
*
|
*
|
||||||
* This file is part of the libisofs project; you can redistribute it and/or
|
* 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
|
* 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);
|
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.
|
* Read the necessary ELF information from the first MIPS boot file.
|
||||||
@ -58,4 +64,206 @@ int iso_read_mipsel_elf(Ecma119Image *t, int flag);
|
|||||||
*/
|
*/
|
||||||
int iso_compute_append_partitions(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 2 KiB */
|
||||||
|
uint32_t start_block;
|
||||||
|
|
||||||
|
/* A block count of 0 means that the partition reaches up to the start of
|
||||||
|
the next one.
|
||||||
|
*/
|
||||||
|
uint32_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(Ecma119Image *t,
|
||||||
|
struct iso_mbr_partition_request *req, int flag);
|
||||||
|
|
||||||
|
/* Convenience frontend for iso_register_mbr_entry().
|
||||||
|
name and type are 0-terminated strings, which may get silently truncated.
|
||||||
|
*/
|
||||||
|
int iso_quick_mbr_entry(Ecma119Image *t,
|
||||||
|
uint32_t start_block, uint32_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(Ecma119Image *t, int slot);
|
||||||
|
|
||||||
|
|
||||||
|
/* The parameter struct for production of a single Apple Partition Map entry.
|
||||||
|
See also the partial APM description in doc/boot_sectors.txt.
|
||||||
|
The list of entries is stored in Ecma119Image.apm_req.
|
||||||
|
The 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.
|
||||||
|
*/
|
||||||
|
uint32_t start_block;
|
||||||
|
uint32_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(Ecma119Image *t,
|
||||||
|
struct iso_apm_partition_request *req, int flag);
|
||||||
|
|
||||||
|
/* Convenience frontend for iso_register_apm_entry().
|
||||||
|
name and type are 0-terminated strings, which may get silently truncated.
|
||||||
|
*/
|
||||||
|
int iso_quick_apm_entry(Ecma119Image *t,
|
||||||
|
uint32_t start_block, uint32_t block_count, char *name, char *type);
|
||||||
|
|
||||||
|
|
||||||
|
/* CRC-32 as of GPT and Ethernet.
|
||||||
|
*/
|
||||||
|
unsigned int iso_crc32_gpt(unsigned char *data, int count, int flag);
|
||||||
|
|
||||||
|
|
||||||
|
/* 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 weakly random variation of a hardcoded real random uuid
|
||||||
|
*/
|
||||||
|
void iso_random_uuid(Ecma119Image *t, uint8_t uuid[16]);
|
||||||
|
|
||||||
|
|
||||||
|
/* 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 2 KiB.
|
||||||
|
Written to the ISO image in blocks of 512.
|
||||||
|
*/
|
||||||
|
uint32_t start_block;
|
||||||
|
uint32_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];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Copies the content of req and registers it in t.gpt_req[].
|
||||||
|
I.e. after the call the submitted storage of req can be disposed or re-used.
|
||||||
|
Submit 0 as value flag.
|
||||||
|
*/
|
||||||
|
int iso_register_gpt_entry(Ecma119Image *t,
|
||||||
|
struct iso_gpt_partition_request *req, int flag);
|
||||||
|
|
||||||
|
/* Convenience frontend for iso_register_gpt_entry().
|
||||||
|
name has to be already encoded as UTF-16LE.
|
||||||
|
*/
|
||||||
|
int iso_quick_gpt_entry(Ecma119Image *t,
|
||||||
|
uint32_t start_block, uint32_t block_count,
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Creates the Partition Prepend writer.
|
||||||
|
*/
|
||||||
|
int partprepend_writer_create(Ecma119Image *target);
|
||||||
|
|
||||||
|
/* Creates the GPT backup tail writer.
|
||||||
|
*/
|
||||||
|
int gpt_tail_writer_create(Ecma119Image *target);
|
||||||
|
|
||||||
|
/* Only for up to 36 characters ISO-8859-1 (or ASCII) input */
|
||||||
|
void iso_ascii_utf_16le(uint8_t gap_name[72]);
|
||||||
|
|
||||||
#endif /* SYSTEM_AREA_H_ */
|
#endif /* SYSTEM_AREA_H_ */
|
||||||
|
344
libisofs/tree.c
344
libisofs/tree.c
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* Copyright (c) 2007 Vreixo Formoso
|
||||||
|
* Copyright (c) 2011 Thomas Schmitt
|
||||||
*
|
*
|
||||||
* This file is part of the libisofs project; you can redistribute it and/or
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -31,11 +32,6 @@
|
|||||||
#include <fnmatch.h>
|
#include <fnmatch.h>
|
||||||
|
|
||||||
|
|
||||||
#ifndef PATH_MAX
|
|
||||||
#define PATH_MAX Libisofs_default_path_maX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new directory to the iso tree.
|
* Add a new directory to the iso tree.
|
||||||
*
|
*
|
||||||
@ -482,12 +478,12 @@ int iso_tree_remove_exclude(IsoImage *image, const char *path)
|
|||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < image->nexcludes; ++i) {
|
for (i = 0; (int) i < image->nexcludes; ++i) {
|
||||||
if (strcmp(image->excludes[i], path) == 0) {
|
if (strcmp(image->excludes[i], path) == 0) {
|
||||||
/* exclude found */
|
/* exclude found */
|
||||||
free(image->excludes[i]);
|
free(image->excludes[i]);
|
||||||
--image->nexcludes;
|
--image->nexcludes;
|
||||||
for (j = i; j < image->nexcludes; ++j) {
|
for (j = i; (int) j < image->nexcludes; ++j) {
|
||||||
image->excludes[j] = image->excludes[j+1];
|
image->excludes[j] = image->excludes[j+1];
|
||||||
}
|
}
|
||||||
image->excludes = realloc(image->excludes, image->nexcludes *
|
image->excludes = realloc(image->excludes, image->nexcludes *
|
||||||
@ -578,20 +574,19 @@ int iso_tree_add_new_node(IsoImage *image, IsoDir *parent, const char *name,
|
|||||||
*node = NULL;
|
*node = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs = image->fs;
|
|
||||||
result = fs->get_by_path(fs, path, &file);
|
|
||||||
if (result < 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find place where to insert */
|
/* find place where to insert */
|
||||||
result = iso_dir_exists(parent, name, &pos);
|
result = iso_dir_exists(parent, name, &pos);
|
||||||
if (result) {
|
if (result) {
|
||||||
/* a node with same name already exists */
|
/* a node with same name already exists */
|
||||||
iso_file_source_unref(file);
|
|
||||||
return ISO_NODE_NAME_NOT_UNIQUE;
|
return ISO_NODE_NAME_NOT_UNIQUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fs = image->fs;
|
||||||
|
result = fs->get_by_path(fs, path, &file);
|
||||||
|
if (result < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
result = image->builder->create_node(image->builder, image, file, &new);
|
result = image->builder->create_node(image->builder, image, file, &new);
|
||||||
|
|
||||||
/* free the file */
|
/* free the file */
|
||||||
@ -766,11 +761,16 @@ int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir)
|
|||||||
|
|
||||||
ret = iso_file_source_open(dir);
|
ret = iso_file_source_open(dir);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
char *path = iso_file_source_get_path(dir);
|
path = iso_file_source_get_path(dir);
|
||||||
/* instead of the probable error, we throw a sorry event */
|
/* instead of the probable error, we throw a sorry event */
|
||||||
ret = iso_msg_submit(image->id, ISO_FILE_CANT_ADD, ret,
|
if (path != NULL) {
|
||||||
"Can't open dir %s", path);
|
ret = iso_msg_submit(image->id, ISO_FILE_CANT_ADD, ret,
|
||||||
free(path);
|
"Can't open dir %s", path);
|
||||||
|
free(path);
|
||||||
|
} else {
|
||||||
|
ret = iso_msg_submit(image->id, ISO_NULL_POINTER, ret,
|
||||||
|
"Can't open dir. NULL pointer caught as dir name");
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -790,6 +790,11 @@ int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir)
|
|||||||
}
|
}
|
||||||
|
|
||||||
path = iso_file_source_get_path(file);
|
path = iso_file_source_get_path(file);
|
||||||
|
if (path == NULL) {
|
||||||
|
ret = iso_msg_submit(image->id, ISO_NULL_POINTER, ret,
|
||||||
|
"NULL pointer caught as file path");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
name = strrchr(path, '/') + 1;
|
name = strrchr(path, '/') + 1;
|
||||||
|
|
||||||
if (image->follow_symlinks) {
|
if (image->follow_symlinks) {
|
||||||
@ -852,7 +857,7 @@ int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir)
|
|||||||
ret = iso_dir_insert(parent, new, pos, replace);
|
ret = iso_dir_insert(parent, new, pos, replace);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
iso_node_unref(new);
|
iso_node_unref(new);
|
||||||
if (ret != ISO_NODE_NAME_NOT_UNIQUE) {
|
if (ret != (int) ISO_NODE_NAME_NOT_UNIQUE) {
|
||||||
/* error */
|
/* error */
|
||||||
goto dir_rec_continue;
|
goto dir_rec_continue;
|
||||||
} else {
|
} else {
|
||||||
@ -972,24 +977,303 @@ int iso_tree_path_to_node(IsoImage *image, const char *path, IsoNode **node)
|
|||||||
|
|
||||||
char *iso_tree_get_node_path(IsoNode *node)
|
char *iso_tree_get_node_path(IsoNode *node)
|
||||||
{
|
{
|
||||||
if (node == NULL || node->parent == NULL) {
|
char *path = NULL, *parent_path = NULL;
|
||||||
|
|
||||||
|
if (node == NULL || node->parent == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if ((IsoNode*)node->parent == node) {
|
if ((IsoNode*)node->parent == node) {
|
||||||
return strdup("/");
|
return strdup("/");
|
||||||
} else {
|
} else {
|
||||||
char path[PATH_MAX];
|
parent_path = iso_tree_get_node_path((IsoNode*)node->parent);
|
||||||
char *parent_path = iso_tree_get_node_path((IsoNode*)node->parent);
|
if (parent_path == NULL)
|
||||||
if (parent_path == NULL) {
|
goto ex;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (strlen(parent_path) == 1) {
|
if (strlen(parent_path) == 1) {
|
||||||
snprintf(path, PATH_MAX, "/%s", node->name);
|
path = calloc(1, strlen(node->name) + 2);
|
||||||
|
if (path == NULL)
|
||||||
|
goto ex;
|
||||||
|
sprintf(path, "/%s", node->name);
|
||||||
} else {
|
} else {
|
||||||
snprintf(path, PATH_MAX, "%s/%s", parent_path, node->name);
|
path = calloc(1, strlen(parent_path) + strlen(node->name) + 2);
|
||||||
|
if (path == NULL)
|
||||||
|
goto ex;
|
||||||
|
sprintf(path, "%s/%s", parent_path, node->name);
|
||||||
}
|
}
|
||||||
free(parent_path);
|
|
||||||
return strdup(path);
|
|
||||||
}
|
}
|
||||||
|
ex:;
|
||||||
|
if (parent_path != NULL)
|
||||||
|
free(parent_path);
|
||||||
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------- tree cloning ------------------------------ */
|
||||||
|
|
||||||
|
static
|
||||||
|
int iso_tree_copy_node_attr(IsoNode *old_node, IsoNode *new_node, int flag)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
new_node->mode = old_node->mode;
|
||||||
|
new_node->uid = old_node->uid;
|
||||||
|
new_node->gid = old_node->gid;
|
||||||
|
new_node->atime = old_node->atime;
|
||||||
|
new_node->mtime = old_node->mtime;
|
||||||
|
new_node->ctime = old_node->ctime;
|
||||||
|
new_node->hidden = old_node->hidden;
|
||||||
|
ret = iso_node_clone_xinfo(old_node, new_node, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
return ISO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@param flag bit0= merge directory with *new_node
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
int iso_tree_clone_dir(IsoDir *old_dir,
|
||||||
|
IsoDir *new_parent, char *new_name, IsoNode **new_node,
|
||||||
|
int flag)
|
||||||
|
{
|
||||||
|
IsoDir *new_dir = NULL;
|
||||||
|
IsoNode *sub_node = NULL, *new_sub_node = NULL;
|
||||||
|
IsoDirIter *iter = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (flag & 1) {
|
||||||
|
new_dir = (IsoDir *) *new_node;
|
||||||
|
} else {
|
||||||
|
*new_node = NULL;
|
||||||
|
ret = iso_tree_add_new_dir(new_parent, new_name, &new_dir);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
/* Avoid traversal of target directory to allow cloning of old_dir to a
|
||||||
|
subordinate of old_dir.
|
||||||
|
*/
|
||||||
|
iso_node_take((IsoNode *) new_dir);
|
||||||
|
|
||||||
|
ret = iso_dir_get_children(old_dir, &iter);
|
||||||
|
if (ret < 0)
|
||||||
|
goto ex;
|
||||||
|
while(1) {
|
||||||
|
ret = iso_dir_iter_next(iter, &sub_node);
|
||||||
|
if (ret == 0)
|
||||||
|
break;
|
||||||
|
ret = iso_tree_clone(sub_node, new_dir, sub_node->name, &new_sub_node,
|
||||||
|
flag & 1);
|
||||||
|
if (ret < 0)
|
||||||
|
goto ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now graft in the new tree resp. graft back the merged tree */
|
||||||
|
ret = iso_dir_add_node(new_parent, (IsoNode *) new_dir, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
goto ex;
|
||||||
|
|
||||||
|
if (!(flag & 1))
|
||||||
|
*new_node = (IsoNode *) new_dir;
|
||||||
|
ret = ISO_SUCCESS;
|
||||||
|
ex:;
|
||||||
|
if (iter != NULL)
|
||||||
|
iso_dir_iter_free(iter);
|
||||||
|
if (ret < 0 && new_dir != NULL) {
|
||||||
|
if (flag & 1) {
|
||||||
|
/* graft back the merged tree (eventually with half copy) */
|
||||||
|
iso_dir_add_node(new_parent, (IsoNode *) new_dir, 0);
|
||||||
|
} else {
|
||||||
|
iso_node_remove_tree((IsoNode *) new_dir, NULL);
|
||||||
|
*new_node = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int iso_tree_clone_file(IsoFile *old_file,
|
||||||
|
IsoDir *new_parent, char *new_name, IsoNode **new_node,
|
||||||
|
int flag)
|
||||||
|
{
|
||||||
|
IsoStream *new_stream = NULL;
|
||||||
|
IsoFile *new_file = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
*new_node = NULL;
|
||||||
|
|
||||||
|
ret = iso_stream_clone(old_file->stream, &new_stream, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = iso_tree_add_new_file(new_parent, new_name, new_stream, &new_file);
|
||||||
|
if (ret < 0)
|
||||||
|
goto ex;
|
||||||
|
new_stream = NULL; /* now owned by new_file */
|
||||||
|
new_file->sort_weight = old_file->sort_weight;
|
||||||
|
*new_node = (IsoNode *) new_file;
|
||||||
|
ret = ISO_SUCCESS;
|
||||||
|
ex:;
|
||||||
|
if (new_stream != NULL)
|
||||||
|
iso_stream_unref(new_stream);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int iso_tree_clone_symlink(IsoSymlink *node,
|
||||||
|
IsoDir *new_parent, char *new_name, IsoNode **new_node,
|
||||||
|
int flag)
|
||||||
|
{
|
||||||
|
IsoSymlink *new_sym;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
*new_node = NULL;
|
||||||
|
|
||||||
|
ret = iso_tree_add_new_symlink(new_parent, new_name, node->dest, &new_sym);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
new_sym->fs_id = node->fs_id;
|
||||||
|
new_sym->st_dev = node->st_dev;
|
||||||
|
new_sym->st_ino = node->st_ino;
|
||||||
|
*new_node = (IsoNode *) new_sym;
|
||||||
|
return ISO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int iso_tree_clone_special(IsoSpecial *node,
|
||||||
|
IsoDir *new_parent, char *new_name, IsoNode **new_node,
|
||||||
|
int flag)
|
||||||
|
{
|
||||||
|
IsoSpecial *new_spec;
|
||||||
|
IsoNode *iso_node;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
iso_node = (IsoNode *) node;
|
||||||
|
ret = iso_tree_add_new_special(new_parent, new_name, iso_node->mode,
|
||||||
|
node->dev, &new_spec);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
new_spec->fs_id = node->fs_id;
|
||||||
|
new_spec->st_dev = node->st_dev;
|
||||||
|
new_spec->st_ino = node->st_ino;
|
||||||
|
*new_node = (IsoNode *) new_spec;
|
||||||
|
return ISO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* API */
|
||||||
|
int iso_tree_clone(IsoNode *node,
|
||||||
|
IsoDir *new_parent, char *new_name, IsoNode **new_node,
|
||||||
|
int flag)
|
||||||
|
{
|
||||||
|
int ret = ISO_SUCCESS;
|
||||||
|
|
||||||
|
if (iso_dir_get_node(new_parent, new_name, new_node) == 1) {
|
||||||
|
if (! (node->type == LIBISO_DIR && (*new_node)->type == LIBISO_DIR &&
|
||||||
|
(flag & 1))) {
|
||||||
|
*new_node = NULL;
|
||||||
|
return ISO_NODE_NAME_NOT_UNIQUE;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
flag &= ~1;
|
||||||
|
|
||||||
|
if (node->type == LIBISO_DIR) {
|
||||||
|
ret = iso_tree_clone_dir((IsoDir *) node, new_parent, new_name,
|
||||||
|
new_node, flag & 1);
|
||||||
|
} else if (node->type == LIBISO_FILE) {
|
||||||
|
ret = iso_tree_clone_file((IsoFile *) node, new_parent, new_name,
|
||||||
|
new_node, 0);
|
||||||
|
} else if (node->type == LIBISO_SYMLINK) {
|
||||||
|
ret = iso_tree_clone_symlink((IsoSymlink *) node, new_parent, new_name,
|
||||||
|
new_node, 0);
|
||||||
|
} else if (node->type == LIBISO_SPECIAL) {
|
||||||
|
ret = iso_tree_clone_special((IsoSpecial *) node, new_parent, new_name,
|
||||||
|
new_node, 0);
|
||||||
|
} else if (node->type == LIBISO_BOOT) {
|
||||||
|
ret = ISO_SUCCESS; /* API says they are silently ignored */
|
||||||
|
}
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
if (flag & 1)
|
||||||
|
return 2; /* merged two directories, *new_node is not new */
|
||||||
|
ret = iso_tree_copy_node_attr(node, *new_node, 0);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int iso_tree_resolve_symlink(IsoImage *img, IsoSymlink *sym, IsoNode **res,
|
||||||
|
int *depth, int flag)
|
||||||
|
{
|
||||||
|
IsoDir *cur_dir = NULL;
|
||||||
|
IsoNode *n, *resolved_node;
|
||||||
|
char *dest, *dest_start, *dest_end;
|
||||||
|
int ret = 0;
|
||||||
|
unsigned int comp_len, dest_len;
|
||||||
|
|
||||||
|
dest = sym->dest;
|
||||||
|
dest_len = strlen(dest);
|
||||||
|
|
||||||
|
if (dest[0] == '/') {
|
||||||
|
|
||||||
|
/* ??? How to resolve absolute links without knowing the
|
||||||
|
path of the future mount point ?
|
||||||
|
??? Would it be better to throw error ?
|
||||||
|
I can only assume that it gets mounted at / during some stage
|
||||||
|
of booting.
|
||||||
|
*/;
|
||||||
|
|
||||||
|
cur_dir = img->root;
|
||||||
|
dest_end = dest;
|
||||||
|
} else {
|
||||||
|
cur_dir = sym->node.parent;
|
||||||
|
if (cur_dir == NULL)
|
||||||
|
cur_dir = img->root;
|
||||||
|
dest_end = dest - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (dest_end < dest + dest_len) {
|
||||||
|
dest_start = dest_end + 1;
|
||||||
|
dest_end = strchr(dest_start, '/');
|
||||||
|
if (dest_end == NULL)
|
||||||
|
dest_end = dest_start + strlen(dest_start);
|
||||||
|
comp_len = dest_end - dest_start;
|
||||||
|
if (comp_len == 0 || (comp_len == 1 && dest_start[0] == '.'))
|
||||||
|
continue;
|
||||||
|
if (comp_len == 2 && dest_start[0] == '.' && dest_start[1] == '.') {
|
||||||
|
cur_dir = cur_dir->node.parent;
|
||||||
|
if (cur_dir == NULL) /* link shoots over root */
|
||||||
|
return ISO_DEAD_SYMLINK;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Search node in cur_dir */
|
||||||
|
for (n = cur_dir->children; n != NULL; n = n->next)
|
||||||
|
if (strncmp(dest_start, n->name, comp_len) == 0 &&
|
||||||
|
strlen(n->name) == comp_len)
|
||||||
|
break;
|
||||||
|
if (n == NULL)
|
||||||
|
return ISO_DEAD_SYMLINK;
|
||||||
|
|
||||||
|
if (n->type == LIBISO_DIR) {
|
||||||
|
cur_dir = (IsoDir *) n;
|
||||||
|
} else if (n->type == LIBISO_SYMLINK) {
|
||||||
|
if (*depth >= LIBISO_MAX_LINK_DEPTH)
|
||||||
|
return ISO_DEEP_SYMLINK;
|
||||||
|
(*depth)++;
|
||||||
|
ret = iso_tree_resolve_symlink(img, (IsoSymlink *) n,
|
||||||
|
&resolved_node, depth, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
if (resolved_node->type != LIBISO_DIR) {
|
||||||
|
n = resolved_node;
|
||||||
|
goto leaf_type;
|
||||||
|
}
|
||||||
|
cur_dir = (IsoDir *) resolved_node;
|
||||||
|
} else {
|
||||||
|
leaf_type:;
|
||||||
|
if (dest_end < dest + dest_len) /* attempt to dive into file */
|
||||||
|
return ISO_DEAD_SYMLINK;
|
||||||
|
*res = n;
|
||||||
|
return ISO_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*res = (IsoNode *) cur_dir;
|
||||||
|
return ISO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
555
libisofs/util.c
555
libisofs/util.c
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* Copyright (c) 2007 Vreixo Formoso
|
||||||
* Copyright (c) 2007 Mario Danic
|
* Copyright (c) 2007 Mario Danic
|
||||||
* 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
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -16,6 +16,7 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "libisofs.h"
|
#include "libisofs.h"
|
||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
|
#include "joliet.h"
|
||||||
#include "../version.h"
|
#include "../version.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -218,7 +219,7 @@ int strconv(const char *str, const char *icharset, const char *ocharset,
|
|||||||
src = (char *)str;
|
src = (char *)str;
|
||||||
ret = (char *)out;
|
ret = (char *)out;
|
||||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||||
if (n == -1) {
|
if (n == (size_t) -1) {
|
||||||
/* error */
|
/* error */
|
||||||
iso_iconv_close(&conv, 0);
|
iso_iconv_close(&conv, 0);
|
||||||
retval = ISO_CHARSET_CONV_ERROR;
|
retval = ISO_CHARSET_CONV_ERROR;
|
||||||
@ -268,7 +269,7 @@ int strnconv(const char *str, const char *icharset, const char *ocharset,
|
|||||||
src = (char *)str;
|
src = (char *)str;
|
||||||
ret = (char *)out;
|
ret = (char *)out;
|
||||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||||
if (n == -1) {
|
if (n == (size_t) -1) {
|
||||||
/* error */
|
/* error */
|
||||||
iso_iconv_close(&conv, 0);
|
iso_iconv_close(&conv, 0);
|
||||||
retval = ISO_CHARSET_CONV_ERROR;
|
retval = ISO_CHARSET_CONV_ERROR;
|
||||||
@ -335,7 +336,7 @@ int str2wchar(const char *icharset, const char *input, wchar_t **output)
|
|||||||
src = (char *)input;
|
src = (char *)input;
|
||||||
|
|
||||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||||
while (n == -1) {
|
while (n == (size_t) -1) {
|
||||||
|
|
||||||
if (errno == E2BIG) {
|
if (errno == E2BIG) {
|
||||||
/* error, should never occur */
|
/* error, should never occur */
|
||||||
@ -381,12 +382,13 @@ conv_error:;
|
|||||||
int str2ascii(const char *icharset, const char *input, char **output)
|
int str2ascii(const char *icharset, const char *input, char **output)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
wchar_t *wsrc_;
|
wchar_t *wsrc_ = NULL;
|
||||||
char *ret;
|
char *ret = NULL;
|
||||||
char *ret_;
|
char *ret_ = NULL;
|
||||||
char *src;
|
char *src;
|
||||||
struct iso_iconv_handle conv;
|
struct iso_iconv_handle conv;
|
||||||
int conv_ret;
|
int conv_ret;
|
||||||
|
int direct_conv = 0;
|
||||||
|
|
||||||
/* That while loop smells like a potential show stopper */
|
/* That while loop smells like a potential show stopper */
|
||||||
size_t loop_counter = 0, loop_limit = 3;
|
size_t loop_counter = 0, loop_limit = 3;
|
||||||
@ -404,37 +406,58 @@ int str2ascii(const char *icharset, const char *input, char **output)
|
|||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* First try the traditional way via intermediate character set WCHAR_T.
|
||||||
|
* Up to August 2011 this was the only way. But it will not work if
|
||||||
|
* there is no character set "WCHAR_T". E.g. on Solaris.
|
||||||
|
*/
|
||||||
/* convert the string to a wide character string. Note: outbytes
|
/* convert the string to a wide character string. Note: outbytes
|
||||||
* is in fact the number of characters in the string and doesn't
|
* is in fact the number of characters in the string and doesn't
|
||||||
* include the last NULL character.
|
* include the last NULL character.
|
||||||
*/
|
*/
|
||||||
|
conv_ret = 0;
|
||||||
result = str2wchar(icharset, input, &wsrc_);
|
result = str2wchar(icharset, input, &wsrc_);
|
||||||
if (result < 0) {
|
if (result == (int) ISO_SUCCESS) {
|
||||||
goto fallback;
|
src = (char *)wsrc_;
|
||||||
}
|
numchars = wcslen(wsrc_);
|
||||||
src = (char *)wsrc_;
|
|
||||||
numchars = wcslen(wsrc_);
|
|
||||||
|
|
||||||
inbytes = numchars * sizeof(wchar_t);
|
inbytes = numchars * sizeof(wchar_t);
|
||||||
loop_limit = inbytes + 3;
|
loop_limit = inbytes + 3;
|
||||||
|
|
||||||
ret_ = malloc(numchars + 1);
|
ret_ = malloc(numchars + 1);
|
||||||
if (ret_ == NULL) {
|
if (ret_ == NULL) {
|
||||||
return ISO_OUT_OF_MEM;
|
return ISO_OUT_OF_MEM;
|
||||||
}
|
}
|
||||||
outbytes = numchars;
|
outbytes = numchars;
|
||||||
ret = ret_;
|
ret = ret_;
|
||||||
|
|
||||||
/* initialize iconv */
|
/* initialize iconv */
|
||||||
conv_ret = iso_iconv_open(&conv, "ASCII", "WCHAR_T", 0);
|
conv_ret = iso_iconv_open(&conv, "ASCII", "WCHAR_T", 0);
|
||||||
|
if (conv_ret <= 0) {
|
||||||
|
free(wsrc_);
|
||||||
|
free(ret_);
|
||||||
|
}
|
||||||
|
} else if (result != (int) ISO_CHARSET_CONV_ERROR)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/* If this did not succeed : Try the untraditional direct conversion.
|
||||||
|
*/
|
||||||
if (conv_ret <= 0) {
|
if (conv_ret <= 0) {
|
||||||
free(wsrc_);
|
conv_ret = iso_iconv_open(&conv, "ASCII", (char *) icharset, 0);
|
||||||
free(ret_);
|
if (conv_ret <= 0)
|
||||||
goto fallback;
|
goto fallback;
|
||||||
|
direct_conv = 1;
|
||||||
|
src = (char *) input;
|
||||||
|
inbytes = strlen(input);
|
||||||
|
loop_limit = inbytes + 3;
|
||||||
|
outbytes = (inbytes + 1) * sizeof(uint16_t);
|
||||||
|
ret_ = malloc(outbytes);
|
||||||
|
if (ret_ == NULL)
|
||||||
|
return ISO_OUT_OF_MEM;
|
||||||
|
ret = ret_;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||||
while (n == -1) {
|
while (n == (size_t) -1) {
|
||||||
/* The destination buffer is too small. Stops here. */
|
/* The destination buffer is too small. Stops here. */
|
||||||
if (errno == E2BIG)
|
if (errno == E2BIG)
|
||||||
break;
|
break;
|
||||||
@ -457,8 +480,13 @@ int str2ascii(const char *icharset, const char *input, char **output)
|
|||||||
/* There was an error with one character but some other remain
|
/* There was an error with one character but some other remain
|
||||||
* to be converted. That's probably a multibyte character.
|
* to be converted. That's probably a multibyte character.
|
||||||
* See above comment. */
|
* See above comment. */
|
||||||
src += sizeof(wchar_t);
|
if (direct_conv) {
|
||||||
inbytes -= sizeof(wchar_t);
|
src++;
|
||||||
|
inbytes--;
|
||||||
|
} else {
|
||||||
|
src += sizeof(wchar_t);
|
||||||
|
inbytes -= sizeof(wchar_t);
|
||||||
|
}
|
||||||
|
|
||||||
if (!inbytes)
|
if (!inbytes)
|
||||||
break;
|
break;
|
||||||
@ -470,8 +498,9 @@ int str2ascii(const char *icharset, const char *input, char **output)
|
|||||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||||
}
|
}
|
||||||
iso_iconv_close(&conv, 0);
|
iso_iconv_close(&conv, 0);
|
||||||
*ret='\0';
|
*ret = 0;
|
||||||
free(wsrc_);
|
if (wsrc_ != NULL)
|
||||||
|
free(wsrc_);
|
||||||
|
|
||||||
*output = ret_;
|
*output = ret_;
|
||||||
return ISO_SUCCESS;
|
return ISO_SUCCESS;
|
||||||
@ -516,12 +545,13 @@ int cmp_ucsbe(const uint16_t *ucs, char c)
|
|||||||
int str2ucs(const char *icharset, const char *input, uint16_t **output)
|
int str2ucs(const char *icharset, const char *input, uint16_t **output)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
wchar_t *wsrc_;
|
wchar_t *wsrc_ = NULL;
|
||||||
char *src;
|
char *src;
|
||||||
char *ret;
|
char *ret = NULL;
|
||||||
char *ret_;
|
char *ret_ = NULL;
|
||||||
struct iso_iconv_handle conv;
|
struct iso_iconv_handle conv;
|
||||||
int conv_ret;
|
int conv_ret = 0;
|
||||||
|
int direct_conv = 0;
|
||||||
|
|
||||||
/* That while loop smells like a potential show stopper */
|
/* That while loop smells like a potential show stopper */
|
||||||
size_t loop_counter = 0, loop_limit = 3;
|
size_t loop_counter = 0, loop_limit = 3;
|
||||||
@ -539,33 +569,54 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
|
|||||||
* is in fact the number of characters in the string and doesn't
|
* is in fact the number of characters in the string and doesn't
|
||||||
* include the last NULL character.
|
* include the last NULL character.
|
||||||
*/
|
*/
|
||||||
|
/* First try the traditional way via intermediate character set WCHAR_T.
|
||||||
|
* Up to August 2011 this was the only way. But it will not work if
|
||||||
|
* there is no character set "WCHAR_T". E.g. on Solaris.
|
||||||
|
*/
|
||||||
|
conv_ret = 0;
|
||||||
result = str2wchar(icharset, input, &wsrc_);
|
result = str2wchar(icharset, input, &wsrc_);
|
||||||
if (result < 0) {
|
if (result == (int) ISO_SUCCESS) {
|
||||||
|
src = (char *)wsrc_;
|
||||||
|
numchars = wcslen(wsrc_);
|
||||||
|
|
||||||
|
inbytes = numchars * sizeof(wchar_t);
|
||||||
|
loop_limit = inbytes + 3;
|
||||||
|
|
||||||
|
ret_ = malloc((numchars+1) * sizeof(uint16_t));
|
||||||
|
if (ret_ == NULL)
|
||||||
|
return ISO_OUT_OF_MEM;
|
||||||
|
outbytes = numchars * sizeof(uint16_t);
|
||||||
|
ret = ret_;
|
||||||
|
|
||||||
|
/* initialize iconv */
|
||||||
|
conv_ret = iso_iconv_open(&conv, "UCS-2BE", "WCHAR_T", 0);
|
||||||
|
if (conv_ret <= 0) {
|
||||||
|
free(wsrc_);
|
||||||
|
free(ret_);
|
||||||
|
}
|
||||||
|
} else if (result != (int) ISO_CHARSET_CONV_ERROR)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
src = (char *)wsrc_;
|
|
||||||
numchars = wcslen(wsrc_);
|
|
||||||
|
|
||||||
inbytes = numchars * sizeof(wchar_t);
|
/* If this did not succeed : Try the untraditional direct conversion.
|
||||||
loop_limit = inbytes + 3;
|
*/
|
||||||
|
|
||||||
ret_ = malloc((numchars+1) * sizeof(uint16_t));
|
|
||||||
if (ret_ == NULL) {
|
|
||||||
return ISO_OUT_OF_MEM;
|
|
||||||
}
|
|
||||||
outbytes = numchars * sizeof(uint16_t);
|
|
||||||
ret = ret_;
|
|
||||||
|
|
||||||
/* initialize iconv */
|
|
||||||
conv_ret = iso_iconv_open(&conv, "UCS-2BE", "WCHAR_T", 0);
|
|
||||||
if (conv_ret <= 0) {
|
if (conv_ret <= 0) {
|
||||||
free(wsrc_);
|
conv_ret = iso_iconv_open(&conv, "UCS-2BE", (char *) icharset, 0);
|
||||||
free(ret_);
|
if (conv_ret <= 0) {
|
||||||
return ISO_CHARSET_CONV_ERROR;
|
return ISO_CHARSET_CONV_ERROR;
|
||||||
|
}
|
||||||
|
direct_conv = 1;
|
||||||
|
src = (char *) input;
|
||||||
|
inbytes = strlen(input);
|
||||||
|
loop_limit = inbytes + 3;
|
||||||
|
outbytes = (inbytes + 1) * sizeof(uint16_t);
|
||||||
|
ret_ = malloc(outbytes);
|
||||||
|
if (ret_ == NULL)
|
||||||
|
return ISO_OUT_OF_MEM;
|
||||||
|
ret = ret_;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||||
while (n == -1) {
|
while (n == (size_t) -1) {
|
||||||
/* The destination buffer is too small. Stops here. */
|
/* The destination buffer is too small. Stops here. */
|
||||||
if (errno == E2BIG)
|
if (errno == E2BIG)
|
||||||
break;
|
break;
|
||||||
@ -588,8 +639,13 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
|
|||||||
/* There was an error with one character but some other remain
|
/* There was an error with one character but some other remain
|
||||||
* to be converted. That's probably a multibyte character.
|
* to be converted. That's probably a multibyte character.
|
||||||
* See above comment. */
|
* See above comment. */
|
||||||
src += sizeof(wchar_t);
|
if (direct_conv) {
|
||||||
inbytes -= sizeof(wchar_t);
|
src++;
|
||||||
|
inbytes--;
|
||||||
|
} else {
|
||||||
|
src += sizeof(wchar_t);
|
||||||
|
inbytes -= sizeof(wchar_t);
|
||||||
|
}
|
||||||
|
|
||||||
if (!inbytes)
|
if (!inbytes)
|
||||||
break;
|
break;
|
||||||
@ -604,7 +660,8 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
|
|||||||
|
|
||||||
/* close the ucs string */
|
/* close the ucs string */
|
||||||
set_ucsbe((uint16_t*) ret, '\0');
|
set_ucsbe((uint16_t*) ret, '\0');
|
||||||
free(wsrc_);
|
if (wsrc_ != NULL)
|
||||||
|
free(wsrc_);
|
||||||
|
|
||||||
*output = (uint16_t*)ret_;
|
*output = (uint16_t*)ret_;
|
||||||
return ISO_SUCCESS;
|
return ISO_SUCCESS;
|
||||||
@ -628,36 +685,75 @@ static int valid_j_char(uint16_t c)
|
|||||||
&& cmp_ucsbe(&c, '\\');
|
&& cmp_ucsbe(&c, '\\');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* @param relaxed bit0+1 0= strict ECMA-119
|
||||||
|
1= additionally allow lowercase (else map to upper)
|
||||||
|
2= allow all 8-bit characters
|
||||||
|
bit2 allow all 7-bit characters (but map to upper if
|
||||||
|
not bit0+1 == 2)
|
||||||
|
*/
|
||||||
|
static char map_fileid_char(char c, int relaxed)
|
||||||
|
{
|
||||||
|
char upper;
|
||||||
|
|
||||||
|
if (c == '/') /* Allowing slashes would cause lots of confusion */
|
||||||
|
return '_';
|
||||||
|
if ((relaxed & 3) == 2)
|
||||||
|
return c;
|
||||||
|
if (valid_d_char(c))
|
||||||
|
return c;
|
||||||
|
if ((relaxed & 4) && (c & 0x7f) == c && (c < 'a' || c > 'z'))
|
||||||
|
return c;
|
||||||
|
upper= toupper(c);
|
||||||
|
if (valid_d_char(upper)) {
|
||||||
|
if (relaxed & 3) {
|
||||||
|
/* lower chars are allowed */
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
return upper;
|
||||||
|
}
|
||||||
|
return '_';
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
char *iso_dirid(const char *src, int size)
|
char *iso_dirid(const char *src, int size, int relaxed)
|
||||||
{
|
{
|
||||||
size_t len, i;
|
size_t len, i;
|
||||||
char name[32];
|
char name[32];
|
||||||
|
|
||||||
len = strlen(src);
|
len = strlen(src);
|
||||||
if (len > size) {
|
if ((int) len > size) {
|
||||||
len = size;
|
len = size;
|
||||||
}
|
}
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
|
|
||||||
|
#ifdef Libisofs_old_ecma119_nameS
|
||||||
|
|
||||||
char c= toupper(src[i]);
|
char c= toupper(src[i]);
|
||||||
name[i] = valid_d_char(c) ? c : '_';
|
name[i] = valid_d_char(c) ? c : '_';
|
||||||
|
|
||||||
|
#else /* Libisofs_old_ecma119_nameS */
|
||||||
|
|
||||||
|
name[i] = map_fileid_char(src[i], relaxed);
|
||||||
|
|
||||||
|
#endif /* ! Libisofs_old_ecma119_nameS */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
name[len] = '\0';
|
name[len] = '\0';
|
||||||
return strdup(name);
|
return strdup(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *iso_1_dirid(const char *src)
|
char *iso_1_dirid(const char *src, int relaxed)
|
||||||
{
|
{
|
||||||
return iso_dirid(src, 8);
|
return iso_dirid(src, 8, relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *iso_2_dirid(const char *src)
|
char *iso_2_dirid(const char *src)
|
||||||
{
|
{
|
||||||
return iso_dirid(src, 31);
|
return iso_dirid(src, 31, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *iso_1_fileid(const char *src)
|
char *iso_1_fileid(const char *src, int relaxed, int force_dots)
|
||||||
{
|
{
|
||||||
char *dot; /* Position of the last dot in the filename, will be used
|
char *dot; /* Position of the last dot in the filename, will be used
|
||||||
* to calculate lname and lext. */
|
* to calculate lname and lext. */
|
||||||
@ -668,7 +764,8 @@ char *iso_1_fileid(const char *src)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
dot = strrchr(src, '.');
|
dot = strrchr(src, '.');
|
||||||
|
if (dot == src && strlen(src) > 4)
|
||||||
|
dot = NULL; /* Use the long extension instead of the empty name */
|
||||||
lext = dot ? strlen(dot + 1) : 0;
|
lext = dot ? strlen(dot + 1) : 0;
|
||||||
lname = strlen(src) - lext - (dot ? 1 : 0);
|
lname = strlen(src) - lext - (dot ? 1 : 0);
|
||||||
|
|
||||||
@ -681,19 +778,43 @@ char *iso_1_fileid(const char *src)
|
|||||||
|
|
||||||
/* Convert up to 8 characters of the filename. */
|
/* Convert up to 8 characters of the filename. */
|
||||||
for (i = 0; i < lname && i < 8; i++) {
|
for (i = 0; i < lname && i < 8; i++) {
|
||||||
|
|
||||||
|
#ifdef Libisofs_old_ecma119_nameS
|
||||||
|
|
||||||
char c= toupper(src[i]);
|
char c= toupper(src[i]);
|
||||||
|
|
||||||
dest[pos++] = valid_d_char(c) ? c : '_';
|
dest[pos++] = valid_d_char(c) ? c : '_';
|
||||||
|
|
||||||
|
#else /* Libisofs_old_ecma119_nameS */
|
||||||
|
|
||||||
|
if (dot == NULL && src[i] == '.')
|
||||||
|
dest[pos++] = '_'; /* make sure that ignored dots do not appear */
|
||||||
|
else
|
||||||
|
dest[pos++] = map_fileid_char(src[i], relaxed);
|
||||||
|
|
||||||
|
#endif /* ! Libisofs_old_ecma119_nameS */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This dot is mandatory, even if there is no extension. */
|
/* This dot is mandatory, even if there is no extension. */
|
||||||
dest[pos++] = '.';
|
if (force_dots || lext > 0)
|
||||||
|
dest[pos++] = '.';
|
||||||
|
|
||||||
/* Convert up to 3 characters of the extension, if any. */
|
/* Convert up to 3 characters of the extension, if any. */
|
||||||
for (i = 0; i < lext && i < 3; i++) {
|
for (i = 0; i < lext && i < 3; i++) {
|
||||||
|
|
||||||
|
#ifdef Libisofs_old_ecma119_nameS
|
||||||
|
|
||||||
char c= toupper(src[lname + 1 + i]);
|
char c= toupper(src[lname + 1 + i]);
|
||||||
|
|
||||||
dest[pos++] = valid_d_char(c) ? c : '_';
|
dest[pos++] = valid_d_char(c) ? c : '_';
|
||||||
|
|
||||||
|
#else /* Libisofs_old_ecma119_nameS */
|
||||||
|
|
||||||
|
dest[pos++] = map_fileid_char(src[lname + 1 + i], relaxed);
|
||||||
|
|
||||||
|
#endif /* ! Libisofs_old_ecma119_nameS */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dest[pos] = '\0';
|
dest[pos] = '\0';
|
||||||
@ -760,8 +881,11 @@ char *iso_2_fileid(const char *src)
|
|||||||
* @param size
|
* @param size
|
||||||
* Max len for the name
|
* Max len for the name
|
||||||
* @param relaxed
|
* @param relaxed
|
||||||
* 0 only allow d-characters, 1 allow also lowe case chars,
|
* bit0+1: 0 only allow d-characters,
|
||||||
* 2 allow all characters
|
* 1 allow also lowe case chars,
|
||||||
|
* 2 allow all 8-bit characters,
|
||||||
|
* bit2: allow 7-bit characters (but map lowercase to uppercase if
|
||||||
|
* not bit0+1 == 2)
|
||||||
*/
|
*/
|
||||||
char *iso_r_dirid(const char *src, int size, int relaxed)
|
char *iso_r_dirid(const char *src, int size, int relaxed)
|
||||||
{
|
{
|
||||||
@ -769,13 +893,16 @@ char *iso_r_dirid(const char *src, int size, int relaxed)
|
|||||||
char *dest;
|
char *dest;
|
||||||
|
|
||||||
len = strlen(src);
|
len = strlen(src);
|
||||||
if (len > size) {
|
if ((int) len > size) {
|
||||||
len = size;
|
len = size;
|
||||||
}
|
}
|
||||||
dest = malloc(len + 1);
|
dest = malloc(len + 1);
|
||||||
if (dest == NULL)
|
if (dest == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
|
|
||||||
|
#ifdef Libisofs_old_ecma119_nameS
|
||||||
|
|
||||||
char c= src[i];
|
char c= src[i];
|
||||||
if (relaxed == 2) {
|
if (relaxed == 2) {
|
||||||
/* all chars are allowed */
|
/* all chars are allowed */
|
||||||
@ -796,6 +923,13 @@ char *iso_r_dirid(const char *src, int size, int relaxed)
|
|||||||
dest[i] = '_';
|
dest[i] = '_';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else /* Libisofs_old_ecma119_nameS */
|
||||||
|
|
||||||
|
dest[i] = map_fileid_char(src[i], relaxed);
|
||||||
|
|
||||||
|
#endif /* ! Libisofs_old_ecma119_nameS */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dest[len] = '\0';
|
dest[len] = '\0';
|
||||||
@ -803,13 +937,17 @@ char *iso_r_dirid(const char *src, int size, int relaxed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a file name suitable for an ISO image with relaxed constraints.
|
* Create a file name suitable for an ISO image with level > 1 and
|
||||||
|
* with relaxed constraints.
|
||||||
*
|
*
|
||||||
* @param len
|
* @param len
|
||||||
* Max len for the name, without taken the "." into account.
|
* Max len for the name, without taken the "." into account.
|
||||||
* @param relaxed
|
* @param relaxed
|
||||||
* 0 only allow d-characters, 1 allow also lowe case chars,
|
* bit0+1: 0 only allow d-characters,
|
||||||
* 2 allow all characters
|
* 1 allow also lowe case chars,
|
||||||
|
* 2 allow all 8-bit characters,
|
||||||
|
* bit2: allow 7-bit characters (but map lowercase to uppercase if
|
||||||
|
* not bit0+1 == 2)
|
||||||
* @param forcedot
|
* @param forcedot
|
||||||
* Whether to ensure that "." is added
|
* Whether to ensure that "." is added
|
||||||
*/
|
*/
|
||||||
@ -837,15 +975,15 @@ char *iso_r_fileid(const char *src, size_t len, int relaxed, int forcedot)
|
|||||||
*/
|
*/
|
||||||
if (dot == NULL || *(dot + 1) == '\0') {
|
if (dot == NULL || *(dot + 1) == '\0') {
|
||||||
lname = strlen(src);
|
lname = strlen(src);
|
||||||
lnname = (lname > len) ? len : lname;
|
lnname = (lname > (int) len) ? (int) len : lname;
|
||||||
lext = lnext = 0;
|
lext = lnext = 0;
|
||||||
} else {
|
} else {
|
||||||
lext = strlen(dot + 1);
|
lext = strlen(dot + 1);
|
||||||
lname = strlen(src) - lext - 1;
|
lname = strlen(src) - lext - 1;
|
||||||
lnext = (strlen(src) > len + 1 && lext > 3) ?
|
lnext = (strlen(src) > len + 1 && lext > 3) ?
|
||||||
(lname < len - 3 ? len - lname : 3)
|
(lname < (int) len - 3 ? (int) len - lname : 3)
|
||||||
: lext;
|
: lext;
|
||||||
lnname = (strlen(src) > len + 1) ? len - lnext : lname;
|
lnname = (strlen(src) > len + 1) ? (int) len - lnext : lname;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lnname == 0 && lnext == 0) {
|
if (lnname == 0 && lnext == 0) {
|
||||||
@ -856,6 +994,9 @@ char *iso_r_fileid(const char *src, size_t len, int relaxed, int forcedot)
|
|||||||
|
|
||||||
/* Convert up to lnname characters of the filename. */
|
/* Convert up to lnname characters of the filename. */
|
||||||
for (i = 0; i < lnname; i++) {
|
for (i = 0; i < lnname; i++) {
|
||||||
|
|
||||||
|
#ifdef Libisofs_old_ecma119_nameS
|
||||||
|
|
||||||
char c= src[i];
|
char c= src[i];
|
||||||
if (relaxed == 2) {
|
if (relaxed == 2) {
|
||||||
/* all chars are allowed */
|
/* all chars are allowed */
|
||||||
@ -876,6 +1017,13 @@ char *iso_r_fileid(const char *src, size_t len, int relaxed, int forcedot)
|
|||||||
dest[pos++] = '_';
|
dest[pos++] = '_';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else /* Libisofs_old_ecma119_nameS */
|
||||||
|
|
||||||
|
dest[pos++] = map_fileid_char(src[i], relaxed);
|
||||||
|
|
||||||
|
#endif /* ! Libisofs_old_ecma119_nameS */
|
||||||
|
|
||||||
}
|
}
|
||||||
if (lnext > 0 || forcedot) {
|
if (lnext > 0 || forcedot) {
|
||||||
dest[pos++] = '.';
|
dest[pos++] = '.';
|
||||||
@ -883,6 +1031,9 @@ char *iso_r_fileid(const char *src, size_t len, int relaxed, int forcedot)
|
|||||||
|
|
||||||
/* Convert up to lnext characters of the extension, if any. */
|
/* Convert up to lnext characters of the extension, if any. */
|
||||||
for (i = lname + 1; i < lname + 1 + lnext; i++) {
|
for (i = lname + 1; i < lname + 1 + lnext; i++) {
|
||||||
|
|
||||||
|
#ifdef Libisofs_old_ecma119_nameS
|
||||||
|
|
||||||
char c= src[i];
|
char c= src[i];
|
||||||
if (relaxed == 2) {
|
if (relaxed == 2) {
|
||||||
/* all chars are allowed */
|
/* all chars are allowed */
|
||||||
@ -903,6 +1054,13 @@ char *iso_r_fileid(const char *src, size_t len, int relaxed, int forcedot)
|
|||||||
dest[pos++] = '_';
|
dest[pos++] = '_';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else /* Libisofs_old_ecma119_nameS */
|
||||||
|
|
||||||
|
dest[pos++] = map_fileid_char(src[i], relaxed);
|
||||||
|
|
||||||
|
#endif /* ! Libisofs_old_ecma119_nameS */
|
||||||
|
|
||||||
}
|
}
|
||||||
dest[pos] = '\0';
|
dest[pos] = '\0';
|
||||||
|
|
||||||
@ -916,16 +1074,22 @@ ex:;
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
bit0= no_force_dots
|
bit0= no_force_dots
|
||||||
|
bit1= allow 103 characters rather than 64
|
||||||
*/
|
*/
|
||||||
uint16_t *iso_j_file_id(const uint16_t *src, int flag)
|
uint16_t *iso_j_file_id(const uint16_t *src, int flag)
|
||||||
{
|
{
|
||||||
uint16_t *dot;
|
uint16_t *dot, *retval = NULL;
|
||||||
size_t lname, lext, lnname, lnext, pos, i;
|
size_t lname, lext, lnname, lnext, pos, i, maxchar = 64;
|
||||||
uint16_t dest[66]; /* 66 = 64 (name + ext) + 1 (.) + 1 (\0) */
|
uint16_t *dest = NULL;
|
||||||
|
|
||||||
|
LIBISO_ALLOC_MEM_VOID(dest, uint16_t, LIBISO_JOLIET_NAME_MAX);
|
||||||
|
/* was: 66 = 64 (name + ext) + 1 (.) + 1 (\0) */
|
||||||
|
|
||||||
if (src == NULL) {
|
if (src == NULL) {
|
||||||
return NULL;
|
goto ex;
|
||||||
}
|
}
|
||||||
|
if (flag & 2)
|
||||||
|
maxchar = 103;
|
||||||
|
|
||||||
dot = ucsrchr(src, '.');
|
dot = ucsrchr(src, '.');
|
||||||
|
|
||||||
@ -937,18 +1101,19 @@ uint16_t *iso_j_file_id(const uint16_t *src, int flag)
|
|||||||
*/
|
*/
|
||||||
if (dot == NULL || cmp_ucsbe(dot + 1, '\0') == 0) {
|
if (dot == NULL || cmp_ucsbe(dot + 1, '\0') == 0) {
|
||||||
lname = ucslen(src);
|
lname = ucslen(src);
|
||||||
lnname = (lname > 64) ? 64 : lname;
|
lnname = (lname > maxchar) ? maxchar : lname;
|
||||||
lext = lnext = 0;
|
lext = lnext = 0;
|
||||||
} else {
|
} else {
|
||||||
lext = ucslen(dot + 1);
|
lext = ucslen(dot + 1);
|
||||||
lname = ucslen(src) - lext - 1;
|
lname = ucslen(src) - lext - 1;
|
||||||
lnext = (ucslen(src) > 65 && lext > 3) ? (lname < 61 ? 64 - lname : 3)
|
lnext = (ucslen(src) > maxchar + 1 && lext > 3)
|
||||||
|
? (lname < maxchar - 3 ? maxchar - lname : 3)
|
||||||
: lext;
|
: lext;
|
||||||
lnname = (ucslen(src) > 65) ? 64 - lnext : lname;
|
lnname = (ucslen(src) > maxchar + 1) ? maxchar - lnext : lname;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lnname == 0 && lnext == 0) {
|
if (lnname == 0 && lnext == 0) {
|
||||||
return NULL;
|
goto ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = 0;
|
pos = 0;
|
||||||
@ -983,21 +1148,30 @@ uint16_t *iso_j_file_id(const uint16_t *src, int flag)
|
|||||||
|
|
||||||
is_done:;
|
is_done:;
|
||||||
set_ucsbe(dest + pos, '\0');
|
set_ucsbe(dest + pos, '\0');
|
||||||
return ucsdup(dest);
|
retval = ucsdup(dest);
|
||||||
|
ex:;
|
||||||
|
LIBISO_FREE_MEM(dest);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t *iso_j_dir_id(const uint16_t *src)
|
/* @param flag bit1= allow 103 characters rather than 64
|
||||||
|
*/
|
||||||
|
uint16_t *iso_j_dir_id(const uint16_t *src, int flag)
|
||||||
{
|
{
|
||||||
size_t len, i;
|
size_t len, i, maxchar = 64;
|
||||||
uint16_t dest[65]; /* 65 = 64 + 1 (\0) */
|
uint16_t *dest = NULL, *retval = NULL;
|
||||||
|
/* was: 65 = 64 + 1 (\0) */
|
||||||
|
LIBISO_ALLOC_MEM_VOID(dest, uint16_t, LIBISO_JOLIET_NAME_MAX);
|
||||||
|
|
||||||
if (src == NULL) {
|
if (src == NULL) {
|
||||||
return NULL;
|
goto ex;
|
||||||
}
|
}
|
||||||
|
if (flag & 2)
|
||||||
|
maxchar = 103;
|
||||||
|
|
||||||
len = ucslen(src);
|
len = ucslen(src);
|
||||||
if (len > 64) {
|
if (len > maxchar) {
|
||||||
len = 64;
|
len = maxchar;
|
||||||
}
|
}
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
uint16_t c = src[i];
|
uint16_t c = src[i];
|
||||||
@ -1008,7 +1182,10 @@ uint16_t *iso_j_dir_id(const uint16_t *src)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
set_ucsbe(dest + len, '\0');
|
set_ucsbe(dest + len, '\0');
|
||||||
return ucsdup(dest);
|
retval = ucsdup(dest);
|
||||||
|
ex:
|
||||||
|
LIBISO_FREE_MEM(dest);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ucslen(const uint16_t *str)
|
size_t ucslen(const uint16_t *str)
|
||||||
@ -1048,12 +1225,13 @@ uint16_t *ucsdup(const uint16_t *str)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Although each character is 2 bytes, we actually compare byte-by-byte
|
* Although each character is 2 bytes, we actually compare byte-by-byte
|
||||||
* (thats what the spec says).
|
* because the words are big-endian. Comparing possibly swapped words
|
||||||
|
* would make the sorting order depend on the machine byte order.
|
||||||
*/
|
*/
|
||||||
int ucscmp(const uint16_t *s1, const uint16_t *s2)
|
int ucscmp(const uint16_t *s1, const uint16_t *s2)
|
||||||
{
|
{
|
||||||
const char *s = (const char*)s1;
|
const uint8_t *s = (const uint8_t*)s1;
|
||||||
const char *t = (const char*)s2;
|
const uint8_t *t = (const uint8_t*)s2;
|
||||||
size_t len1 = ucslen(s1);
|
size_t len1 = ucslen(s1);
|
||||||
size_t len2 = ucslen(s2);
|
size_t len2 = ucslen(s2);
|
||||||
size_t i, len = MIN(len1, len2) * 2;
|
size_t i, len = MIN(len1, len2) * 2;
|
||||||
@ -1177,6 +1355,18 @@ void iso_bb(uint8_t *buf, uint32_t num, int bytes)
|
|||||||
iso_msb(buf+bytes, num, bytes);
|
iso_msb(buf+bytes, num, 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)
|
||||||
|
{
|
||||||
|
int b, bits;
|
||||||
|
|
||||||
|
bits = bytes * 8;
|
||||||
|
for (b = 0; b < bits; b += 8)
|
||||||
|
*((unsigned char *) ((*wpt)++)) = (value >> b) & 0xff;
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t iso_read_lsb(const uint8_t *buf, int bytes)
|
uint32_t iso_read_lsb(const uint8_t *buf, int bytes)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -1298,12 +1488,41 @@ void iso_datetime_17(unsigned char *buf, time_t t, int always_gmt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HAVE_TIMEGM
|
#ifndef HAVE_TIMEGM
|
||||||
|
|
||||||
|
/* putenv is SVr4, POSIX.1-2001, 4.3BSD , setenv is 4.3BSD, POSIX.1-2001.
|
||||||
|
So putenv is more widely available.
|
||||||
|
Also, setenv spoils eventual putenv expectation of applications because
|
||||||
|
putenv installs the original string which then may be altered from
|
||||||
|
its owner. setenv installs a copy that may not be altered.
|
||||||
|
Both are slow.
|
||||||
|
Thus first try with a naive implementation that assumes no leap seconds.
|
||||||
|
If it fails a test with gmtime() then use the slow function with mktime().
|
||||||
|
*/
|
||||||
|
#define Libisofs_use_putenV yes
|
||||||
|
|
||||||
static
|
static
|
||||||
time_t timegm(struct tm *tm)
|
time_t env_timegm(struct tm *tm)
|
||||||
{
|
{
|
||||||
time_t ret;
|
time_t ret;
|
||||||
char *tz;
|
char *tz;
|
||||||
|
|
||||||
|
#ifdef Libisofs_use_putenV
|
||||||
|
|
||||||
|
static char unset_name[] = {"TZ"};
|
||||||
|
|
||||||
|
tz = getenv("TZ");
|
||||||
|
putenv("TZ=");
|
||||||
|
tzset();
|
||||||
|
ret = mktime(tm);
|
||||||
|
if (tz != NULL) {
|
||||||
|
/* tz is a pointer to the value part in a string of form "TZ="value */
|
||||||
|
putenv(tz - 3);
|
||||||
|
} else
|
||||||
|
putenv(unset_name); /* not daring to submit constant */
|
||||||
|
tzset();
|
||||||
|
|
||||||
|
#else /* Libisofs_use_putenV */
|
||||||
|
|
||||||
tz = getenv("TZ");
|
tz = getenv("TZ");
|
||||||
setenv("TZ", "", 1);
|
setenv("TZ", "", 1);
|
||||||
tzset();
|
tzset();
|
||||||
@ -1313,9 +1532,92 @@ time_t timegm(struct tm *tm)
|
|||||||
else
|
else
|
||||||
unsetenv("TZ");
|
unsetenv("TZ");
|
||||||
tzset();
|
tzset();
|
||||||
|
|
||||||
|
#endif /* ! Libisofs_use_putenV */
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
static
|
||||||
|
int ts_is_leapyear(int tm_year) /* years since 1900 */
|
||||||
|
{
|
||||||
|
return ((tm_year % 4) == 0 && ((tm_year % 100) != 0 ||
|
||||||
|
(tm_year % 400) == 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fast implementation without leap seconds.
|
||||||
|
Inspired by but not copied from code by Kungliga Tekniska Hgskolan
|
||||||
|
(Royal Institute of Technology, Stockholm, Sweden),
|
||||||
|
which was modified by Andrew Tridgell for Samba4.
|
||||||
|
I claim own copyright 2011 Thomas Schmitt <scdbackup@gmx.net>.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
time_t ts_timegm(struct tm *tm)
|
||||||
|
{
|
||||||
|
time_t ret;
|
||||||
|
static int month_length_normal[12] =
|
||||||
|
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||||
|
static int month_length_leap[12] =
|
||||||
|
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||||
|
int *month_length_pt;
|
||||||
|
int years, i;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
years = tm->tm_year - 70; /* Years since 1970 */
|
||||||
|
if (years < 0)
|
||||||
|
return ret;
|
||||||
|
for (i = 0; i < years; i++) {
|
||||||
|
ret += 365 * 86400;
|
||||||
|
if (ts_is_leapyear(70 + i))
|
||||||
|
ret += 86400;
|
||||||
|
}
|
||||||
|
if (ts_is_leapyear(tm->tm_year))
|
||||||
|
month_length_pt = month_length_leap;
|
||||||
|
else
|
||||||
|
month_length_pt = month_length_normal;
|
||||||
|
for (i = 0; i < tm->tm_mon; i++)
|
||||||
|
ret += month_length_pt[i] * 86400;
|
||||||
|
ret += (tm->tm_mday - 1) * 86400;
|
||||||
|
ret += tm->tm_hour * 3600;
|
||||||
|
ret += tm->tm_min * 60;
|
||||||
|
ret += tm->tm_sec;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
time_t timegm(struct tm *tm)
|
||||||
|
{
|
||||||
|
time_t raw_t, ret;
|
||||||
|
struct tm *test_tm, input_tm_copy;
|
||||||
|
|
||||||
|
/* Beware of ill effects if tm is result of gmtime() or alike */
|
||||||
|
memcpy(&input_tm_copy, tm, sizeof(struct tm));
|
||||||
|
|
||||||
|
/* Try without leapseconds (which are rarely implemented, as it seems) */
|
||||||
|
raw_t = ts_timegm(tm);
|
||||||
|
if (raw_t == 0)
|
||||||
|
return raw_t;
|
||||||
|
|
||||||
|
/* Check whether this translates back to the input values */
|
||||||
|
test_tm = gmtime(&raw_t);
|
||||||
|
if (input_tm_copy.tm_sec == test_tm->tm_sec &&
|
||||||
|
input_tm_copy.tm_min == test_tm->tm_min &&
|
||||||
|
input_tm_copy.tm_hour == test_tm->tm_hour &&
|
||||||
|
input_tm_copy.tm_mday == test_tm->tm_mday &&
|
||||||
|
input_tm_copy.tm_mon == test_tm->tm_mon &&
|
||||||
|
input_tm_copy.tm_year == test_tm->tm_year) {
|
||||||
|
ret = raw_t;
|
||||||
|
} else {
|
||||||
|
/* Mismatch. Use slow method around mktime() */
|
||||||
|
ret = env_timegm(&input_tm_copy);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ! HAVE_TIMEGM */
|
||||||
|
|
||||||
|
|
||||||
time_t iso_datetime_read_7(const uint8_t *buf)
|
time_t iso_datetime_read_7(const uint8_t *buf)
|
||||||
{
|
{
|
||||||
@ -1327,6 +1629,7 @@ time_t iso_datetime_read_7(const uint8_t *buf)
|
|||||||
tm.tm_hour = buf[3];
|
tm.tm_hour = buf[3];
|
||||||
tm.tm_min = buf[4];
|
tm.tm_min = buf[4];
|
||||||
tm.tm_sec = buf[5];
|
tm.tm_sec = buf[5];
|
||||||
|
|
||||||
return timegm(&tm) - ((int8_t)buf[6]) * 60 * 15;
|
return timegm(&tm) - ((int8_t)buf[6]) * 60 * 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1413,16 +1716,17 @@ char *iso_util_strcopy(const char *buf, size_t len)
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *iso_util_strcopy_untail(const char *buf, size_t len)
|
char *iso_util_strcopy_untail(const char *buf, size_t len_in)
|
||||||
{
|
{
|
||||||
char *str;
|
char *str;
|
||||||
|
int len;
|
||||||
|
|
||||||
str = iso_util_strcopy(buf, len);
|
str = iso_util_strcopy(buf, len_in);
|
||||||
if (str == NULL) {
|
if (str == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* remove trailing spaces */
|
/* remove trailing spaces */
|
||||||
for (len = len-1; len >= 0; --len) {
|
for (len = len_in - 1; len >= 0; --len) {
|
||||||
if (str[len] != ' ')
|
if (str[len] != ' ')
|
||||||
break;
|
break;
|
||||||
str[len] = 0;
|
str[len] = 0;
|
||||||
@ -1440,12 +1744,12 @@ void strncpy_pad(char *dest, const char *src, size_t max)
|
|||||||
|
|
||||||
if (src != NULL) {
|
if (src != NULL) {
|
||||||
len = MIN(strlen(src), max);
|
len = MIN(strlen(src), max);
|
||||||
|
for (i = 0; i < len; ++i)
|
||||||
|
dest[i] = src[i];
|
||||||
} else {
|
} else {
|
||||||
len = 0;
|
len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < len; ++i)
|
|
||||||
dest[i] = src[i];
|
|
||||||
for (i = len; i < max; ++i)
|
for (i = len; i < max; ++i)
|
||||||
dest[i] = ' ';
|
dest[i] = ' ';
|
||||||
}
|
}
|
||||||
@ -1477,7 +1781,7 @@ char *ucs2str(const char *buf, size_t len)
|
|||||||
|
|
||||||
n = iso_iconv(&conv, &src, &inbytes, &str, &outbytes, 0);
|
n = iso_iconv(&conv, &src, &inbytes, &str, &outbytes, 0);
|
||||||
iso_iconv_close(&conv, 0);
|
iso_iconv_close(&conv, 0);
|
||||||
if (n == -1) {
|
if (n == (size_t) -1) {
|
||||||
/* error */
|
/* error */
|
||||||
goto ex;
|
goto ex;
|
||||||
}
|
}
|
||||||
@ -1714,12 +2018,12 @@ int iso_util_eval_md5_tag(char *block, int desired, uint32_t lba,
|
|||||||
*tag_type = 0;
|
*tag_type = 0;
|
||||||
decode_ret = iso_util_decode_md5_tag(block, tag_type, &pos,
|
decode_ret = iso_util_decode_md5_tag(block, tag_type, &pos,
|
||||||
&range_start, &range_size, next_tag, md5, 0);
|
&range_start, &range_size, next_tag, md5, 0);
|
||||||
if (decode_ret != 1 && decode_ret != ISO_MD5_AREA_CORRUPTED)
|
if (decode_ret != 1 && decode_ret != (int) ISO_MD5_AREA_CORRUPTED)
|
||||||
return 0;
|
return 0;
|
||||||
if (*tag_type > 30)
|
if (*tag_type > 30)
|
||||||
goto unexpected_type;
|
goto unexpected_type;
|
||||||
|
|
||||||
if (decode_ret == ISO_MD5_AREA_CORRUPTED) {
|
if (decode_ret == (int) ISO_MD5_AREA_CORRUPTED) {
|
||||||
ret = decode_ret;
|
ret = decode_ret;
|
||||||
goto ex;
|
goto ex;
|
||||||
} else if (!((1 << *tag_type) & desired)) {
|
} else if (!((1 << *tag_type) & desired)) {
|
||||||
@ -1727,10 +2031,24 @@ unexpected_type:;
|
|||||||
iso_msg_submit(-1, ISO_MD5_TAG_UNEXPECTED, 0, NULL);
|
iso_msg_submit(-1, ISO_MD5_TAG_UNEXPECTED, 0, NULL);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
goto ex;
|
goto ex;
|
||||||
} else if(pos != lba) {
|
} else if (pos != lba) {
|
||||||
|
if (*tag_type == 2) { /* Superblock tag */
|
||||||
|
if (lba < 32) {
|
||||||
|
/* Check whether this is a copied superblock */
|
||||||
|
range_start -= (off_t) pos - (off_t) lba;
|
||||||
|
if (range_start != ctx_start_lba) {
|
||||||
|
|
||||||
|
/* >>> check for matching MD5 ? */;
|
||||||
|
|
||||||
|
ret = ISO_MD5_TAG_MISPLACED;
|
||||||
|
} else
|
||||||
|
ret = ISO_MD5_TAG_COPIED;
|
||||||
|
goto ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
ret = ISO_MD5_TAG_MISPLACED;
|
ret = ISO_MD5_TAG_MISPLACED;
|
||||||
goto ex;
|
goto ex;
|
||||||
} else if(range_start != ctx_start_lba) {
|
} else if (range_start != ctx_start_lba) {
|
||||||
ret = ISO_MD5_TAG_MISPLACED;
|
ret = ISO_MD5_TAG_MISPLACED;
|
||||||
}
|
}
|
||||||
ret = iso_md5_clone(ctx, &cloned_ctx);
|
ret = iso_md5_clone(ctx, &cloned_ctx);
|
||||||
@ -1748,4 +2066,29 @@ ex:;
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *iso_alloc_mem(size_t size, size_t count, int flag)
|
||||||
|
{
|
||||||
|
void *pt;
|
||||||
|
|
||||||
|
pt = calloc(size, count);
|
||||||
|
if(pt == NULL)
|
||||||
|
iso_msg_submit(-1, ISO_OUT_OF_MEM, 0, "Out of virtual memory");
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t iso_ntohs(uint16_t v)
|
||||||
|
{
|
||||||
|
return iso_read_msb((uint8_t *) &v, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t iso_htons(uint16_t v)
|
||||||
|
{
|
||||||
|
uint16_t ret;
|
||||||
|
|
||||||
|
iso_msb((uint8_t *) &ret, (uint32_t) v, 2);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* 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
|
* 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
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -11,7 +11,14 @@
|
|||||||
#ifndef LIBISO_UTIL_H_
|
#ifndef LIBISO_UTIL_H_
|
||||||
#define LIBISO_UTIL_H_
|
#define LIBISO_UTIL_H_
|
||||||
|
|
||||||
|
#ifdef HAVE_STDINT_H
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_INTTYPES_H
|
||||||
|
#include <inttypes.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#ifndef MAX
|
#ifndef MAX
|
||||||
@ -86,8 +93,11 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output);
|
|||||||
*
|
*
|
||||||
* @param src
|
* @param src
|
||||||
* The identifier, in ASCII encoding.
|
* 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.
|
* Create a level 2 directory identifier.
|
||||||
@ -117,8 +127,13 @@ char *iso_r_dirid(const char *src, int size, int relaxed);
|
|||||||
*
|
*
|
||||||
* @param src
|
* @param src
|
||||||
* The identifier, in ASCII encoding.
|
* 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.
|
* Create a level 2 file identifier.
|
||||||
@ -146,13 +161,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
|
* Create a Joliet file identifier that consists of name and extension. The
|
||||||
* combined name and extension length will not exceed 128 bytes, and the
|
* combined name and extension length will normally not exceed 64 characters
|
||||||
* name and extension will be separated (.). All characters consist of
|
* (= 128 bytes). The name and the extension will be separated (.).
|
||||||
* 2 bytes and the resulting string is NULL-terminated by a 2-byte NULL.
|
* 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.
|
* Note that version number and (;1) is not appended.
|
||||||
* @param flag
|
* @param flag
|
||||||
* bit0= no_force_dots
|
* bit0= no_force_dots
|
||||||
|
* bit1= allow 103 characters rather than 64
|
||||||
* @return
|
* @return
|
||||||
* NULL if the original name and extension both are of length 0.
|
* NULL if the original name and extension both are of length 0.
|
||||||
*/
|
*/
|
||||||
@ -164,10 +181,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
|
* 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.
|
* 2 bytes and the resulting string is NULL-terminated by a 2-byte NULL.
|
||||||
*
|
*
|
||||||
|
* @param flag
|
||||||
|
* bit1= allow 103 characters rather than 64
|
||||||
* @return
|
* @return
|
||||||
* NULL if the original name and extension both are of length 0.
|
* 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.
|
* Like strlen, but for Joliet strings.
|
||||||
@ -213,6 +232,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_msb(uint8_t *buf, uint32_t num, int bytes);
|
||||||
void iso_bb(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_lsb(const uint8_t *buf, int bytes);
|
||||||
uint32_t iso_read_msb(const uint8_t *buf, int bytes);
|
uint32_t iso_read_msb(const uint8_t *buf, int bytes);
|
||||||
|
|
||||||
@ -505,13 +528,61 @@ int iso_util_tag_magic(int tag_type, char **tag_magic, int *len, int flag);
|
|||||||
*/
|
*/
|
||||||
int checksum_cx_xinfo_func(void *data, 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
|
/* Function to identify and manage md5 sums of unspecified providence stored
|
||||||
* directly in this xinfo. This is supposed to override any other recorded
|
* 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.
|
* MD5 of the node unless data get copied and checksummed during that copying.
|
||||||
*/
|
*/
|
||||||
int checksum_md5_xinfo_func(void *data, int flag);
|
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); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
/* 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_*/
|
#endif /*LIBISO_UTIL_H_*/
|
||||||
|
@ -164,7 +164,7 @@ int iso_rbtree_insert(IsoRBTree *tree, void *data, void **item)
|
|||||||
new = data;
|
new = data;
|
||||||
added = 1;
|
added = 1;
|
||||||
} else {
|
} 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 *g, *t; /* Grandparent & parent */
|
||||||
struct iso_rbnode *p, *q; /* Iterator & parent */
|
struct iso_rbnode *p, *q; /* Iterator & parent */
|
||||||
|
Reference in New Issue
Block a user