Compare commits

..

301 Commits

Author SHA1 Message Date
1dd05f63a7 Version leap to 1.2.4 2012-07-20 20:04:30 +02:00
fe07c87788 Updated changelog 2012-07-20 14:23:03 +02:00
8c58e2a012 Corrected some indentation 2012-07-20 13:14:57 +02:00
b6b8b1625c Removed obsolete code variations from hfsplus.c 2012-07-20 13:10:18 +02:00
042dbd01ed Removed obsolete development marks 2012-07-20 12:21:36 +02:00
7001121a3f New flag bit with iso_node_set_attrs() to protect namespace "isofs" 2012-07-12 18:16:38 +02:00
942ec97c7b Made Libisofs_with_rr_reloc_diR unconditional 2012-07-11 15:52:53 +02:00
8b2edd7ca4 Mad new hfsplus_case.c usable for GNU xorriso 2012-07-11 12:16:45 +02:00
2e6c3efda2 Corrected a comment in new hfsplus_case.c 2012-07-11 12:09:18 +02:00
2e63856dee Replaced implementation of HFS+ case-insensitive character conversion
by one of my own copyright.
2012-07-11 11:31:45 +02:00
b211ce6804 Clarified copyright of libisofs/hfsplus_classes.c 2012-07-07 11:40:18 +02:00
4c2a24514d Replaced use of ntohs() and htons() by iso_ntohs() and iso_htons(). 2012-07-06 17:33:45 +02:00
b07d60bbfc Moved some functions from util.c to hfsplus.c 2012-07-03 18:56:26 +02:00
e8f6f924bd Adjusting symbolic links in HFS+ which are affected by name mangling 2012-07-02 19:57:25 +02:00
7a8995f322 New API call iso_tree_resolve_symlink(). 2012-07-01 18:41:54 +02:00
2c88e74798 Introduced mangling of HFS+ names for case-insensitive uniqueness. 2012-06-30 21:48:42 +02:00
2d441cca5d New API call iso_write_opts_set_hfsp_block_size(). 2012-06-27 20:39:57 +02:00
7e49fb553b Enabled the opportunity to set HFSPLUS_BLOCK_SIZE to 512 for experiments. 2012-06-24 16:00:03 +02:00
af367561a6 Setting the boot bit with the CHRP MBR partition. 2012-06-22 16:33:03 +02:00
85bedae639 Introduced opportunity to choose an MBR partition number with
struct iso_mbr_partition_request and iso_quick_mbr_entry().
2012-06-21 12:29:00 +02:00
bbd198a81b Avoiding a SIGSEGV if no El Torito is involved. Introduced by rev 1014. 2012-06-20 20:40:15 +02:00
2a08471c04 Trying to get push to work after merge. 2012-06-20 19:41:10 +02:00
72bdd7a3d0 Small update in doc/boot_sectors.txt 2012-06-20 19:32:30 +02:00
bab3cf0c7c New option bits 2 to 7 with el_torito_set_isolinux_options() 2012-06-20 19:21:35 +02:00
862d4fb571 Revoked rev 1013: Partition type of PReP is indeed 0x41. 2012-06-20 13:08:37 +02:00
27277914c6 Ended the special out-of-loop handling of eltorito_writer_compute_data_blocks() 2012-06-19 16:49:03 +02:00
2d3bbe51ed Corrected partition type of PReP from 0x41 to 0x42 2012-06-19 11:37:44 +02:00
5288cec97d Removed an obsolete experimental member from Ecma119Image 2012-06-18 15:13:48 +02:00
09b314c66f Reacted on harmless compiler warning. 2012-06-18 14:43:56 +02:00
55e134fb1c Enabled writing of EFI El Torito boot image as EFI System Partition outside
the range of the HFS+ partition.
2012-06-18 10:06:16 +02:00
9882d983b9 Avoiding to print a NULL pointer via %s in a HFS+ debug message 2012-06-17 12:56:32 +02:00
6fd859a2c1 Closed a potential memory leak in case of memory shortage 2012-06-15 20:07:30 +02:00
4d10b8c73c Silenced compiler warnings about too modern array initilization. 2012-06-14 13:46:31 +02:00
0ebc8fe186 Provisorily moved tail writer after checksum writer
and accounted for size of backup GPT in cylinder alignment of tail writer.
2012-06-13 13:31:37 +02:00
912e0cd1be Provisorily allowing the combination of HFS+ and CHRP. 2012-06-13 08:15:38 +02:00
3a60720099 Correcterd criterion for enabling CHRP partition entry. 2012-06-12 21:58:55 +02:00
c166a49889 Bug fix: Partition cylinder alignment worked only if both, El Torito and
application provided system area data were present.
2012-06-12 21:21:14 +02:00
6fc3bb6777 New ystem area sub type CHRP with iso_write_opts_set_system_area() 2012-06-12 21:16:56 +02:00
d7401f0a4c Updated description of boot sectors by sparse info about PReP, CHRP.
Described the layout for GRUB2 based hybrid images.
2012-06-12 17:42:22 +02:00
6a3273dc72 New API calls so_write_opts_set_prep_img(), iso_write_opts_set_efi_bootp() 2012-06-12 13:24:50 +02:00
0897896713 Inner API for requesting MBR partition table entries. 2012-06-11 13:05:46 +02:00
1de0284eaa New API call iso_write_opts_set_fat(). (FAT feature not implemented yet.) 2012-06-10 19:41:00 +02:00
7c6c3466e9 Provisorily moved gpt_tail_writer to the very end of the writer list. 2012-06-10 16:08:36 +02:00
3528795b55 Corrected computation for error ISO_OVWRT_FIFO_TOO_SMALL. 2012-06-10 15:09:08 +02:00
3b95f4c4c4 Closed a small memory leak found by valgrind 2012-06-10 12:52:34 +02:00
2cc387fcce Aborting image generation in case of ISO_OVWRT_FIFO_TOO_SMALL. 2012-06-10 12:48:22 +02:00
45bee0a849 Marking HFS+ partition in APM as automountable for legacy Macs. 2012-06-10 10:42:39 +02:00
7fd36ffade Reserved new AAIP names isofs.hb and isofs.hx for storing HFS+ attributes. 2012-06-07 23:15:16 +02:00
5427fa9e17 Described the layout of APM and GPT. Moved description of isohybrid
and grub-mkrescue to the end of boot_sectors.txt.
2012-06-07 15:38:05 +02:00
ce17f78d59 Changed APM data partition flags from 0x03 to 0x13. 2012-06-07 15:35:58 +02:00
1bbdb97a2d Small change in iso_hybrid_fs.txt 2012-06-07 10:58:51 +02:00
f39e73d2ce Updated the documentation about the overall framework of libisofs
image production and opportunities to add metadata of other filesystem
types.
2012-06-07 10:45:09 +02:00
74bc1808a1 Renamed gpt_tail_writer_ecma119_writer_create() to gpt_tail_writer_create(). 2012-06-07 10:38:27 +02:00
ad251e8c7d Mentioned in API description the impact of iso_write_opts_set_hfsplus()
on System Area.
2012-06-06 18:58:00 +02:00
cb3a6f8bb0 Pre-computing size of data file content area and publishing it to
writers as Ecma119Image.filesrc_blocks.
2012-06-05 21:29:52 +02:00
a3285f6e5d Silenced a compiler warning 2012-06-05 17:00:16 +02:00
36502f8ae3 Second stage of implementation of GPT production.
It implements the writer class for the backup GPT.
2012-06-04 20:39:34 +02:00
21109ffcf1 Disabled GTP test mock-up. 2012-06-02 19:37:23 +02:00
bcd4b88319 First stage of implementation of GPT production.
The writer class for the backup GPT is not implemented yet.
2012-06-02 19:32:22 +02:00
714ef6493a New API call iso_image_hfsplus_get_blessed() 2012-05-30 16:42:12 +02:00
01b2ee088b Silenced a harmless compiler warning. 2012-05-30 12:51:37 +02:00
2ed96d89f9 Corrections to HFS+ code by Vladimir Serbinko. 2012-05-30 08:57:04 +02:00
cc71d9e30b Now writing micro mock-up of APM Block0.
Corrected block size handling with APM entry 1.
2012-05-29 22:17:09 +02:00
4fd7faa636 Fixed a bug about APM that was introduced with rev 968. Found by Vladimir. 2012-05-29 21:20:42 +02:00
d2c19ed2b4 New adjustemets to HFS+ by Vladimir Serbinenko. 2012-05-29 17:59:42 +02:00
63df7749fa Silenced compiler warnings by fixing micro bugs. 2012-05-28 09:27:07 +02:00
e9eb22f514 New error code ISO_BOOT_APM_OVERLAP 2012-05-28 09:17:17 +02:00
e57e45e40b New API call iso_write_opts_set_hfsp_serial_number(). 2012-05-27 18:55:04 +02:00
1ed3ba7933 Introduced internal pseudo-random generators iso_random_uuid() and
iso_random_8byte().
2012-05-27 16:05:56 +02:00
3e2479c095 Fixed a bug in yet unused code which was introduced by rev 965. 2012-05-26 23:17:59 +02:00
bc7e8acb74 Corrected three comments about recently introduced error codes. 2012-05-26 23:09:55 +02:00
8770148cad Introduced inner API iso_apm_partition_request for definition of
Apple Partition Map entries by hfsplus.c.
2012-05-26 23:04:42 +02:00
6fc6a09040 Fixed several memory problems introduced by rev 965 2012-05-25 20:57:06 +02:00
a72fd6a309 Corrected a comment in libisofs.h 2012-05-25 19:55:45 +02:00
82f39020cf Attributed HFS+ blessings to IsoImage rather than IsoWriteOpts. 2012-05-25 19:34:09 +02:00
1842921b2c Adaptions to new HFS+ blessing interface by Vladimir Serbinenko. 2012-05-25 18:19:46 +02:00
ab11c954d9 Created API and hfsplus interface of HFS+ blessing.
But iso_write_opts_bless() is still a dummy.
2012-05-25 14:40:06 +02:00
177864bd13 Made struct iso_hfsplus_xinfo_data clonable. 2012-05-25 10:42:26 +02:00
ed986aa4ea HFS+ enhancement by Vladimir Serbinenko:
Mostly symlinks, POSIX files and attributes.
2012-05-25 08:25:45 +02:00
45bf3d9717 Cleaned out obsolete development remarks. 2012-05-24 21:46:53 +02:00
c1df1c9fd8 Corrected type of the new iso_hfsplus_xinfo_data members. 2012-05-24 19:49:52 +02:00
a7ae64e3c7 Removed an unused variable. 2012-05-24 19:33:57 +02:00
6cb5f802af Committing the yet incomplete implementation of SYSLINUX isohybrid
for MBR, UEFI and x86-Mac. This shall avoid tangling with ongoing HFS+
efforts.
2012-05-24 19:31:00 +02:00
a8b20b87aa New API functions iso_hfsplus_xinfo_func(), iso_hfsplus_xinfo_new()
and pre-version 0 of struct iso_hfsplus_xinfo_data.
2012-05-24 19:27:03 +02:00
201e7f15df Including <arpa/inet.h> 2012-05-24 13:54:49 +02:00
f040f31d05 Registered new error ISO_SECT_SCATTERED in iso_error_to_msg(). 2012-05-24 13:06:49 +02:00
9e2d82fc78 Updated Vladimir Serbinenko's work. 2012-05-24 11:27:21 +02:00
1a5c02a27e Updated Vladimir Serbinenko's work. Replaced his extension of Iso_File_Src
by a function that computes the size from Iso_File_Src.sections.
2012-05-24 09:19:23 +02:00
e5a4e33ebd Bug fix: Joliet name comparison was done as signed bytes and thus produced
a peculiar sorting order. Thanks to Vladimir Serbinenko. (For previous commit
too.)
2012-05-23 20:59:14 +02:00
fae423fb54 Bug fix: The separator dot of Joliet names was byte swapped on big-endian
machines.
2012-05-23 20:58:31 +02:00
e97bd3ed2d Added Vladimir Serbinenko to list of libisofs authors. 2012-05-23 19:41:39 +02:00
2c540b1f43 Vladimir Serbinenko began to implement production of HFS+ metadata.
This revision introduces the writer class and a first attempt to integrate
it into image production. Not yet functional.
2012-05-23 14:47:49 +02:00
6982971796 Bug fix: Volume descriptors of Joliet and ISO 9660:1999 beared non-zero
Effective Date, involuntarily restricting the early end of their lifetime.
Thanks to Vladimir Serbinenko.
2012-05-22 16:46:17 +02:00
3c7c534ded Bug fix: File Structure Version field of ISO 9660:1999 Enhanced Volume
Descriptor was 1 instead of 2. Thanks to Vladimir Serbinenko.
2012-05-20 20:37:25 +02:00
262e49ad6b Documented probable isohybrid.c bugs and polished overview table. 2012-05-09 12:03:50 +02:00
502bea814e Documented MBR partitions and GUIDs 2012-05-08 19:46:03 +02:00
fa784d619c Corrected a wrong statement about CRC of empty input 2012-05-07 20:50:48 +02:00
977161cda1 Described the CRC algorithm of GPT 2012-05-07 20:33:53 +02:00
dc2b27ca51 Added an overview table to EFI isohybrid description. 2012-05-06 14:11:34 +02:00
abd2137906 Beginning to describe EFI isohybrid with Apple partition map and GPT. 2012-05-06 10:08:21 +02:00
ff95a84130 Bug fix: Symbol iso_fs_global_id was missing in libisofs.ver.
Thanks to: http://upstream-tracker.org/versions/libisofs.html
2012-04-28 08:51:50 +02:00
f384961808 Bug fix: Memory corruption when reading bootable image that was truncated
before the storage location of the boot catalog
2012-04-19 09:29:31 +02:00
81dd6ce55a Version leap to 1.2.3 2012-04-02 19:12:39 +02:00
125789feef Version leap to 1.2.2 2012-04-02 19:00:27 +02:00
37efffcf26 Removed obsolete development comments 2012-04-02 11:36:16 +02:00
b2c281d0c6 Updated ChangeLog 2012-03-27 13:51:52 +02:00
8a2fa9fe2e New API call iso_write_opts_set_allow_7bit_ascii(). 2012-03-22 11:18:44 +01:00
1247edff95 Reacted on warnings of cppcheck. 2012-03-21 20:28:15 +01:00
a2fe1a4100 Corrected flaws of revision 926. 2012-03-14 13:50:46 +01:00
4eb4146474 Improved standards compliance for ISO level 1 names with partly relaxed
constraints.
2012-03-14 09:07:59 +01:00
ce35aefb32 Bug fix: Directory name mapping to ISO level 1 was too liberal if
iso_write_opts_set_allow_dir_id_ext() was enabled.
2012-03-13 09:38:29 +01:00
269e0b19a5 Improved the ISO level 1 mapping of file names which begin by a dot. 2012-03-13 09:20:20 +01:00
0a8bb0e9b8 Made sure that empty relocation directory name leads to root directory. 2012-03-10 11:29:03 +01:00
76f2a5f4d3 New API call iso_write_opts_set_rr_reloc() 2012-03-09 19:59:51 +01:00
e49f9672bc Disabled skipping of ECMA-119 directory /RR_MOVED by name. 2012-03-06 16:18:05 +01:00
37f880797d Small comment change in libisofs/libisofs.h 2012-03-06 15:14:45 +01:00
475eb36978 Small change in doc/iso_hybrid_fs.txt 2012-03-06 15:13:45 +01:00
ac9116c64e Fixed a typo in doc/iso_hybrid_fs.txt 2012-02-22 18:06:23 +01:00
b1c218c280 Described the opportunities and constraints of ISO 9660 hybrid fileystems,
and the libisofs implementation needs when adding further filesystem types.
2012-02-21 22:30:29 +01:00
ebea7c29ef Reporting name of base file with error message for filtered streams 2012-02-11 19:09:40 +01:00
09c49f777a Version leap to 1.2.1 2012-01-27 15:57:45 +01:00
5f76be9d76 Version leap to 1.2.0 2012-01-27 10:59:50 +01:00
305fe3f496 Updated changelog 2012-01-27 10:56:50 +01:00
191c3245af Corrected libburnia domain name in AAIP documentation 2012-01-24 14:48:42 +01:00
b5b30b1c75 Updated ChangeLog 2012-01-24 14:00:27 +01:00
6a1bbaa902 Extended influence of iso_write_opts_set_dir_rec_mtime() to Joliet and
ISO 9660:1999.
2012-01-14 15:54:25 +01:00
bddc44d1ca Added ./bootstrap script to release tarball 2011-12-03 15:58:38 +01:00
9b61ff377c Removing demo/.libs with make clean 2011-12-03 15:43:18 +01:00
22fed6bedb Reacted on warning of cppcheck 2011-10-09 18:26:13 +02:00
3433592f69 Version leap to 1.1.7 2011-09-27 14:33:07 +02:00
d787ecbcd9 Version leap to 1.1.6 2011-09-27 14:29:18 +02:00
182edb3a00 Updated changelog 2011-09-26 19:10:13 +02:00
cb25d4d4e5 Clarified a remark about maximum length of RR name parts in CA. 2011-09-26 18:23:24 +02:00
afdef92343 Moved version number macros higher in libisofs/libisofs.h 2011-09-24 16:38:20 +02:00
2bc7084315 Adaptions and remarks about GNU/Hurd 2011-08-30 19:20:18 +02:00
6d10908a58 Detecting and rejecting multiple entries of user::, group::, other:: in ACL text 2011-08-24 09:23:02 +02:00
2ba54fafe7 New optional tolerance towards failure to restore "default" ACLS on FreeBSD. 2011-08-23 12:40:09 +02:00
ca63dac7e3 Enabled recording and restoring of extattr on FreeBSD.
Gave up unconditional ACL support in favor of configure control.
2011-08-22 17:10:13 +02:00
f885da8087 Avoided to restore xattr of namespace "isofs" if non-"user" restoring is
enabled.
2011-08-22 15:57:16 +02:00
8438db02cf Avoided to call calloc() for 0 bytes when reading Linux xattr. 2011-08-22 12:37:11 +02:00
ce19db5e19 Bug fix: On Solaris: False out-of-memory errors when writing images. 2011-08-19 12:40:45 +02:00
aeb5258ae2 Removed rogue comma from FreeBSD ACL adapter 2011-08-18 16:06:33 +02:00
f10c2d7779 New API call iso_local_attr_support() 2011-08-18 15:07:31 +02:00
82bfcf429a Bug fix: No ACLs were recorded on FreeBSD. 2011-08-18 10:29:34 +02:00
8fb8c01a0f Corrected a theoretical flaw in a code path which is not yet used. 2011-08-18 10:28:41 +02:00
73910e2f3c Bug fix: ACL entries of groups and of user id 0 were not properly recorded
and cannot be restored.
2011-08-18 10:26:09 +02:00
9c5fc21679 Small change in a comment 2011-08-18 10:24:47 +02:00
3a82f213e0 Implemented direct iconv conversion for the case that the traditional
two-step conversion via character set "WCHAR_T" fails. E.g. on Solaris.
2011-08-11 18:22:49 +02:00
6892c734e2 Bug fix: The function for restoring ACLs and xattr returned error on
FreeBSD, even if no xattr were to be restored.
2011-08-09 19:00:03 +02:00
66f6937c17 Clarified stream version prescription and made internal stream data
instances static.
2011-08-09 14:59:19 +02:00
baa5b7cd42 Added missing symbol serial_id to libisofs.ver 2011-08-09 14:58:46 +02:00
f2658ef173 Started new development cycle 2011-08-09 12:32:04 +02:00
ecdb3aeb1d Version leap to 1.1.5 2011-08-08 13:58:43 +02:00
745a878884 Version leap to 1.1.4 2011-08-08 09:35:46 +02:00
6ae8386c23 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.
2011-08-08 08:25:18 +02:00
b90e613246 Reacted on warnings of cppcheck 2011-07-11 12:44:12 +02:00
bbc3caf86b Reacted on warnings of cppcheck 2011-07-11 12:43:12 +02:00
b086d53274 Reacted on warnings of cppcheck 2011-07-11 12:41:30 +02:00
17b36623a6 Version leap to 1.1.3 2011-07-08 14:42:09 +02:00
286648574d Version leap to 1.1.2 2011-07-08 10:28:12 +02:00
317bba395e Updated changelog 2011-07-08 10:25:24 +02:00
541b41b6a1 Clarified a comment about retrieving content of boot catalog. 2011-07-07 14:11:30 +02:00
91a8be5262 Silenced a warning of cppcheck about possible null pointer dereference. 2011-07-06 12:31:37 +02:00
91e99703b4 Reacted on warnings of -Wunused-but-set-variable 2011-07-04 18:54:11 +02:00
dd7dac3397 Reacted on warnings of -Wunused-but-set-variable 2011-07-04 16:07:35 +02:00
43d4833dd6 Reacted on warnings of -Wunused-but-set-variable 2011-07-04 16:06:16 +02:00
dd1629b5ca Reacted on warnings of -Wunused-but-set-variable 2011-07-04 16:04:05 +02:00
bc8138ce78 Reacted on warnings of -Wunused-but-set-variable 2011-07-04 16:00:29 +02:00
2d568c1dbb Reacted on warnings of -Wunused-but-set-variable 2011-07-04 15:56:26 +02:00
842b62d111 Reacted on warnings of -Wunused-but-set-variable 2011-07-04 15:50:52 +02:00
4f3357e3ec Reacted on warnings of -Wunused-but-set-variable 2011-07-04 15:39:38 +02:00
9ffe91c372 Reacted on warnings of -Wunused-but-set-variable 2011-07-04 15:37:55 +02:00
7e2add413a Reacted on warnings of -Wunused-but-set-variable 2011-07-04 15:35:43 +02:00
004aefd0b7 New API call iso_image_get_bootcat() 2011-07-03 21:02:19 +02:00
00955ba85c Version leap to 1.1.1 2011-06-18 19:22:11 +02:00
4a79812d15 Version leap to 1.1.0 2011-06-18 14:23:02 +02:00
9b2f97e4b7 Updated changelog 2011-06-18 14:06:38 +02:00
35cfb756be 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.
2011-06-15 17:09:48 +02:00
2835fccfa4 Replaced some large local variables by other means in libisofs/util.c 2011-06-12 12:46:52 +02:00
31c7f68990 Replaced some large local variables by other means in libisofs/system_area.c 2011-06-12 12:28:38 +02:00
4e0ca258de Replaced some large local variables by other means in libisofs/stream.c 2011-06-12 09:59:53 +02:00
9653854462 Replaced some large local variables by other means in libisofs/rockridge.c 2011-06-12 09:51:08 +02:00
6e95f8bbcb Replaced some large local variables by other means in libisofs/messages.c 2011-06-11 22:23:44 +02:00
ce3aa0d5c7 Replaced some large local variables by other means in libisofs/md5.c 2011-06-11 19:23:32 +02:00
d5bfc552c4 Replaced some large local variables by other means in libisofs/joliet.c 2011-06-11 16:33:57 +02:00
bad54a5967 Replaced some large local variables by other means in libisofs/iso1999.c 2011-06-11 13:42:55 +02:00
49b0a89bfe Replaced some large local variables by other means in libisofs/fs_image.c 2011-06-11 12:40:33 +02:00
265df5fbe3 Replaced some large local variables by other means in libisofs/filesrc.c 2011-06-11 11:08:20 +02:00
f089bcf66a Replaced some large local variables by other means in libisofs/ecma119.c 2011-06-10 14:55:57 +02:00
062e5f0bf0 Changed error code of libisofs/util.h from -1 to ISO_OUT_OF_MEM 2011-06-10 14:55:34 +02:00
d932bfcdea Replaced some large local variables by other means in libisofs/builder.c 2011-06-09 16:51:00 +02:00
3ef67cb49d Replaced some large local variables by other means in libisofs/aaip_0_2.c 2011-06-09 14:27:41 +02:00
f08ae22dbe Macros LIBISO_ALLOC_MEM, LIBISO_FREE_MEM for replaceing local variables 2011-06-09 14:23:21 +02:00
45d316d1ca Added option -I . to aclocal in bootstrap script on advise of George Danchev 2011-06-09 14:21:20 +02:00
4d8fc6ffee Introduced AC_CONFIG_MACRO_DIR() and ACLOCAL_AMFLAGS on advise of George Danchev 2011-06-08 21:27:53 +02:00
023e413624 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for
libisofs/aaip-os-freebsd.c
2011-06-02 10:28:52 +02:00
d361186bca Made callers of iso_file_source_get_path() aware that NULL might be returned. 2011-06-01 11:37:30 +02:00
e7d9559d16 Avoiding to produce NM field for "." and ".." entries if Rock Ridge
version 1.10 is chosen by iso_write_opts_set_rrip_version_1_10()
2011-06-01 11:34:45 +02:00
94eecbb123 Reacted on static code checker warning reported by George Danchev 2011-05-22 20:23:48 +02:00
777f74ea0b Added options -Wextra -Wno-unused-parameter for gcc 2011-05-22 16:35:22 +02:00
2b8d47ddd8 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for util_rbtree.c 2011-05-21 23:21:14 +02:00
e839b7b368 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for util.c 2011-05-21 23:20:44 +02:00
1334027a83 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for tree.c 2011-05-21 23:19:34 +02:00
8d3a0a6a9e Reacted on -Wextra -Wno-unused-parameter warnings of gcc for system_area.c 2011-05-21 23:19:06 +02:00
7b7ea41f12 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for stream.c 2011-05-21 23:18:35 +02:00
bb5886094e Reacted on -Wextra -Wno-unused-parameter warnings of gcc for rockridge_read.c 2011-05-21 23:18:00 +02:00
b076ce9b44 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for rockridge.c 2011-05-21 23:17:38 +02:00
05f26898f3 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for node.c 2011-05-21 23:16:35 +02:00
a698f0ee22 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for messages.c 2011-05-21 23:16:10 +02:00
e69854b35f Reacted on -Wextra -Wno-unused-parameter warnings of gcc for md5.c 2011-05-21 23:15:48 +02:00
228995c148 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for make_isohybrid_mbr.c 2011-05-21 23:15:19 +02:00
071e14f9b0 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for joliet.c 2011-05-21 23:14:49 +02:00
b08d6271ab Reacted on -Wextra -Wno-unused-parameter warnings of gcc for iso1999.c 2011-05-21 23:14:16 +02:00
431d31fff6 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for fs_local.c 2011-05-21 23:13:40 +02:00
a37571c6c5 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for fs_image.c 2011-05-21 23:13:16 +02:00
6e98006640 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for filters/zisofs.c 2011-05-21 23:12:29 +02:00
d264e818c3 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for filters/gzip.c 2011-05-21 23:11:48 +02:00
d0f740facf Reacted on -Wextra -Wno-unused-parameter warnings of gcc for eltorito.c 2011-05-21 23:11:18 +02:00
944b5a6152 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for ecma119_tree.c 2011-05-21 23:10:21 +02:00
b51232fef4 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for ecma119.c 2011-05-21 23:09:44 +02:00
99f037e210 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for buffer.c 2011-05-21 23:08:53 +02:00
c794a48a06 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for aaip_0_2.c 2011-05-21 23:08:14 +02:00
47d599e8c3 Reacted on -Wextra -Wno-unused-parameter warnings of gcc for aaip-os-linux.c 2011-05-21 23:05:17 +02:00
0a87e838df Mentioned the need to define uint32_t when including libisofs.h 2011-05-19 15:43:44 +02:00
e945e38add Mentioned upcomming version in ChangeLog 2011-05-13 09:01:01 +02:00
6d68abc707 Version leap to 1.0.9 2011-05-12 18:59:38 +02:00
e80dd0735b Version leap to 1.0.8 2011-05-12 18:55:58 +02:00
c276681735 Updated changelog. 2011-05-12 16:43:46 +02:00
1d723f0834 Corrected an inappropriate variable type when setting xattr or ACL. 2011-05-12 16:22:02 +02:00
1a4b2a2584 Bug fix: SIGSEGV if the path given by iso_image_add_mips_boot_file()
does not exist in the image at image production time.
2011-05-09 15:32:27 +02:00
4eb2a7199c Bug fix: iso_write_opts_set_system_area() with system area types
1=MIPS Big Endian and 2=MIPS Little Endian caused SIGSEGV.
2011-05-09 15:12:52 +02:00
6d5e68fd01 Clarified two comments. 2011-05-06 13:32:06 +02:00
fed8b23017 Returning proper error code on memory shortage with iso_node_lookup_attr(). 2011-05-06 13:30:37 +02:00
e3329a98a9 Corrected previous revision which freed memory too generously 2011-05-01 22:49:34 +02:00
49efbdad76 Closed tiny memory leak detected by valgrind. 2011-05-01 16:44:20 +02:00
9538a5d57b Performing collision test before FileSource creation in iso_tree_add_new_node() 2011-04-28 20:24:17 +02:00
66dc6c2d0e Disabled HAVE_DOT in doxygen.conf 2011-04-15 14:52:36 +02:00
81608815ae Closed a memory leak which happened in case of memory shortage. 2011-04-11 20:49:03 +02:00
ae5ab4a08f Closed a memory leak of 32 kB per loaded ISO image. 2011-04-11 20:47:34 +02:00
76b6737570 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.)
2011-04-11 20:19:35 +02:00
9210a57500 Version leap to 1.0.7 2011-04-09 11:11:36 +02:00
8a752b50fa Version leap to 1.0.6 2011-04-08 19:47:18 +02:00
c38b1a3a3a Updated changelog 2011-04-08 19:00:33 +02:00
73c9c7f244 Removed inactive debugging code 2011-04-08 18:56:08 +02:00
0b9f03bb23 Fixed a typo in comments 2011-04-05 09:20:25 +02:00
d1c3a017e3 Cleaned up use of PATH_MAX (local filesystem) and LIBISOFS_NODE_PATH_MAX
(ISO filesystem).
2011-04-03 11:02:15 +02:00
b200feceed Requiring libjte version 1.0.0 (if libjte is to be linked at all). 2011-04-02 16:30:23 +02:00
7958b2ea22 Mentioned configure option to disable libjte 2011-03-31 18:26:23 +02:00
c0bdf4d3b5 Reacted on warning about theoretical memory leak. 2011-03-28 20:43:13 +02:00
71efc996e3 New error code ISO_RR_PATH_TOO_LONG. 2011-03-28 15:00:44 +02:00
61383dea2d New error codes ISO_RR_NAME_TOO_LONG and ISO_RR_NAME_RESERVED for
occasions which previously returned ISO_WRONG_ARG_VALUE.
2011-03-26 20:54:20 +01:00
270cd1cad5 Closed a memory leak found by valgrind. 2011-03-26 19:23:51 +01:00
559e9b564d New API call iso_write_opts_set_joliet_long_names() 2011-03-26 15:38:08 +01:00
d8a56f60ef Interpreting the return values of fwrite() in demo/demo.c 2011-03-11 09:09:39 +01:00
10e3b2939a Updated copyright year 2011-03-10 20:03:35 +01:00
ba67523278 Version leap to 1.0.5 2011-03-10 13:43:13 +01:00
f09964cf51 Version leap to 1.0.4 2011-03-10 09:22:57 +01:00
e4a70a823d Updated changelog 2011-03-10 08:36:03 +01:00
655d86b97a Bug fix: Compilation failed if --disable-zlib was configured 2011-03-09 21:24:47 +01:00
f2f780115b New no_md5 value 2 for API call iso_read_opts_set_no_md5() 2011-03-08 19:37:52 +01:00
b6be8457f7 Fixed a memory hog introduced with rev 775. 2011-03-07 11:11:58 +01:00
1238c19494 Changed message about cylinder alignment. 2011-03-04 15:14:11 +01:00
2caf527f67 Refusign cylinder alignment if it is impossible to do it exactly. 2011-03-04 11:24:36 +01:00
43eae7502b New option bits 8 and 9 with iso_write_opts_set_system_area(). 2011-03-03 19:14:40 +01:00
e035146e01 Bug fix: isohybrid image size was not aligned to cylinder boundary.
Now the cylinder size gets adjusted if the image does not fit into 1024 cyl.
2011-03-01 18:31:59 +01:00
de3e21629f Corrected little flaws detected by George Danchev with cpp. 2011-02-24 20:02:56 +01:00
d79a3fcec4 Incresed mismatch test severity to FATAL again. 2011-02-23 20:16:59 +01:00
de079cec42 Version leap to 1.0.3 2011-02-23 20:14:10 +01:00
b33d06eb0c Version leap to 1.0.2 2011-02-23 13:01:56 +01:00
dfdaa2902a Reduced size mismtach test severity to WARNING.
This shall avoid the risk of false positives as long as the test is new.
2011-02-23 12:11:57 +01:00
0173c51c23 Updated change log. 2011-02-22 20:54:39 +01:00
a118127e9c Re-enabled use of system provide function timegm(), if available. 2011-02-21 13:46:46 +01:00
1f24b39879 Corrected sequence of IsoNode xinfo list after cloning. 2011-02-21 12:35:50 +01:00
16863755be Installed a check for miscalculated ECMA-119 tree size. 2011-02-20 12:10:26 +01:00
b25ac0f52d Avoided to give directories the same PX inode number.
(Solaris believes in them.)
2011-02-18 18:59:00 +01:00
5c59295e72 Bug fix: With a probability of 2 to 5 percent, AAIP could spoil the image
by miscalculating the number of root directory's CE blocks.
This lead to fatal offset of all further data by one block.
All sub directories and all data file content is affected.
Quite obvious to see. The problem existed since March 2009.
AAIP is used for recording of ACL and xattr. The problem gets enabled by call
iso_write_opts_set_aaip(opts, 1).
2011-02-18 17:39:21 +01:00
85893bf58b Removed warning not to use iso_tree_clone(). 2011-02-15 15:24:31 +01:00
722327e4b8 Overwriting eventually existing cloner of iso_node_xinfo_func with
iso_node_xinfo_make_clonable().
2011-02-12 14:48:31 +01:00
ab0a981814 Added capability to merge directories of cloned tree with existing
target tree.
2011-02-12 13:52:17 +01:00
38483d894e Added missing iso_filesystem_ref() for cloned node from local filesystem. 2011-02-01 22:16:05 +01:00
1082e628d1 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().
2011-02-01 19:16:45 +01:00
74c68224c7 Changed name of freshly introduce API call iso_write_opts_set_high_empty_address
to iso_write_opts_set_old_empty, reverted the meaning and the default.
2011-01-26 19:38:50 +01:00
200697898d New API call iso_write_opts_set_high_empty_address(). 2011-01-26 14:24:18 +01:00
a3eeda3d23 Yet incomplete implementation of IsoNode cloning.
(Commited to avoid tangling with upcomming 
 iso_write_opts_set_no_dummy_block_adr())
2011-01-25 10:50:37 +01:00
92073c45ef Bug fix: Volume Descriptor Set Terminator contained non-zero bytes in
the reserved field (ECMA-119 8.3.4). The bytes stem from an uninitialized
local variable.
2011-01-24 15:03:09 +01:00
81cded618d Better hiding of a defunct #ifndef 2011-01-18 17:50:26 +01:00
84c0bd37ff Avoiding <stdint.h> if not available. Trying to use <inttypes.h> in that case. 2011-01-18 16:18:09 +01:00
4e60feaeab Avoiding the use of setenv() and unsetenv() which are not available
on Solaris 9.
2011-01-18 15:26:19 +01:00
d6e150a10e Version leap to 1.0.1 2011-01-16 13:35:07 +01:00
35ceac65f7 Version leap to 1.0.0 2011-01-16 13:29:39 +01:00
45ffdef845 Closed loophole for undefined variable with new call
iso_write_opts_set_untranslated_name_len()
2011-01-16 13:28:07 +01:00
55d6ae343d Updated changelog 2011-01-16 11:17:07 +01:00
a69f45e8cd Made provisory test for directory record overflow permanent 2011-01-16 11:10:08 +01:00
68c3ae522e Added iso_memory_stream_new to list of public symbols. 2011-01-01 15:07:10 +01:00
8e2748f23b New API call iso_memory_stream_new(). (Was formely a private acll.) 2011-01-01 14:55:26 +01:00
f923a79929 New API call iso_write_opts_set_allow_dir_id_ext() 2010-12-25 08:11:19 +01:00
362b15f4d5 Bug fix: ECMA-119 directory names were truncated to 8 characters if
lowercase characters or full ASCII are allowed.
2010-12-24 20:31:24 +01:00
2649045dfe New API call iso_write_opts_set_untranslated_name_len() 2010-12-22 14:21:00 +01:00
3d427bdf70 Corrected a statemenent about Sector Count in boot record documentation. 2010-12-14 06:36:12 +01:00
8b2af3ac36 Prepending ./configure generated options to CFLAGS rather than appending them 2010-12-13 08:47:24 +01:00
113358daea Version leap to 0.6.41 2010-12-10 12:42:43 +01:00
63 changed files with 13681 additions and 1598 deletions

View File

@ -1,3 +1,4 @@
Vreixo Formoso
Mario Danic
Vladimir Serbinenko
Thomas Schmitt

View File

@ -1,7 +1,7 @@
Vreixo Formoso <metalpain2002@yahoo.es>,
Mario Danic <mario.danic@gmail.com>,
Thomas Schmitt <scdbackup@gmx.net>
Copyright (C) 2007-2010 Vreixo Formoso, Mario Danic, Thomas Schmitt
Copyright (C) 2007-2011 Vreixo Formoso, Mario Danic, Thomas Schmitt
This program is free software; you can redistribute it and/or modify

119
ChangeLog
View File

@ -1,6 +1,121 @@
bzr branch lp:libisofs/for-libisoburn (to become libisofs-0.6.42.tar.gz)
libisofs-1.2.4.tar.gz Fri Jul 20 2012
===============================================================================
- no novelties yet
* 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
===============================================================================
* Bug fix: ECMA-119 directory names were truncated to 8 characters if
lowercase characters or full ASCII are allowed.
* New API call iso_write_opts_set_untranslated_name_len()
* New API call iso_write_opts_set_allow_dir_id_ext()
* New API call iso_memory_stream_new(). (Was formely a private call.)
libisofs-0.6.40.tar.gz Fri Dec 10 2010
===============================================================================

View File

@ -6,6 +6,7 @@ pkgconfigdir=$(LIBBURNIA_PKGCONFDIR)
libincludedir=$(includedir)/libisofs
lib_LTLIBRARIES = libisofs/libisofs.la
ACLOCAL_AMFLAGS = -I ./
## ========================================================================= ##
@ -65,6 +66,11 @@ libisofs_libisofs_la_SOURCES = \
libisofs/rockridge_read.c \
libisofs/joliet.h \
libisofs/joliet.c \
libisofs/hfsplus.h \
libisofs/hfsplus.c \
libisofs/hfsplus_decompose.c \
libisofs/hfsplus_classes.c \
libisofs/hfsplus_case.c \
libisofs/eltorito.h \
libisofs/eltorito.c \
libisofs/system_area.h \
@ -219,6 +225,12 @@ demo_demo_SOURCES = demo/demo.c
# test/mocked_fsrc.h \
# test/mocked_fsrc.c
# "make clean" shall remove a few stubborn .libs directories
# which George Danchev reported Dec 03 2011.
# Learned from: http://www.gnu.org/software/automake/manual/automake.html#Clean
clean-local:
-rm -rf demo/.libs
## ========================================================================= ##
## Build documentation (You need Doxygen for this to work)
@ -249,6 +261,7 @@ nodist_pkgconfig_DATA = \
# ts A80114 : added aaip-os*
EXTRA_DIST = \
bootstrap \
libisofs-1.pc.in \
version.h.in \
doc/doxygen.conf.in \

1
README
View File

@ -54,6 +54,7 @@ applications which use it. This dependency can be avoided by configure options
--disable-libacl avoid use of ACL functions like acl_to_text()
--disable-xattr avoid use of xattr functions like listxattr()
--disable-zlib avoid use of zlib functions like compress2()
--disable-libjte avoid use of libjte functions
See INSTALL file for general options of ./configure.

View File

@ -1,10 +1,7 @@
#!/bin/sh -x
aclocal
aclocal -I .
libtoolize --copy --force
autoconf
# ts A61101 : libburn is not prepared for config.h
# autoheader
automake --foreign --add-missing --copy --include-deps

View File

@ -1,4 +1,4 @@
AC_INIT([libisofs], [0.6.40], [http://libburnia-project.org])
AC_INIT([libisofs], [1.2.4], [http://libburnia-project.org])
AC_PREREQ([2.50])
dnl AC_CONFIG_HEADER([config.h])
@ -8,6 +8,7 @@ AC_CANONICAL_TARGET
LIBBURNIA_SET_FLAGS
AM_INIT_AUTOMAKE([subdir-objects])
AC_CONFIG_MACRO_DIR([./])
dnl
dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match
@ -38,9 +39,9 @@ dnl It rather feeds the API function iso_lib_version().
dnl
dnl If LIBISOFS_*_VERSION changes, be sure to change AC_INIT above to match.
dnl
LIBISOFS_MAJOR_VERSION=0
LIBISOFS_MINOR_VERSION=6
LIBISOFS_MICRO_VERSION=40
LIBISOFS_MAJOR_VERSION=1
LIBISOFS_MINOR_VERSION=2
LIBISOFS_MICRO_VERSION=4
LIBISOFS_VERSION=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION.$LIBISOFS_MICRO_VERSION
AC_SUBST(LIBISOFS_MAJOR_VERSION)
@ -50,10 +51,10 @@ AC_SUBST(LIBISOFS_VERSION)
dnl Libtool versioning
LT_RELEASE=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION
# 2010.12.10 development jump has not yet happened
# SONAME = 42 - 36 = 6 . Library name = libisofs.6.36.0
LT_CURRENT=42
LT_AGE=36
# 2012.07.20 development jump has not yet happened
# SONAME = 66 - 60 = 6 . Library name = libisofs.6.60.0
LT_CURRENT=66
LT_AGE=60
LT_REVISION=0
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
@ -133,15 +134,15 @@ AC_ARG_ENABLE(debug,
, enable_debug=yes)
if test x$enable_debug != xyes; then
if test x$GCC = xyes; then
CFLAGS="$CFLAGS -O3"
CFLAGS="$CFLAGS -fexpensive-optimizations"
CFLAGS="-O3 $CFLAGS"
CFLAGS="-fexpensive-optimizations $CFLAGS"
fi
CFLAGS="$CFLAGS -DNDEBUG"
CFLAGS="-DNDEBUG $CFLAGS"
else
if test x$GCC = xyes; then
CFLAGS="$CFLAGS -g -pedantic -Wall"
CFLAGS="-g -pedantic -Wall -Wextra -Wno-unused-parameter $CFLAGS"
fi
CFLAGS="$CFLAGS -DDEBUG"
CFLAGS="-DDEBUG $CFLAGS"
fi
dnl Verbose debug to make libisofs issue more debug messages
@ -159,14 +160,19 @@ LIBBURNIA_SET_PKGCONFIG
dnl Add compiler-specific flags
AC_ARG_ENABLE(libacl,
[ --enable-libacl Enable use of libacl by libisofs, default=yes],
[ --enable-libacl Enable use of ACL functions by libisofs, default=yes],
, enable_libacl=yes)
if test "x$enable_libacl" = xyes; then
dnl Check whether there is libacl-devel and libacl-runtime.
dnl If not, erase this macro which would enable use of acl_to_text and others
LIBACL_DEF="-DLibisofs_with_aaip_acL"
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
LIBACL_DEF=
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
XATTR_DEF="-DLibisofs_with_aaip_xattR"
AC_CHECK_HEADER(attr/xattr.h, AC_CHECK_LIB(c, listxattr, X= , XATTR_DEF= ), XATTR_DEF= )
if test "x$XATTR_DEF" = x
then
XATTR_DEF="-DLibisofs_with_freebsd_extattR"
AC_CHECK_HEADER(sys/extattr.h, AC_CHECK_LIB(c, extattr_list_file, X=, XATTR_DEF= ), XATTR_DEF= )
fi
else
XATTR_DEF=
fi

View File

@ -50,6 +50,7 @@ static char helptext[][80] = {
#include <fcntl.h>
#include <err.h>
#include <limits.h>
#include <errno.h>
#ifndef PATH_MAX
@ -372,7 +373,11 @@ int gesture_iso(int argc, char **argv)
iso_write_opts_free(opts);
while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
fwrite(buf, 1, 2048, fp);
result = fwrite(buf, 1, 2048, fp);
if (result < 2048) {
printf ("Cannot write block. errno= %d\n", errno);
goto ex;
}
}
fclose(fp);
burn_src->free_data(burn_src);
@ -537,7 +542,7 @@ int gesture_iso_read(int argc, char **argv)
int gesture_iso_cat(int argc, char **argv)
{
int res;
int res, write_ret;
IsoFilesystem *fs;
IsoFileSource *file;
struct stat info;
@ -596,7 +601,11 @@ int gesture_iso_cat(int argc, char **argv)
return 1;
}
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) {
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);
while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
fwrite(buf, 1, 2048, fp);
result = fwrite(buf, 1, 2048, fp);
if (result < 2048) {
printf ("Cannot write block. errno= %d\n", errno);
goto ex;
}
}
fclose(fp);
burn_src->free_data(burn_src);
@ -814,7 +827,11 @@ int gesture_iso_ms(int argc, char **argv)
iso_write_opts_free(opts);
while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
fwrite(buf, 1, 2048, fp);
result = fwrite(buf, 1, 2048, fp);
if (result < 2048) {
printf ("Cannot write block. errno= %d\n", errno);
goto ex;
}
}
fclose(fp);
burn_src->free_data(burn_src);

View File

@ -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.
MBR, for PC-BIOS x86 from (pseudo-) hard disk
- SYSLINUX isohybrid MBR
- GRUB2 grub-mkrescue MBR.
Master Boot Record (MBR), for PC-BIOS x86 from (pseudo-) hard disk
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.
@ -25,6 +27,16 @@ DEC Boot Block, for MIPS Little Endian , e.g. DECstation.
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.
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
Boot Catalog.
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
1 = "PowerPC" (possibly for IBM machines with PowerPC CPU)
2 = "Mac" (possibly for Apple computers with MC68000 or PowerPC CPU)
Further in use by GRUB2 is:
Further in use by GRUB2 and ISOLINUX is:
0xef = EFI, a competitor resp. successor to PC-BIOS, possibly in use with
Intel ia64 Itanium and possibly with newer Apple machines.
@ -157,8 +175,8 @@ Byte Range | Value | Meaning
| | "the number of virtual/emulated sectors the system
| | will store at Load Segment during the initial boot
| | procedure."
| | libisofs stores 1 for emulated boot_media and
| | 0 for boot_media == 0.
| | libisofs stores 1 for emulated boot_media and a
| | user defined value for boot_media == 0. Often: 4.
| |
8 - 11 | load_rba | Load RBA. The 2 kB block address where the boot
| | image file content is located in the ISO 9660 image.
@ -210,8 +228,8 @@ Byte Range | Value | Meaning
| |
6 - 7 | sec_count | Sector Count.
| | See above Initial/Default Entry
| | libisofs stores 1 for emulated boot_media and
| | 0 for boot_media == 0.
| | libisofs stores 1 for emulated boot_media and a
| | user defined value for boot_media == 0. Often: 4.
| |
8 - 11 | load_rba | Load RBA. The 2 kB block address where the boot
| | image file content is located in the ISO 9660 image.
@ -248,7 +266,7 @@ Byte Range | Value | Meaning
------------------------------------------------------------------------------
MBR
Master Boot Record (MBR)
for PC-BIOS x86 from (pseudo-) hard disk
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
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:
syslinux-3.72/utils/isohybrid , a perl script by H. Peter Anvin = hpa.
Mailing list conversations with hpa.
http://mjg59.dreamwidth.org/11285.html
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
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.
GPT is the partition map format of EFI, a successor of PC-BIOS.
Block size is always 512. GPT consists of a header block at block address 1 and
a partition table near the start of the medium. This is called the primary GPT.
There is a backup copy of header and table near the end of the medium.
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
| |
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
| | starting 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
0 - 7 | sig | Signature "EFI PART" (with no trailing zero)
8 - 11 | revision | Revision = {0x00, 0x00, 0x01, 0x00} meaning "1.0"
12 - 15 | head_size | Header size = 0x5c = 92
16 - 19 | head_crc | CRC-32 of this header while head_crc is 0
20 - 23 | reserved | = 0
24 - 31 | curr_lba | Location of this header block = 1
32 - 39 | back_lba | Location of header backup block. See below.
40 - 47 | first_lba | First usable LBA for partitions
48 - 55 | last_lba | Last usable LBA for partitions
56 - 71 | guid | Disk GUID, Random
72 - 79 | part_start | Partition entries start
| | Normally this is 2. But to co-exist with APM, it
| might become some other number up to 62.
80 - 83 | entry_count| Number of partition entries
84 - 87 | entry_size | Size of a partition entry = 0x80 = 128
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:
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.
"
Near to the end of the image, after any data blocks which might be of interest
for the filesystems covered by GPT partitions, there is a backup of partition
table and header block.
The header block is supposed to mark the end of the usable medium. But libisofs
may have the need to add more data.
The partition table is stored directly before the header block. So it will
normally not begin at a 2 KiB block start.
------------------------------------------------------------------------------
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
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
Byte Range | Value | Meaning (little endian numbers, LBA unit is 512 byte)
---------- | ---------- | ----------------------------------------------------
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
16 - 19 | head_crc | CRC-32 of this header while head_crc is 0.
| | Is recomputed after the following changes.
24 - 31 | curr_lba | Location of this header block.
| | Shows own block address.
32 - 39 | back_lba | Location of header backup block.
| | Points to primary header block = 1
72 - 79 | part_start | Partition entries start.
| | Points to start of backup partition table.
---------- | ---------- | ----------------------------------------------------
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
"
An EFI System partition usually contains the same data blocks as the El Torito
boot image for EFI. It is used for booting some Macs from (pseudo-) hard disk.
------------------------------------------------------------------------------
@ -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
@ -723,5 +923,505 @@ Byte Range | Value | Meaning
>>> ??? 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 ?
------------------------------------------------------------------------------

View File

@ -1143,7 +1143,8 @@ HIDE_UNDOC_RELATIONS = YES
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)
HAVE_DOT = YES
# ts B10415: dot causes sigsegv on Debian buildd
HAVE_DOT = NO
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and

187
doc/iso_hybrid_fs.txt Normal file
View 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.

View File

@ -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.
Namespace "isofs." is defined for internal use of AAIP enhanced ISO 9660
file systems. Names in this namespace should be registered at libburnia.org.
file systems. Names in this namespace should be registered at
libburnia-project.org.
Further namespaces may be registered at libburnia.org.
Further namespaces may be registered at libburnia-project.org.
The reserved start bytes of names have the following meaning
0x01 escape reserved character at start of name

View File

@ -22,6 +22,8 @@ Purpose:
END is also the block address of the start of the checksum recording
area in the image.
See also isofs.cx .
This attribute shall eventually be attached to the root directory entry
and be global for the whole image.
Format of Value:
START_LEN | START_BYTES | END_LEN | END_BYTES |
@ -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:
isofs.st
@ -150,7 +201,7 @@ Registered:
-------------------------------------------------------------------------------
This text is under
Copyright (c) 2009 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Copyright (c) 2009 - 2011 Thomas Schmitt <scdbackup@gmx.net>
It shall only be modified in sync with libisofs and other software which
makes use of AAIP. Please mail change requests to mailing list
<libburn-hackers@pykix.org> or to the copyright holder in private.

View File

@ -11,7 +11,7 @@
To be included by aaip_0_2.c
Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2+
Copyright (c) 2009 - 2011 Thomas Schmitt, libburnia project, GPLv2+
*/
@ -28,6 +28,29 @@
#include <sys/stat.h>
/* ------------------------------ Inquiry --------------------------------- */
/* See also API iso_local_attr_support().
@param flag
Bitfield for control purposes
bit0= inquire availability of ACL
bit1= inquire availability of xattr
bit2 - bit7= Reserved for future types.
It is permissibile to set them to 1 already now.
bit8 and higher: reserved, submit 0
@return
Bitfield corresponding to flag. 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 --------------------------------- */
/* Obtain the ACL of the given file in long text form.
@ -89,8 +112,12 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
continue;
}
/* Extended Attribute */
if(!(flag & 4))
return(-6);
if(flag & 4)
continue;
if(!(flag & 8))
if(strncmp(names[i], "user.", 5))
continue;
return(-6);
}
if(flag & 2)
return(-6);

View File

@ -7,7 +7,7 @@
To be included by aaip_0_2.c
Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2
Copyright (c) 2009 - 2011 Thomas Schmitt, libburnia project, GPLv2+
*/
@ -24,15 +24,51 @@
#include <sys/stat.h>
#include <errno.h>
#ifndef Libisofs_with_aaip_acL
/* It seems ACL is fixely integrated in FreeBSD libc. There is no libacl. */
#define Libisofs_with_aaip_acL yes
#endif
#ifdef Libisofs_with_aaip_acL
#include <sys/acl.h>
#endif
#ifdef Libisofs_with_freebsd_extattR
#include <sys/extattr.h>
#endif
/* <<< 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 --------------------------------- */
@ -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
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)
bit1= use numeric ACL qualifiers rather than names
bit2= do not encode attributes other than ACL
bit3= -reserved-
bit3= do not ignore eventual non-user attributes
I.e. those which are not from name space
EXTATTR_NAMESPACE_USER
bit4= do not return trivial ACL that matches st_mode
bit15= free memory of names, value_lengths, values
@return >0 ok
<=0 error
-1= out of memory
-2= program error with prediction of result size
-3= error with conversion of name to uid or gid
*/
int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
size_t **value_lengths, char ***values, int flag)
{
int ret;
ssize_t i, num_names;
size_t a_acl_len= 0, acl_len= 0;
unsigned char *a_acl= NULL, *d_acl= NULL, *acl= NULL;
#ifdef Libisofs_with_aaip_acL
size_t a_acl_len= 0;
unsigned char *a_acl= NULL;
char *acl_text= NULL;
#endif
if(flag & (1 << 15)) { /* Free memory */
{ret= 1; goto ex;}
@ -211,25 +598,26 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
(*names)[*num_attrs]= strdup("");
if((*names)[*num_attrs] == NULL)
{ret= -1; goto ex;}
(*values)[*num_attrs]= (char *) acl;
(*value_lengths)[*num_attrs]= acl_len;
(*values)[*num_attrs]= (char *) a_acl;
a_acl= NULL;
(*value_lengths)[*num_attrs]= a_acl_len;
(*num_attrs)++;
}
#endif /* Libisofs_with_aaip_acL */
#endif /* ! Libisofs_with_aaip_acL */
ret= 1;
ex:;
#ifdef Libisofs_with_aaip_acL
if(a_acl != NULL)
free(a_acl);
if(d_acl != NULL)
free(d_acl);
if(acl_text != NULL)
aaip_get_acl_text("", &acl_text, 1 << 15); /* free */
#endif /* Libisofs_with_aaip_acL */
if(ret <= 0 || (flag & (1 << 15))) {
if(*names != NULL) {
for(i= 0; i < *num_attrs; i++)
for(i= 0; i < (ssize_t) *num_attrs; i++)
free((*names)[i]);
free(*names);
}
@ -238,18 +626,18 @@ ex:;
free(*value_lengths);
*value_lengths= NULL;
if(*values != NULL) {
for(i= 0; i < *num_attrs; i++)
for(i= 0; i < (ssize_t) *num_attrs; i++)
free((*values)[i]);
free(*values);
}
if(acl != NULL)
free(acl);
*values= NULL;
*num_attrs= 0;
}
return(ret);
}
#endif /* Libisofs_old_freebsd_acl_adapteR */
/* ------------------------------ Setters --------------------------------- */
@ -259,9 +647,14 @@ ex:;
@param text The input text (0 terminated, ACL long text form)
@param flag Bitfield for control purposes
bit0= set default ACL rather than access ACL
bit5= in case of symbolic link: manipulate link target
bit6= tolerate inappropriate presence or absence of
directory default ACL
@return > 0 ok
0 no suitable ACL manipulation adapter available
-1 failure of system ACL service (see errno)
-2 ACL support not enabled at compile time
-2 attempt to manipulate ACL of a symbolic link
without bit5 resp. with no suitable link target
*/
int aaip_set_acl_text(char *path, char *text, int flag)
{
@ -302,13 +695,200 @@ ex:
#else /* Libisofs_with_aaip_acL */
return(-2);
return(0);
#endif /* ! Libisofs_with_aaip_acL */
}
#ifndef Libisofs_old_freebsd_acl_adapteR
#ifdef Libisofs_with_freebsd_extattR
/*
@param flag Bitfield for control purposes
bit5= in case of symbolic link: manipulate link target
*/
static int aaip_extattr_delete_names(char *path, int attrnamespace,
char *list, ssize_t list_size, int flag)
{
int len;
char name[256];
ssize_t value_ret, i;
for(i= 0; i < list_size; i+= len + 1) {
len= *((unsigned char *) (list + i));
if(len > 0)
strncpy(name, list + i + 1, len);
name[len]= 0;
if(flag & 32)
value_ret= extattr_delete_file(path, attrnamespace, name);
else
value_ret= extattr_delete_file(path, attrnamespace, name);
if(value_ret == -1)
return(0);
}
return(1);
}
#endif /* Libisofs_with_freebsd_extattR */
/* Bring the given attributes and/or ACLs into effect with the given file.
@param flag Bitfield for control purposes
bit0= decode and set ACLs
bit1= first clear all existing attributes of the file
bit2= do not set attributes other than ACLs
bit3= do not ignore eventual non-user attributes.
I.e. those with a name which does not begin
by "user."
bit5= in case of symbolic link: manipulate link target
bit6= tolerate inappropriate presence or absence of
directory default ACL
@return 1 success
-1 error memory allocation
-2 error with decoding of ACL
-3 error with setting ACL
-4 error with setting attribute
-5 error with deleting attributes
-6 support of xattr not enabled at compile time
-7 support of ACL not enabled at compile time
-8 unsupported xattr namespace
ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other::
*/
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
size_t *value_lengths, char **values, int flag)
{
int ret, has_default_acl= 0;
size_t i, consumed, acl_text_fill, acl_idx= 0;
char *acl_text= NULL;
#ifdef Libisofs_with_freebsd_extattR
char *user_list= NULL, *sys_list= NULL, *namept;
ssize_t user_list_size= 0, sys_list_size= 0;
int attrnamespace;
#endif
#ifdef Libisofs_with_freebsd_extattR
if(flag & 2) { /* Delete all file attributes */
ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_USER,
&user_list, &user_list_size, flag & 32);
if(ret <= 0)
{ret= -1; goto ex;}
ret= aaip_extattr_delete_names(path, EXTATTR_NAMESPACE_USER,
user_list, user_list_size, flag & 32);
if(ret <= 0)
{ret= -5; goto ex;}
if(flag & 8) {
ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_SYSTEM,
&sys_list, &sys_list_size, flag & 32);
if(ret <= 0)
{ret= -5; goto ex;}
ret= aaip_extattr_delete_names(path, EXTATTR_NAMESPACE_SYSTEM,
sys_list, sys_list_size, flag & 32);
if(ret <= 0)
{ret= -5; goto ex;}
}
}
#endif /* Libisofs_with_freebsd_extattR */
for(i= 0; i < num_attrs; i++) {
if(names[i] == NULL || values[i] == NULL)
continue;
if(names[i][0] == 0) { /* ACLs */
if(flag & 1)
acl_idx= i + 1;
continue;
}
/* Extended Attribute */
if(flag & 4)
continue;
#ifdef Libisofs_with_freebsd_extattR
if(strncmp(names[i], "user.", 5) == 0) {
attrnamespace= EXTATTR_NAMESPACE_USER;
namept= names[i] + 5;
} else if(strncmp(names[i], "isofs.", 6) == 0 || !(flag & 8)) {
continue;
} else if(strncmp(names[i], "system.", 7) == 0) {
attrnamespace= EXTATTR_NAMESPACE_SYSTEM;
namept= names[i] + 7;
} else {
{ret= -8; goto ex;}
}
if(flag & 32)
ret= extattr_set_file(path, attrnamespace, namept,
values[i], value_lengths[i]);
else
ret= extattr_set_link(path, attrnamespace, namept,
values[i], value_lengths[i]);
if(ret == -1)
{ret= -4; goto ex;}
#else
if(strncmp(names[i], "user.", 5) == 0)
;
else if(strncmp(names[i], "isofs.", 6) == 0 || !(flag & 8))
continue;
{ret= -6; goto ex;}
#endif /* Libisofs_with_freebsd_extattR */
}
/* Decode ACLs */
if(acl_idx == 0)
{ret= 1; goto ex;}
i= acl_idx - 1;
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
&consumed, NULL, 0, &acl_text_fill, 1);
if(ret < -3)
goto ex;
if(ret <= 0)
{ret= -2; goto ex;}
acl_text= calloc(acl_text_fill, 1);
if(acl_text == NULL)
{ret= -1; goto ex;}
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
&consumed, acl_text, acl_text_fill, &acl_text_fill, 0);
if(ret < -3)
goto ex;
if(ret <= 0)
{ret= -2; goto ex;}
has_default_acl= (ret == 2);
#ifdef Libisofs_with_aaip_acL
ret= aaip_set_acl_text(path, acl_text, flag & (32 | 64));
if(ret <= 0)
{ret= -3; goto ex;}
#else
{ret= -7; goto ex;}
#endif
if(has_default_acl && !(flag & 64))
{ret= -3; goto ex;}
ret= 1;
ex:;
if(acl_text != NULL)
free(acl_text);
#ifdef Libisofs_with_freebsd_extattR
if(user_list != NULL)
free(user_list);
if(sys_list != NULL)
free(sys_list);
#endif /* Libisofs_with_freebsd_extattR */
return(ret);
}
#else /* ! Libisofs_old_freebsd_acl_adapteR */
/* Bring the given attributes and/or ACLs into effect with the given file.
Note: There are no Extended Attributes in FreeBSD. So only ACL get set.
@ -317,6 +897,9 @@ ex:
bit0= decode and set ACLs
( bit1= first clear all existing attributes of the file )
( bit2= do not set attributes other than ACLs )
( bit3= do not ignore eventual non-user attributes.
I.e. those with a name which does not begin
by "user." )
@return 1 success
-1 error memory allocation
-2 error with decoding of ACL
@ -338,6 +921,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
continue;
if(names[i][0] == 0) { /* Decode ACLs */
/* access ACL */
if(!(flag & 1))
continue;
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
&consumed, NULL, 0, &acl_text_fill, 1);
if(ret <= 0)
@ -379,8 +964,14 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
if(ret <= 0)
{ret= -3; goto ex;}
}
} else
} else {
if(flag & 4)
continue;
if(!(flag & 8))
if(strncmp(names[i], "user.", 5))
continue;
was_xattr= 1;
}
}
ret= 1;
if(was_xattr)
@ -393,4 +984,5 @@ ex:;
return(ret);
}
#endif /* Libisofs_old_freebsd_acl_adapteR */

View File

@ -7,7 +7,7 @@
To be included by aaip_0_2.c
Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2+
Copyright (c) 2009 - 2011 Thomas Schmitt, libburnia project, GPLv2+
*/
@ -34,6 +34,40 @@
#endif
/* ------------------------------ Inquiry --------------------------------- */
/* See also API iso_local_attr_support().
@param flag
Bitfield for control purposes
bit0= inquire availability of ACL
bit1= inquire availability of xattr
bit2 - bit7= Reserved for future types.
It is permissibile to set them to 1 already now.
bit8 and higher: reserved, submit 0
@return
Bitfield corresponding to flag. If bits are set, th
bit0= ACL adapter is enabled
bit1= xattr adapter is enabled
bit2 - bit7= Reserved for future types.
bit8 and higher: reserved, do not interpret these
*/
int aaip_local_attr_support(int flag)
{
int ret= 0;
#ifdef Libisofs_with_aaip_acL
if(flag & 1)
ret|= 1;
#endif
#ifdef Libisofs_with_aaip_xattR
if(flag & 2)
ret|= 2;
#endif
return(ret);
}
/* ------------------------------ Getters --------------------------------- */
/* Obtain the ACL of the given file in long text form.
@ -144,21 +178,24 @@ int aaip_get_acl_text(char *path, char **text, int flag)
bit15= free memory of names, value_lengths, values
@return >0 ok
<=0 error
-1= out of memory
-2= program error with prediction of result size
-3= error with conversion of name to uid or gid
*/
int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
size_t **value_lengths, char ***values, int flag)
{
int ret;
char *list= NULL;
ssize_t list_size= 0, i, num_names= 0;
unsigned char *acl= NULL;
char *a_acl_text= NULL, *d_acl_text= NULL;
ssize_t i, num_names= 0;
#ifdef Libisofs_with_aaip_acL
unsigned char *acl= NULL;
char *a_acl_text= NULL, *d_acl_text= NULL;
size_t acl_len= 0;
#endif
#ifdef Libisofs_with_aaip_xattR
ssize_t value_ret, retry= 0;
char *list= NULL;
ssize_t value_ret, retry= 0, list_size= 0;
#endif
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;
/* Set up arrays */
if(!(flag & 4)) { /* Get xattr names */
#ifdef Libisofs_with_aaip_xattR
if(!(flag & 4)) { /* Get xattr names */
if(flag & 32)
list_size= listxattr(path, list, 0);
else
list_size= llistxattr(path, list, 0);
if(list_size == -1)
{ret= -1; goto ex;}
list= calloc(list_size, 1);
if(list == NULL)
{ret= -1; goto ex;}
if(flag & 32)
list_size= listxattr(path, list, list_size);
else
list_size= llistxattr(path, list, list_size);
if(list_size == -1)
{ret= -1; goto ex;}
#else /* Libisofs_with_aaip_xattR */
list= strdup("");
#endif /* ! Libisofs_with_aaip_xattR */
if(list_size == -1) {
if(errno == ENOSYS) /* Function not implemented */
list_size= 0; /* Handle as if xattr was disabled at compile time */
else
{ret= -1; goto ex;}
}
if(list_size > 0) {
list= calloc(list_size, 1);
if(list == NULL)
{ret= -1; goto ex;}
if(flag & 32)
list_size= listxattr(path, list, list_size);
else
list_size= llistxattr(path, list, list_size);
if(list_size == -1)
{ret= -1; goto ex;}
}
for(i= 0; i < list_size; i+= strlen(list + i) + 1)
num_names++;
}
#endif /* ! Libisofs_with_aaip_xattR */
#ifdef Libisofs_with_aaip_acL
if(flag & 1)
num_names++;
#endif
if(num_names == 0)
@ -219,8 +259,11 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
(*values)[i]= NULL;
(*value_lengths)[i]= 0;
}
if(!(flag & 4)) {
for(i= 0; i < list_size && num_names > *num_attrs;
#ifdef Libisofs_with_aaip_xattR
if(!(flag & 4)) { /* Get xattr values */
for(i= 0; i < list_size && (size_t) num_names > *num_attrs;
i+= strlen(list + i) + 1) {
if(!(flag & 8))
if(strncmp(list + i, "user.", 5))
@ -229,12 +272,7 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
if((*names)[(*num_attrs) - 1] == NULL)
{ret= -1; goto ex;}
}
}
#ifdef Libisofs_with_aaip_xattR
if(!(flag & 4)) { /* Get xattr values */
for(i= 0; i < *num_attrs; i++) {
for(i= 0; (size_t) i < *num_attrs; i++) {
if(!(flag & 8))
if(strncmp((*names)[i], "user.", 5))
continue;
@ -291,15 +329,22 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
ret= 1;
ex:;
#ifdef Libisofs_with_aaip_acL
if(a_acl_text != NULL)
aaip_get_acl_text("", &a_acl_text, 1 << 15); /* free */
if(d_acl_text != NULL)
aaip_get_acl_text("", &d_acl_text, 1 << 15); /* free */
if(acl != NULL)
free(acl);
#endif
#ifdef Libisofs_with_aaip_xattR
if(list != NULL)
free(list);
#endif
if(ret <= 0 || (flag & (1 << 15))) {
if(*names != NULL) {
for(i= 0; i < *num_attrs; i++)
for(i= 0; (size_t) i < *num_attrs; i++)
free((*names)[i]);
free(*names);
}
@ -308,12 +353,10 @@ ex:;
free(*value_lengths);
*value_lengths= NULL;
if(*values != NULL) {
for(i= 0; i < *num_attrs; i++)
for(i= 0; (size_t) i < *num_attrs; i++)
free((*values)[i]);
free(*values);
}
if(acl != NULL)
free(acl);
*values= NULL;
*num_attrs= 0;
}
@ -384,7 +427,9 @@ ex:
bit3= do not ignore eventual non-user attributes.
I.e. those with a name which does not begin
by "user."
bit5= in case of symbolic link: manipulate link target
bit5= in case of symbolic link: manipulate link target
bit6= tolerate inappropriate presence or absense of
directory default ACL
@return 1 success
-1 error memory allocation
-2 error with decoding of ACL
@ -393,6 +438,8 @@ ex:
-5 error with deleting attributes
-6 support of xattr not enabled at compile time
-7 support of ACL not enabled at compile time
( -8 unsupported xattr namespace )
ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other::
*/
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
size_t *value_lengths, char **values, int flag)
@ -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;
char *acl_text= NULL, *list= NULL;
#ifdef Libisofs_with_aaip_xattR
size_t list_size= 0;
ssize_t list_size= 0;
#endif
#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);
if(list_size == -1)
{ret= -5; goto ex;}
for(i= 0; i < list_size; i+= strlen(list + i) + 1) {
for(i= 0; i < (size_t) list_size; i+= strlen(list + i) + 1) {
if(!(flag & 8))
if(strncmp(list + i, "user.", 5))
continue;
@ -447,7 +494,11 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
continue;
}
/* Extended Attribute */
if((flag & 1) && !(flag & 8))
if(flag & 4)
continue;
if(strncmp(names[i], "isofs.", 6) == 0)
continue;
if(!(flag & 8))
if(strncmp(names[i], "user.", 5))
continue;
@ -475,6 +526,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
/* "access" ACL */
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
&consumed, NULL, 0, &acl_text_fill, 1);
if(ret < -3)
goto ex;
if(ret <= 0)
{ret= -2; goto ex;}
acl_text= calloc(acl_text_fill, 1);
@ -482,6 +535,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
{ret= -1; goto ex;}
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
&consumed, acl_text, acl_text_fill, &acl_text_fill, 0);
if(ret < -3)
goto ex;
if(ret <= 0)
{ret= -2; goto ex;}
has_default_acl= (ret == 2);
@ -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),
value_lengths[i] - consumed, &h_consumed,
NULL, 0, &acl_text_fill, 1);
if(ret < -3)
goto ex;
if(ret <= 0)
{ret= -2; goto ex;}
acl_text= calloc(acl_text_fill, 1);
@ -508,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),
value_lengths[i] - consumed, &h_consumed,
acl_text, acl_text_fill, &acl_text_fill, 0);
if(ret < -3)
goto ex;
if(ret <= 0)
{ret= -2; goto ex;}
ret= aaip_set_acl_text(path, acl_text, 1 | (flag & 32));
if(ret <= 0)
{ret= -3; goto ex;}
} else {
if(!(flag & 64)) {
/* >>> ??? take offense from missing default ACL ?
??? does Linux demand a default ACL for directories with access ACL ?
*/;
}
}
ret= 1;
ex:;

View File

@ -4,10 +4,10 @@
Arbitrary Attribute Interchange Protocol , AAIP versions 0.2 , 1.0 , 2.0.
Implementation of encoding and decoding xattr and ACL.
See test/aaip_0_2.h
See libisofs/aaip_0_2.h
http://libburnia-project.org/wiki/AAIP
Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2+
Copyright (c) 2009 - 2011 Thomas Schmitt, libburnia project, GPLv2+
*/
@ -26,6 +26,7 @@
#include <sys/stat.h>
#include "libisofs.h"
#include "util.h"
/*
#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 *result_len, unsigned char **result, int flag)
{
size_t mem_size= 0, comp_size;
unsigned int number_of_fields, i, num_recs, total_recs= 0, ret;
size_t mem_size= 0, comp_size, ret;
unsigned int number_of_fields, i, num_recs;
/* Predict memory needs, number of SUSP fields and component records */
*result_len= 0;
@ -105,7 +106,6 @@ size_t aaip_encode(size_t num_attrs, char **names,
if(ret <= 0)
return(ret);
mem_size+= comp_size;
total_recs= num_recs;
}
number_of_fields= mem_size / 250 + !!(mem_size % 250);
mem_size+= number_of_fields * 5;
@ -158,9 +158,9 @@ size_t aaip_encode(size_t num_attrs, char **names,
ret= 0;
for(i= 0; i < *result_len; i+= ((unsigned char *) (*result))[i + 2])
ret++;
if(ret != number_of_fields) {
if(ret != (int) number_of_fields) {
fprintf(stderr, "aaip_encode(): WRONG NUMBER OF FIELDS %d <> %d\n",
number_of_fields, ret);
(int) number_of_fields, ret);
}
#endif /* Aaip_encode_debuG */
@ -187,7 +187,7 @@ static int aaip_encode_comp(unsigned char *result, size_t *result_fill,
aaip_encode_byte(result, result_fill, 0);
return(1);
}
for(rpt= data; rpt - data < l;) {
for(rpt= data; rpt - data < (ssize_t) l;) {
todo= l - (rpt - data) + (prefix > 0);
aaip_encode_byte(result, result_fill, (todo > 255));
if(todo > 255)
@ -198,7 +198,7 @@ static int aaip_encode_comp(unsigned char *result, size_t *result_fill,
todo--;
prefix= 0;
}
for(comp_start= rpt; rpt - comp_start < todo; rpt++)
for(comp_start= rpt; rpt - comp_start < (ssize_t) todo; rpt++)
aaip_encode_byte(result, result_fill, *((unsigned char *) rpt));
}
return(1);
@ -268,7 +268,11 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
bit3= check for completeness of list and eventually
fill up with entries deduced from st_mode
@return >0 means ok
0 means error
<=0 means error
-1= out of memory
-2= program error with prediction of result size
-3= error with conversion of name to uid or gid
ISO_AAIP_ACL_MULT_OBJ= multiple entries of user::, group::, other::
*/
int aaip_encode_acl(char *acl_text, mode_t st_mode,
size_t *result_len, unsigned char **result, int flag)
@ -279,8 +283,10 @@ int aaip_encode_acl(char *acl_text, mode_t st_mode,
*result_len= 0;
bytes= aaip_encode_acl_text(acl_text, st_mode,
(size_t) 0, NULL, 1 | (flag & (2 | 4 | 8)));
if(bytes < -2)
return(bytes);
if(bytes < 0)
return(0);
return((int) bytes - 1);
if(flag & 1) {
*result_len= bytes;
return(1);
@ -292,9 +298,13 @@ int aaip_encode_acl(char *acl_text, mode_t st_mode,
*result_len= bytes;
bytes= aaip_encode_acl_text(acl_text, st_mode, *result_len, *result,
(flag & (2 | 4 | 8)));
if(bytes != *result_len) {
if(bytes < -2)
return(bytes);
if(bytes < 0)
return((int) bytes - 1);
if((size_t) bytes != *result_len) {
*result_len= 0;
return(0);
return(-2);
}
return(1);
}
@ -341,26 +351,31 @@ static int aaip_make_aaip_perms(int r, int w, int x)
fill up with entries deduced from st_mode
@return >=0 number of bytes produced resp. counted
<0 means error
-1: result size overflow
-2: conversion errror with user name or group name
ISO_AAIP_ACL_MULT_OBJ: multiple entries of user::, group::, other::
*/
static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
size_t result_size, unsigned char *result, int flag)
{
char *rpt, *npt, *cpt;
int qualifier= 0, perms, type, i, qualifier_len= 0, num_recs, needed= 0;
int qualifier= 0, perms, type, i, qualifier_len= 0, num_recs, needed= 0, ret;
unsigned int has_u= 0, has_g= 0, has_o= 0, has_m= 0, is_trivial= 1;
uid_t uid, huid;
gid_t gid, hgid;
ssize_t count= 0;
struct passwd *pwd;
struct group *grp;
char name[1024];
char *name = NULL;
int name_size= 1024;
double num;
LIBISO_ALLOC_MEM(name, char, name_size);
if(flag & 4) {
/* set SWITCH_MARK to indicate a default ACL */;
if(!(flag & 1)) {
if(count >= result_size)
return(-1);
if((size_t) count >= result_size)
{ret= -1; goto ex;}
result[count]= (Aaip_SWITCH_MARK << 4) | Aaip_EXEC;
}
count++;
@ -384,9 +399,16 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
if(strncmp(rpt, "user:", 5) == 0) {
if(cpt - rpt == 5) {
type= Aaip_ACL_USER_OBJ;
if (has_u) {
/* >>> Duplicate u:: entry. */;
/* >>> ??? If it matches the previous one: ignore */
return((int) ISO_AAIP_ACL_MULT_OBJ);
}
has_u++;
} else {
if(cpt - (rpt + 5) >= sizeof(name))
if(cpt - (rpt + 5) >= name_size)
continue;
is_trivial= 0;
strncpy(name, rpt + 5, cpt - (rpt + 5));
@ -396,8 +418,10 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
pwd= getpwnam(name);
if(pwd == NULL) {
num= aaip_numeric_id(name, 0);
if(num <= 0)
goto user_by_name;
if(num <= 0) {
/* ACL_USER is not part of AAIP 2.0 */
{ret= -2; goto ex;}
}
uid= huid= num;
} else
uid= huid= pwd->pw_uid;
@ -405,31 +429,44 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
for(i= 0; huid != 0; i++)
huid= huid >> 8;
qualifier_len= i;
if(qualifier_len <= 0)
qualifier_len= 1;
for(i= 0; i < qualifier_len ; i++)
name[i]= uid >> (8 * (qualifier_len - i - 1));
} else {
user_by_name:;
type= Aaip_ACL_USER;
qualifier_len= strlen(name);
if(qualifier_len <= 0)
qualifier_len= 1;
}
qualifier= 1;
}
} else if(strncmp(rpt, "group:", 6) == 0) {
if(cpt - rpt == 6) {
type= Aaip_ACL_GROUP_OBJ;
if (has_g) {
/* >>> Duplicate g:: entry. */;
/* >>> ??? If it matches the previous one: ignore */
return((int) ISO_AAIP_ACL_MULT_OBJ);
}
has_g++;
} else {
if(cpt - (rpt + 6) >= sizeof(name))
if(cpt - (rpt + 6) >= name_size)
continue;
is_trivial= 0;
strncpy(name, rpt + 6, cpt - (rpt + 6));
name[cpt - (rpt + 6)]= 0;
if(flag & 2) {
type= Aaip_ACL_GROUP_N;
grp= getgrnam(name);
if(grp == NULL) {
num= aaip_numeric_id(name, 0);
if(num <= 0)
goto group_by_name;
if(num <= 0) {
/* ACL_GROUP is not part of AAIP 2.0 */
{ret= -2; goto ex;}
}
gid= hgid= num;
} else
gid= hgid= grp->gr_gid;
@ -437,18 +474,27 @@ user_by_name:;
for(i= 0; hgid != 0; i++)
hgid= hgid >> 8;
qualifier_len= i;
if(qualifier_len <= 0)
qualifier_len= 1;
for(i= 0; i < qualifier_len ; i++)
name[i]= gid >> (8 * (qualifier_len - i - 1));
} else {
group_by_name:;
type= Aaip_ACL_GROUP;
qualifier_len= strlen(name);
if(qualifier_len <= 0)
qualifier_len= 1;
}
qualifier= 1;
}
} else if(strncmp(rpt, "other:", 6) == 0) {
type= Aaip_ACL_OTHER;
if (has_o) {
/* >>> Duplicate o:: entry. */;
/* >>> ??? If it matches the previous one: ignore */
return((int) ISO_AAIP_ACL_MULT_OBJ);
}
has_o++;
} else if(strncmp(rpt, "mask:", 5) == 0) {
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');
if(!(flag & 1)) {
if(count >= result_size)
return(-1);
if((size_t) count >= result_size)
{ret= -1; goto ex;}
result[count]= perms | ((!!qualifier) << 3) | (type << 4);
}
count++;
@ -470,8 +516,8 @@ group_by_name:;
if(qualifier) {
num_recs= (qualifier_len / 127) + !!(qualifier_len % 127);
if(!(flag & 1)) {
if(count + 1 > result_size)
return(-1);
if((size_t) (count + 1) > result_size)
{ret= -1; goto ex;}
for(i= 0; i < num_recs; i++) {
if(i < num_recs - 1)
result[count++]= 255;
@ -480,8 +526,8 @@ group_by_name:;
if(result[count - 1] == 0)
result[count - 1]= 127;
}
if(count + (result[count - 1] & 127) > result_size)
return(-1);
if((size_t) (count + (result[count - 1] & 127)) > result_size)
{ret= -1; goto ex;}
memcpy(result + count, name + i * 127, result[count - 1] & 127);
count+= result[count - 1] & 127;
}
@ -495,8 +541,8 @@ group_by_name:;
if(flag & 1)
count+= needed;
else {
if(count + needed > result_size)
return(-1);
if((size_t) (count + needed) > result_size)
{ret= -1; goto ex;}
}
}
if ((flag & 8) && needed > 0 && !(flag & 1)) {
@ -521,7 +567,10 @@ group_by_name:;
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;
todo= *num_data;
if(todo > aaip->aa_missing)
if(todo > (size_t) aaip->aa_missing)
todo= aaip->aa_missing;
if(todo >= aaip->rec_head_missing)
if(todo >= (size_t) aaip->rec_head_missing)
todo= aaip->rec_head_missing;
if(!aaip->recs_invalid)
aaip_push_to_recs(aaip, *data, todo, 0);
@ -1144,9 +1193,9 @@ static int aaip_consume_rec_data(struct aaip_state *aaip,
size_t todo;
todo= *num_data;
if(todo > aaip->aa_missing)
if(todo > (size_t) aaip->aa_missing)
todo= aaip->aa_missing;
if(todo > aaip->rec_missing)
if(todo > (size_t) aaip->rec_missing)
todo= aaip->rec_missing;
if(!aaip->recs_invalid)
aaip_push_to_recs(aaip, *data, todo, 1);
@ -1178,7 +1227,7 @@ static int aaip_consume_aa_head(struct aaip_state *aaip,
unsigned char aa_head[5];
todo= *num_data;
if(todo >= aaip->aa_head_missing)
if(todo >= (size_t) aaip->aa_head_missing)
todo= aaip->aa_head_missing;
aaip_push_to_recs(aaip, *data, todo, 0);
aaip->aa_head_missing-= todo;
@ -1225,7 +1274,7 @@ static int aaip_consume_aa_data(struct aaip_state *aaip,
aaip_push_to_recs(aaip, zero_char, 1, 0);
} else {
/* fill in missing btes */
for(i= 0; i < aaip->rec_missing; i++)
for(i= 0; (int) i < aaip->rec_missing; i++)
aaip_push_to_recs(aaip, zero_char, 1, 1);
}
aaip->rec_head_missing= 2;
@ -1696,7 +1745,7 @@ int aaip_decode_attrs(struct aaip_state **handle,
unsigned char *data, size_t num_data, size_t *consumed,
int flag)
{
int ret, was_non_aa= 0;
int ret;
struct aaip_state *aaip;
size_t h_num, *h_lengths, i, new_mem, pair_consumed= 0;
char **h_names, **h_values, *hpt;
@ -1785,7 +1834,6 @@ int aaip_decode_attrs(struct aaip_state **handle,
return(ret);
} else if(ret == -1) { /* non-AAIP field detected */
was_non_aa= 1;
if(pair_consumed <= 0)
return(-4); /* interpretation did not advance */
@ -1968,14 +2016,16 @@ static int aaip_read_qualifier(unsigned char *data, size_t num_data,
char *name, size_t name_size, size_t *name_fill,
int flag)
{
int is_done= 0, rec_len= 0;
int is_done= 0;
size_t rec_len= 0;
unsigned char *rpt;
*name_fill= 0;
for(rpt= data; !is_done; rpt+= rec_len) {
rec_len= (*rpt) & 127;
is_done= !((*rpt) & 128);
if(*name_fill + rec_len >= name_size || rpt + 1 + rec_len - data > num_data)
if(*name_fill + rec_len >= name_size ||
(size_t) (rpt + 1 + rec_len - data) > num_data)
return(-1);
memcpy(name + *name_fill, rpt + 1, rec_len);
rpt+= 1 + rec_len;
@ -2013,20 +2063,21 @@ int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
size_t *acl_text_fill, int flag)
{
unsigned char *rpt;
char perm_text[4], *wpt, name[1024];
int type, qualifier= 0, perm, ret, i, cnt;
size_t w_size, name_fill= 0;
char perm_text[4], *wpt, *name= NULL;
int type, qualifier= 0, perm, ret, cnt, name_size= 1024;
size_t w_size, name_fill= 0, i;
uid_t uid;
gid_t gid;
struct passwd *pwd;
struct group *grp;
LIBISO_ALLOC_MEM(name, char, name_size);
cnt= flag & 1;
*consumed= 0;
wpt= acl_text;
w_size= acl_text_size;
*acl_text_fill= 0;
for(rpt= data; rpt - data < num_data; ) {
for(rpt= data; (size_t) (rpt - data) < num_data; ) {
perm= *rpt;
strcpy(perm_text, "---");
if(perm & Aaip_READ)
@ -2038,14 +2089,14 @@ int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
type= (*rpt) >> 4;
if(type == Aaip_FUTURE_VERSION) /* indicate to caller: version mismatch */
return(-3);
{ret = -3; goto ex;}
qualifier= !!((*rpt) & 8);
if(qualifier) {
ret= aaip_read_qualifier(rpt + 1, num_data - (rpt + 1 - data),
name, sizeof(name), &name_fill, 0);
name, name_size, &name_fill, 0);
if(ret <= 0)
return(-1);
{ret = -1; goto ex;}
}
/* Advance read pointer */
@ -2086,7 +2137,7 @@ int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
pwd= getpwuid(uid);
if(pwd == NULL)
sprintf(name, "%.f", (double) uid);
else if(strlen(pwd->pw_name) >= sizeof(name))
else if(strlen(pwd->pw_name) >= (size_t) name_size)
sprintf(name, "%.f", (double) uid);
else
strcpy(name, pwd->pw_name);
@ -2100,7 +2151,7 @@ int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
grp= getgrgid(gid);
if(grp == NULL)
sprintf(name, "%.f", (double) gid);
else if(strlen(grp->gr_name) >= sizeof(name))
else if(strlen(grp->gr_name) >= (size_t) name_size)
sprintf(name, "%.f", (double) gid);
else
strcpy(name, grp->gr_name);
@ -2108,15 +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);
} else {
/* indicate to caller: unknown type */
return(-4);
{ret = -4; goto ex;}
}
if(ret <= 0)
return(-2);
{ret = -2; goto ex;}
}
ret= 1;
ex:;
*acl_text_fill= w_size;
if(flag & 1)
*acl_text_fill= w_size + 1;
(*acl_text_fill)++;
LIBISO_FREE_MEM(name);
return(ret);
}
@ -2133,6 +2186,13 @@ ex:;
#include "aaip-os-linux.c"
/* August 2011: aaip-os-linux.c would also work for GNU/Hurd : ifdef __GNU__
Libraries and headers are present on Debian GNU/Hurd but there is no
ACL or xattr support in the filesystems yet.
Further, llistxattr() produces ENOSYS "Function not implemented".
So it makes few sense to enable it here.
*/
#else
#include "aaip-os-dummy.c"

View File

@ -56,7 +56,11 @@ size_t aaip_encode(size_t num_attrs, char **names,
bit3= check for completeness of list and eventually
fill up with entries deduced from st_mode
@return >0 means ok
0 means error
<=0 means error
-1= out of memory
-2= program error with prediction of result size
-3= error with conversion of name to uid or gid
ISO_AAIP_ACL_MULT_OBJ= multiple entries of user::, group::, other::
*/
int aaip_encode_acl(char *acl_text, mode_t st_mode,
size_t *result_len, unsigned char **result, int flag);
@ -80,7 +84,7 @@ int aaip_encode_acl(char *acl_text, mode_t st_mode,
bit3= check for completeness of list and eventually
fill up with entries deduced from st_mode
@return >0 means ok
0 means error
<=0 means error, see aaip_encode_acl
*/
int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text, mode_t st_mode,
size_t *result_len, unsigned char **result, int flag);
@ -145,6 +149,24 @@ int aaip_add_acl_st_mode(char *acl_text, mode_t st_mode, int flag);
/* ------ OS interface ------ */
/* See also API iso_local_attr_support().
@param flag
Bitfield for control purposes
bit0= inquire availability of ACL
bit1= inquire availability of xattr
bit2 - bit7= Reserved for future types.
It is permissibile to set them to 1 already now.
bit8 and higher: reserved, submit 0
@return
Bitfield corresponding to flag. If bits are set, th
bit0= ACL adapter is enabled
bit1= xattr adapter is enabled
bit2 - bit7= Reserved for future types.
bit8 and higher: reserved, do not interpret these
*/
int aaip_local_attr_support(int flag);
/* Obtain the ACL of the given file in long text form.
@param path Path to the file
@param text Will hold the result. This is a managed object which
@ -478,6 +500,8 @@ int aaip_set_acl_text(char *path, char *text, int flag);
-5 error with deleting attributes
-6 support of xattr not enabled at compile time
-7 support of ACL not enabled at compile time
-8 unsupported xattr namespace
ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other::
*/
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
size_t *value_lengths, char **values, int flag);

View File

@ -150,7 +150,7 @@ void iso_ring_buffer_free(IsoRingBuffer *buf)
int iso_ring_buffer_write(IsoRingBuffer *buf, uint8_t *data, size_t count)
{
size_t len;
int bytes_write = 0;
size_t bytes_write = 0;
if (buf == NULL || data == NULL) {
return ISO_NULL_POINTER;
@ -206,7 +206,7 @@ int iso_ring_buffer_write(IsoRingBuffer *buf, uint8_t *data, size_t count)
int iso_ring_buffer_read(IsoRingBuffer *buf, uint8_t *dest, size_t count)
{
size_t len;
int bytes_read = 0;
size_t bytes_read = 0;
if (buf == NULL || dest == NULL) {
return ISO_NULL_POINTER;

View File

@ -11,7 +11,14 @@
#define LIBISO_BUFFER_H_
#include <stdlib.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#endif
#define BLOCK_SIZE 2048

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt
* Copyright (c) 2009 - 2011 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -20,16 +20,13 @@
#include "fsource.h"
#include "image.h"
#include "aaip_0_2.h"
#include "util.h"
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <stdio.h>
#ifndef PATH_MAX
#define PATH_MAX Libisofs_default_path_maX
#endif
void iso_node_builder_ref(IsoNodeBuilder *builder)
@ -75,6 +72,8 @@ int default_create_file(IsoNodeBuilder *builder, IsoImage *image,
iso_file_source_ref(src);
name = iso_file_source_get_name(src);
if (strlen(name) > LIBISOFS_NODE_NAME_MAX)
name[LIBISOFS_NODE_NAME_MAX] = 0;
ret = iso_node_new_file(name, stream, &node);
if (ret < 0) {
iso_stream_unref(stream);
@ -106,9 +105,11 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
char *name;
unsigned char *aa_string = NULL;
char *a_text = NULL, *d_text = NULL;
char *dest = NULL;
IsoSymlink *link;
if (builder == NULL || src == NULL || node == NULL) {
return ISO_NULL_POINTER;
{ret = ISO_NULL_POINTER; goto ex;}
}
/* get info about source */
@ -118,10 +119,12 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
ret = iso_file_source_lstat(src, &info);
}
if (ret < 0) {
return ret;
goto ex;
}
name = iso_file_source_get_name(src);
if (strlen(name) > LIBISOFS_NODE_NAME_MAX)
name[LIBISOFS_NODE_NAME_MAX] = 0;
fs = iso_file_source_get_filesystem(src);
new = NULL;
@ -157,10 +160,8 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
case S_IFLNK:
{
/* source is a symbolic link */
char dest[PATH_MAX];
IsoSymlink *link;
ret = iso_file_source_readlink(src, dest, PATH_MAX);
LIBISO_ALLOC_MEM(dest, char, LIBISOFS_NODE_PATH_MAX);
ret = iso_file_source_readlink(src, dest, LIBISOFS_NODE_PATH_MAX);
if (ret < 0) {
break;
}
@ -198,7 +199,7 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
if (ret < 0) {
free(name);
return ret;
goto ex;
}
/* fill fields */
@ -233,19 +234,25 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
if (ret == 1 && aa_string != NULL) {
ret = iso_node_add_xinfo(new, aaip_xinfo_func, aa_string);
if (ret < 0)
return ret;
goto ex;
} else if(aa_string != NULL) {
free(aa_string);
}
*node = new;
return ISO_SUCCESS;
ret = ISO_SUCCESS;
ex:;
LIBISO_FREE_MEM(dest);
return ret;
}
static
void default_free(IsoNodeBuilder *builder)
{
/* The .free() method of IsoNodeBuilder shall free private data but not
the builder itself. The latter is done in iso_node_builder_unref().
*/
return;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt
* Copyright (c) 2009 - 2012 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -15,7 +15,14 @@
#include "util.h"
#include "buffer.h"
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#endif
#include <pthread.h>
#define BLOCK_SIZE 2048
@ -52,6 +59,34 @@
#define ISO_DISC_LABEL_SIZE 129
/* The maximum lenght of an specs violating ECMA-119 file identifier.
The theoretical limit is 254 - 34 - 28 (len of SUSP CE entry) = 192
Currently the practical limit is 254 - 34 - 96 (non-CE RR entries) - 28 (CE)
*/
#ifdef Libisofs_with_rrip_rR
#define ISO_UNTRANSLATED_NAMES_MAX 92
#else
#define ISO_UNTRANSLATED_NAMES_MAX 96
#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.
*/
@ -65,6 +100,8 @@ struct iso_write_opts {
unsigned int rockridge :1;
unsigned int joliet :1;
unsigned int iso1999 :1;
unsigned int hfsplus :1;
unsigned int fat :1;
unsigned int aaip :1; /* whether to write eventual ACL and EAs */
@ -76,6 +113,14 @@ struct iso_write_opts {
* but it is supposed to work on most moderns systems. Use with caution.
*/
/**
* Convert directory names for ECMA-119 the same way as other file names
* but do not force dots or add version numbers.
* This violates ECMA-119 by allowing one "." and especially ISO level 1
* by allowing DOS style 8.3 names rather than only 8 characters.
*/
unsigned int allow_dir_id_ext :1;
/**
* Omit the version number (";1") at the end of the ISO-9660 identifiers.
* Version numbers are usually not used.
@ -123,6 +168,13 @@ struct iso_write_opts {
*/
unsigned int allow_full_ascii :1;
/**
* If not allow_full_ascii is set: allow all 7 bit characters that would
* be allowed by allow_full_ascii. But still map lowercase to uppercase if
* not allow_lowercase is set to 1.
*/
unsigned int allow_7bit_ascii :1;
/**
* Allow all characters to be part of Volume and Volset identifiers on
* the Primary Volume Descriptor. This breaks ISO-9660 contraints, but
@ -135,6 +187,11 @@ struct iso_write_opts {
*/
unsigned int joliet_longer_paths :1;
/**
* Allow Joliet names up to 103 characters rather than 64.
*/
unsigned int joliet_long_names :1;
/**
* Write Rock Ridge info as of specification RRIP-1.10 rather than
* RRIP-1.12: signature "RRIP_1991A" rather than "IEEE_1282",
@ -171,8 +228,27 @@ struct iso_write_opts {
* to expect that we do have a creation timestamp with the source.
* mkisofs writes mtimes and the result seems more suitable if mounted
* without Rock Ridge support.)
* bit0= ECMA-119, bit1= Joliet, bit2= ISO 9660:1999
*/
unsigned int dir_rec_mtime :1;
unsigned int dir_rec_mtime :3;
/**
* This describes the directory where to store Rock Ridge relocated
* directories.
* If not relaxation "allow_deep_paths" is in effect, it is necessary to
* relocate directories so that no ECMA-119 file path has more than
* 8 components. For Rock Ridge the relocated directories are linked forth
* and back to a placeholder at their original position in path level 8
* (entries CL and PL). Directories marked by entry RE are to be considered
* artefacts of relocation and shall not be read into a Rock Ridge tree.
* For plain ECMA-119, the relocation directory is just a normal directory
* which contains normal files and directories.
*/
char *rr_reloc_dir; /* IsoNode name in root directory */
int rr_reloc_flags; /* bit0= mark auto-created rr_reloc_dir by RE
bit1= directory was auto-created
(cannot be set via API)
*/
/**
* Compute MD5 checksum for the whole session and record it as index 0 of
@ -218,6 +294,26 @@ struct iso_write_opts {
uid_t uid; /** uid to use when replace_uid == 2. */
gid_t gid; /** gid to use when replace_gid == 2. */
/**
* See API call iso_write_opts_set_old_empty().
*/
unsigned int old_empty :1;
/**
* Extra Caution: This option breaks any assumptions about names that
* are supported by ECMA-119 specifications.
* Omit any translation which would make a file name compliant to the
* ECMA-119 rules. This includes and exceeds omit_version_numbers,
* max_37_char_filenames, no_force_dots bit0, allow_lowercase.
* The maximum name length is given by this variable.
* There is a length limit of ISO_UNTRANSLATED_NAMES_MAX characters,
* because ECMA-119 allows 254 byte in a directory record, some
* of them are occupied by ECMA-119, some more are needed for SUSP CE,
* and some are fixely occupied by libisofs Rock Ridge code.
* The default value 0 disables this feature.
*/
unsigned int untranslated_name_len;
/**
* 0 to use IsoNode timestamps, 1 to use recording time, 2 to use
* values from timestamp field. This has only meaning if RR extensions
@ -356,6 +452,16 @@ struct iso_write_opts {
*/
uint32_t tail_blocks;
/* Eventual disk file path of a PreP partition which shall be prepended
to HFS+/FAT and IsoFileSrc areas and marked by an MBR partition entry.
*/
char *prep_partition;
/* 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
after the ISO image and described by partiton table entries in a MBR
*/
@ -365,12 +471,27 @@ struct iso_write_opts {
/* Eventual name of the non-ISO aspect of the image. E.g. SUN ASCII label.
*/
char ascii_disc_label[ISO_DISC_LABEL_SIZE];
/* HFS+ image serial number.
* 00...00 means that it shall be generated by libisofs.
*/
uint8_t hfsp_serial_number[8];
/* Allocation block size of HFS+ : 0= auto , 512, or 2048
*/
int hfsp_block_size;
/* Block size of and in APM : 0= auto , 512, or 2048
*/
int apm_block_size;
};
typedef struct ecma119_image Ecma119Image;
typedef struct ecma119_node Ecma119Node;
typedef struct joliet_node JolietNode;
typedef struct iso1999_node Iso1999Node;
typedef struct hfsplus_node HFSPlusNode;
typedef struct Iso_File_Src IsoFileSrc;
typedef struct Iso_Image_Writer IsoImageWriter;
@ -390,6 +511,8 @@ struct ecma119_image
unsigned int joliet :1;
unsigned int eltorito :1;
unsigned int iso1999 :1;
unsigned int hfsplus :1;
unsigned int fat :1;
unsigned int hardlinks:1; /* see iso_write_opts_set_hardlinks() */
@ -399,6 +522,7 @@ struct ecma119_image
unsigned int always_gmt :1;
/* relaxed constraints */
unsigned int allow_dir_id_ext :1;
unsigned int omit_version_numbers :2;
unsigned int allow_deep_paths :1;
unsigned int allow_longer_paths :1;
@ -406,12 +530,16 @@ struct ecma119_image
unsigned int no_force_dots :2;
unsigned int allow_lowercase :1;
unsigned int allow_full_ascii :1;
unsigned int allow_7bit_ascii :1;
unsigned int relaxed_vol_atts : 1;
/** Allow paths on Joliet tree to be larger than 240 bytes */
unsigned int joliet_longer_paths :1;
/** Allow Joliet names up to 103 characters rather than 64 */
unsigned int joliet_long_names :1;
/** Write old fashioned RRIP-1.10 rather than RRIP-1.12 */
unsigned int rrip_version_1_10 :1;
@ -421,8 +549,16 @@ struct ecma119_image
/* Write AAIP as extension according to SUSP 1.10 rather than SUSP 1.12. */
unsigned int aaip_susp_1_10 :1;
/* Store in ECMA-119 timestamp mtime of source */
unsigned int dir_rec_mtime :1;
/* Store in ECMA-119, Joliet, ISO 9660:1999 timestamp the mtime of source
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_file_checksums :2;
@ -443,6 +579,9 @@ struct ecma119_image
mode_t dir_mode;
time_t timestamp;
unsigned int old_empty :1;
unsigned int untranslated_name_len;
/**
* if sort files or not. Sorting is based of the weight of each file
*/
@ -451,6 +590,11 @@ struct ecma119_image
char *input_charset;
char *output_charset;
/* See iso_write_opts and iso_write_opts_set_hfsp_serial_number().
* 00...00 means that it shall be generated by libisofs.
*/
uint8_t hfsp_serial_number[8];
unsigned int appendable : 1;
uint32_t ms_block; /**< start block for a ms image */
time_t now; /**< Time at which writing began. */
@ -475,6 +619,12 @@ struct ecma119_image
*/
uint32_t empty_file_block;
/*
* The calculated block address after ECMA-119 tree and eventual
* tree checksum tag.
*/
uint32_t tree_end_block;
/*
* number of dirs in ECMA-119 tree, computed together with dir position,
* and needed for path table computation in a efficient way
@ -493,6 +643,29 @@ struct ecma119_image
uint32_t joliet_l_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
*/
@ -519,19 +692,27 @@ struct ecma119_image
*/
char *system_area_data;
/*
* bit0= Only with PC-BIOS DOS MBR
* bit0= Only with DOS MBR
* Make bytes 446 - 512 of the system area a partition
* table which reserves partition 1 from byte 63*512 to the
* end of the ISO image. Assumed are 63 secs/hed, 255 head/cyl.
* (GRUB protective msdos label.)
* This works with and without system_area_data.
* bit1= Only with PC-BIOS DOS MBR
* bit1= Only with DOS MBR
* Apply isohybrid MBR patching to the system area.
* This works only with system_area_data plus ISOLINUX boot image
* and only if not bit0 is set.
* bit2-7= System area type
* 0= DOS MBR
* 1= MIPS Big Endian Volume Header
* 2= DEC Boot Block for MIPS Little Endian
* 3= SUN Disk Label for SUN SPARC
* bit8-9= Only with DOS MBR
* Cylinder alignment mode eventually pads the image to make it
* end at a cylinder boundary.
* 0 = auto (align if bit1)
* 1 = always align to cylinder boundary
* 2 = never align to cylinder boundary
*/
int system_area_options;
@ -644,6 +825,84 @@ struct ecma119_image
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]
@ -774,5 +1033,11 @@ struct ecma119_vol_desc_terminator
uint8_t reserved BP(8, 2048);
};
void ecma119_set_voldescr_times(IsoImageWriter *writer,
struct ecma119_pri_vol_desc *vol);
/* Copies a data file into the ISO image output stream */
int iso_write_partition_file(Ecma119Image *target, char *path,
uint32_t prepad, uint32_t blocks, int flag);
#endif /*LIBISO_ECMA119_H_*/

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt
* Copyright (c) 2009 - 2012 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -12,6 +12,9 @@
#include "../config.h"
#endif
/* Must be before ecma119.h because of eventual Libisofs_with_rrip_rR */
#include "libisofs.h"
#include "ecma119_tree.h"
#include "ecma119.h"
#include "node.h"
@ -29,7 +32,7 @@
static
int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name)
{
int ret, relaxed;
int ret, relaxed, free_ascii_name= 0, force_dots = 0;
char *ascii_name;
char *isoname= NULL;
@ -38,9 +41,16 @@ int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name)
return ISO_SUCCESS;
}
ret = str2ascii(img->input_charset, iso->name, &ascii_name);
if (img->untranslated_name_len > 0) {
ascii_name = iso->name;
ret = 1;
} else {
ret = str2ascii(img->input_charset, iso->name, &ascii_name);
free_ascii_name = 1;
}
if (ret < 0) {
iso_msg_submit(img->image->id, ret, 0, "Can't convert %s", iso->name);
iso_msg_submit(img->image->id, ret, 0,
"Cannot convert name '%s' to ASCII", iso->name);
return ret;
}
@ -49,43 +59,86 @@ int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name)
} else {
relaxed = (int)img->allow_lowercase;
}
if (iso->type == LIBISO_DIR) {
if (img->max_37_char_filenames) {
if (img->allow_7bit_ascii)
relaxed |= 4;
if (iso->type == LIBISO_DIR && !(img->allow_dir_id_ext)) {
if (img->untranslated_name_len > 0) {
if (strlen(ascii_name) > img->untranslated_name_len) {
needs_transl:;
iso_msg_submit(img->image->id, ISO_NAME_NEEDS_TRANSL, 0,
"File name too long (%d > %d) for untranslated recording: '%s'",
strlen(ascii_name), img->untranslated_name_len,
ascii_name);
return ISO_NAME_NEEDS_TRANSL;
}
isoname = strdup(ascii_name);
} else if (img->max_37_char_filenames) {
isoname = iso_r_dirid(ascii_name, 37, relaxed);
} else if (img->iso_level == 1) {
#ifdef Libisofs_old_ecma119_nameS
if (relaxed) {
isoname = iso_r_dirid(ascii_name, 8, relaxed);
} else {
isoname = iso_1_dirid(ascii_name);
isoname = iso_1_dirid(ascii_name, 0);
}
#else /* Libisofs_old_ecma119_nameS */
isoname = iso_1_dirid(ascii_name, relaxed);
#endif /* ! Libisofs_old_ecma119_nameS */
} else {
if (relaxed) {
isoname = iso_r_dirid(ascii_name, 8, relaxed);
isoname = iso_r_dirid(ascii_name, 31, relaxed);
} else {
isoname = iso_2_dirid(ascii_name);
}
}
} else {
if (img->max_37_char_filenames) {
isoname = iso_r_fileid(ascii_name, 36, relaxed,
(img->no_force_dots & 1) ? 0 : 1);
force_dots = !((img->no_force_dots & 1) || iso->type == LIBISO_DIR);
if (img->untranslated_name_len > 0) {
if (strlen(ascii_name) > img->untranslated_name_len)
goto needs_transl;
isoname = strdup(ascii_name);
} else if (img->max_37_char_filenames) {
isoname = iso_r_fileid(ascii_name, 36, relaxed, force_dots);
} else if (img->iso_level == 1) {
#ifdef Libisofs_old_ecma119_nameS
int max_len;
if (relaxed) {
isoname = iso_r_fileid(ascii_name, 11, relaxed,
(img->no_force_dots & 1) ? 0 : 1);
if (strchr(ascii_name, '.') == NULL)
max_len = 8;
else
max_len = 11;
isoname = iso_r_fileid(ascii_name, max_len, relaxed,
force_dots);
} else {
isoname = iso_1_fileid(ascii_name);
isoname = iso_1_fileid(ascii_name, 0, force_dots);
}
#else /* Libisofs_old_ecma119_nameS */
isoname = iso_1_fileid(ascii_name, relaxed, force_dots);
#endif /* ! Libisofs_old_ecma119_nameS */
} else {
if (relaxed) {
isoname = iso_r_fileid(ascii_name, 30, relaxed,
(img->no_force_dots & 1) ? 0 : 1);
if (relaxed || !force_dots) {
isoname = iso_r_fileid(ascii_name, 30, relaxed, force_dots);
} else {
isoname = iso_2_fileid(ascii_name);
}
}
}
free(ascii_name);
if (free_ascii_name)
free(ascii_name);
if (isoname != NULL) {
*name = isoname;
return ISO_SUCCESS;
@ -98,6 +151,15 @@ int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name)
}
}
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
int create_ecma119_node(Ecma119Image *img, IsoNode *iso, Ecma119Node **node)
{
@ -271,7 +333,7 @@ void ecma119_node_free(Ecma119Node *node)
return;
}
if (node->type == ECMA119_DIR) {
int i;
size_t i;
for (i = 0; i < node->info.dir->nchildren; i++) {
ecma119_node_free(node->info.dir->children[i]);
}
@ -406,6 +468,15 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree,
if (ret < 0) {
goto ex;
}
if (depth == 1) { /* root is default */
image->rr_reloc_node = node;
} else if (depth == 2) {
/* Directories in root may be used as relocation dir */
if (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;
pos = dir->children;
@ -416,8 +487,6 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree,
!!hidden);
if (cret < 0) {
/* error */
if (!hidden)
ecma119_node_free(node);
ret = cret;
break;
} else if (cret == ISO_SUCCESS && !hidden) {
@ -537,6 +606,18 @@ int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
continue;
}
if (img->untranslated_name_len) {
/* This should not happen because no two IsoNode names should be
identical and only unaltered IsoNode names should be seen here.
Thus the Ema119Node names should be unique.
*/
iso_msg_submit(img->image->id, ISO_NAME_NEEDS_TRANSL, 0,
"ECMA-119 file name collision: '%s'",
children[i]->iso_name);
ret = ISO_NAME_NEEDS_TRANSL;
goto mangle_cleanup;
}
/*
* A max of 7 characters is good enought, it allows handling up to
* 9,999,999 files with same name. We can increment this to
@ -553,10 +634,11 @@ int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
/* compute name and extension */
dot = strrchr(full_name, '.');
if (dot != NULL && children[i]->type != ECMA119_DIR) {
if (dot != NULL &&
(children[i]->type != ECMA119_DIR || img->allow_dir_id_ext)) {
/*
* File (not dir) with extension
* File (normally not dir) with extension
* Note that we don't need to check for placeholders, as
* tree reparent happens later, so no placeholders can be
* here at this time.
@ -596,15 +678,15 @@ int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
name[max] = '\0';
}
} else {
/* Directory, or file without extension */
/* Directory (normally), or file without extension */
if (children[i]->type == ECMA119_DIR) {
max = max_dir_len - digits;
dot = NULL; /* dots have no meaning in dirs */
dot = NULL; /* dots (normally) have no meaning in dirs */
} else {
max = max_file_len - digits;
}
name = full_name;
if (max < strlen(name)) {
if ((size_t) max < strlen(name)) {
name[max] = '\0';
}
/* let ext be an empty string */
@ -639,8 +721,11 @@ int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
ret = ISO_OUT_OF_MEM;
goto mangle_cleanup;
}
#ifdef Libisofs_extra_verbose_debuG
iso_msg_debug(img->image->id, "\"%s\" renamed to \"%s\"",
children[k]->iso_name, new);
#endif
iso_htable_remove_ptr(table, children[k]->iso_name, NULL);
free(children[k]->iso_name);
@ -711,12 +796,14 @@ int mangle_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
}
static
int mangle_tree(Ecma119Image *img, int recurse)
int mangle_tree(Ecma119Image *img, Ecma119Node *dir, int recurse)
{
int max_file, max_dir;
Ecma119Node *root;
if (img->max_37_char_filenames) {
if (img->untranslated_name_len > 0) {
max_file = max_dir = img->untranslated_name_len;
} else if (img->max_37_char_filenames) {
max_file = max_dir = 37;
} else if (img->iso_level == 1) {
max_file = 12; /* 8 + 3 + 1 */
@ -724,7 +811,9 @@ int mangle_tree(Ecma119Image *img, int recurse)
} else {
max_file = max_dir = 31;
}
if (img->eff_partition_offset > 0) {
if (dir != NULL) {
root = dir;
} else if (img->eff_partition_offset > 0) {
root = img->partition_root;
} else {
root = img->root;
@ -846,41 +935,61 @@ int reparent(Ecma119Node *child, Ecma119Node *parent)
* 1 success, < 0 error
*/
static
int reorder_tree(Ecma119Image *img, Ecma119Node *dir, int level, int pathlen)
int reorder_tree(Ecma119Image *img, Ecma119Node *dir,
int dir_level, int dir_pathlen)
{
int ret;
size_t max_path;
Ecma119Node *root;
int ret, level, pathlen, newpathlen;
size_t max_path, i;
Ecma119Node *reloc, *child;
/* might change by relocation */
level = dir_level;
pathlen = dir_pathlen;
max_path = pathlen + 1 + max_child_name_len(dir);
if (level > 8 || max_path > 255) {
if (img->eff_partition_offset > 0) {
root = img->partition_root;
} else {
root = img->root;
reloc = img->rr_reloc_node;
if (reloc == NULL) {
if (img->eff_partition_offset > 0) {
reloc = img->partition_root;
} else {
reloc = img->root;
}
}
ret = reparent(dir, root);
ret = reparent(dir, reloc);
if (ret < 0) {
return ret;
}
/*
* we are appended to the root's children now, so there is no
* need to recurse (the root will hit us again)
*/
} else {
size_t i;
if (reloc == img->root || reloc == img->partition_root) {
/*
* we are appended to the root's children now, so there is no
* need to recurse (the root will hit us again)
*/
return ISO_SUCCESS;
}
for (i = 0; i < dir->info.dir->nchildren; i++) {
Ecma119Node *child = dir->info.dir->children[i];
if (child->type == ECMA119_DIR) {
int newpathlen = pathlen + 1 + strlen(child->iso_name);
ret = reorder_tree(img, child, level + 1, newpathlen);
if (ret < 0) {
return ret;
}
}
/* dir is now the relocated Ecma119Node */
pathlen = 37 + 1; /* The dir name might get longer by mangling */
level = 2;
if (img->rr_reloc_dir != NULL) {
pathlen += strlen(img->rr_reloc_node->iso_name) + 1;
if(img->rr_reloc_dir[0] != 0)
level = 3;
}
}
if (ecma119_is_dedicated_reloc_dir(img, (Ecma119Node *) dir))
return ISO_SUCCESS;
for (i = 0; i < dir->info.dir->nchildren; i++) {
child = dir->info.dir->children[i];
if (child->type == ECMA119_DIR) {
newpathlen = pathlen + 1 + strlen(child->iso_name);
ret = reorder_tree(img, child, level + 1, newpathlen);
if (ret < 0)
return ret;
}
}
return ISO_SUCCESS;
@ -1033,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);
family_start = 0;
for (i = 1; i < node_count; i++) {
if (ecma119_node_cmp_hard(nodes + (i - 1), nodes + i) == 0) {
if (nodes[i]->type != ECMA119_DIR &&
ecma119_node_cmp_hard(nodes + (i - 1), nodes + i) == 0) {
/* Still in same ino family */
if (img_ino == 0) { /* Just in case any member knows its img_ino */
iso_node_get_id(nodes[0]->node, &fs_id, &dev_id, &img_ino, 1);
}
}
continue;
}
family_set_ino(img, nodes, family_start, i, img_ino, prev_ino, 0);
@ -1083,14 +1193,14 @@ int ecma119_tree_create(Ecma119Image *img)
sort_tree(root);
iso_msg_debug(img->image->id, "Mangling names...");
ret = mangle_tree(img, 1);
ret = mangle_tree(img, NULL, 1);
if (ret < 0) {
return ret;
}
if (img->rockridge && !img->allow_deep_paths) {
/* 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);
if (ret < 0) {
return ret;
@ -1098,10 +1208,10 @@ int ecma119_tree_create(Ecma119Image *img)
/*
* and we need to remangle the root directory, as the function
* above could insert new directories into the root.
* above could insert new directories into the relocation directory.
* Note that recurse = 0, as we don't need to recurse.
*/
ret = mangle_tree(img, 0);
ret = mangle_tree(img, img->rr_reloc_node, 0);
if (ret < 0) {
return ret;
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* 2012 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -96,5 +97,11 @@ void ecma119_node_free(Ecma119Node *node);
*/
Ecma119Node *ecma119_search_iso_node(Ecma119Image *img, IsoNode *node);
/**
* Tell whether node is a dedicated relocation directory which only contains
* relocated directories.
*/
int ecma119_is_dedicated_reloc_dir(Ecma119Image *img, Ecma119Node *node);
#endif /*LIBISO_ECMA119_TREE_H_*/

View File

@ -12,8 +12,8 @@
#include "../config.h"
#endif
#include "libisofs.h"
#include "eltorito.h"
#include "stream.h"
#include "fsource.h"
#include "filesrc.h"
#include "image.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)
{
bootimg->isolinux_options = (options & 0x03);
bootimg->isolinux_options = (options & 0x01ff);
return ISO_SUCCESS;
}
/* API */
int el_torito_get_isolinux_options(ElToritoBootImage *bootimg, int flag)
{
return bootimg->isolinux_options & 0x03;
return bootimg->isolinux_options & 0x01ff;
}
/* API */
@ -239,6 +239,7 @@ int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot)
IsoBoot *node;
IsoNode **pos;
time_t now;
int ret;
if (parent == NULL || name == NULL || boot == NULL) {
return ISO_NULL_POINTER;
@ -248,9 +249,9 @@ int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot)
}
/* check if the name is valid */
if (!iso_node_is_valid_name(name)) {
return ISO_WRONG_ARG_VALUE;
}
ret = iso_node_is_valid_name(name);
if (ret < 0)
return ret;
/* find place where to insert */
pos = &(parent->children);
@ -274,6 +275,9 @@ int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot)
free(node);
return ISO_OUT_OF_MEM;
}
node->lba = 0;
node->size = 0;
node->content = NULL;
/* atributes from parent */
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)) {
iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
"Can't read MBR from image file.");
return ret < 0 ? ret : ISO_FILE_READ_ERROR;
return ret < 0 ? ret : (int) ISO_FILE_READ_ERROR;
}
/* check valid MBR signature */
if ( mbr.sign1 != 0x55 || mbr.sign2 != 0xAA ) {
iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0,
"Invalid MBR. Wrong signature.");
return ISO_BOOT_IMAGE_NOT_VALID;
return (int) ISO_BOOT_IMAGE_NOT_VALID;
}
/* ensure single partition */
@ -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'",
catdir);
free(catdir);
return ret < 0 ? ret : ISO_NODE_DOESNT_EXIST;
return ret < 0 ? ret : (int) ISO_NODE_DOESNT_EXIST;
}
if (p->type != LIBISO_DIR) {
free(catdir);
@ -597,6 +601,30 @@ int iso_image_get_boot_image(IsoImage *image, ElToritoBootImage **boot,
return ISO_SUCCESS;
}
int iso_image_get_bootcat(IsoImage *image, IsoBoot **catnode, uint32_t *lba,
char **content, off_t *size)
{
IsoBoot *bootcat;
*catnode = NULL;
*lba = 0;
*content = NULL;
*size = 0;
bootcat = image->bootcat->node;
if (bootcat == NULL)
return 0;
*catnode = bootcat;
*lba = bootcat->lba;
*size = bootcat->size;
if (bootcat->size > 0 && bootcat->content != NULL) {
*content = calloc(1, bootcat->size);
if (*content == NULL)
return ISO_OUT_OF_MEM;
memcpy(*content, bootcat->content, bootcat->size);
}
return 1;
}
int iso_image_get_all_boot_imgs(IsoImage *image, int *num_boots,
ElToritoBootImage ***boots, IsoFile ***bootnodes, int flag)
{
@ -759,7 +787,6 @@ write_validation_entry(uint8_t *buf, uint8_t platform_id,
static void
write_section_header(uint8_t *buf, Ecma119Image *t, int idx, int num_entries)
{
int pi;
char *id_string;
struct el_torito_section_header *e =
@ -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 */
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[1] = (num_entries >> 8) & 0xff;;
id_string = (char *) e->id_string;
@ -836,10 +863,10 @@ int catalog_open(IsoStream *stream)
for (j = i + 1; j < cat->num_bootimages; j++) {
if (boots[i]->platform_id != boots[j]->platform_id)
break;
for (k = 0; k < sizeof(boots[i]->id_string); k++)
for (k = 0; k < (int) sizeof(boots[i]->id_string); k++)
if (boots[i]->id_string[k] != boots[j]->id_string[k])
break;
if (k < sizeof(boots[i]->id_string))
if (k < (int) sizeof(boots[i]->id_string))
break;
}
num_entries = j - i;
@ -895,7 +922,7 @@ int catalog_read(IsoStream *stream, void *buf, size_t count)
return ISO_FILE_NOT_OPENED;
}
len = MIN(count, BLOCK_SIZE - data->offset);
len = MIN(count, (size_t) (BLOCK_SIZE - data->offset));
memcpy(buf, data->buffer + data->offset, len);
return len;
}
@ -935,7 +962,11 @@ IsoStreamIface catalog_stream_class = {
catalog_read,
catalog_is_repeatable,
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 */
file->prev_img = 0; /* TODO allow copy of old img catalog???? */
file->no_write = 0; /* TODO allow copy of old img catalog???? */
file->checksum_index = 0;
file->nsections = 1;
file->sections = calloc(1, sizeof(struct iso_file_section));
@ -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
*/
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;
@ -1085,27 +1117,18 @@ int patch_boot_image(uint8_t *buf, Ecma119Image *t, size_t imgsize, int idx)
return ret;
}
static
int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
/* Patch the boot images if indicated */
int iso_patch_eltoritos(Ecma119Image *t)
{
/*
* We have nothing to write, but if we need to patch an isolinux image,
* this is a good place to do so.
*/
Ecma119Image *t;
int ret, idx;
size_t size;
uint8_t *buf;
IsoStream *new = NULL;
IsoStream *original = NULL;
if (writer == NULL) {
return ISO_NULL_POINTER;
}
if (t->catalog == NULL)
return ISO_SUCCESS;
t = writer->target;
/* Patch the boot image info tables if indicated */
for (idx = 0; idx < t->catalog->num_bootimages; idx++) {
if (!(t->catalog->bootimages[idx]->isolinux_options & 0x01))
continue;
@ -1126,12 +1149,12 @@ int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
}
ret = iso_stream_read(original, buf, size);
iso_stream_close(original);
if (ret != size) {
return (ret < 0) ? ret : ISO_FILE_READ_ERROR;
if (ret != (int) size) {
return (ret < 0) ? ret : (int) ISO_FILE_READ_ERROR;
}
/* 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) {
return ret;
}
@ -1148,6 +1171,16 @@ int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
return ISO_SUCCESS;
}
static
int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
{
/*
* We have nothing to write.
*/
return ISO_SUCCESS;
}
/**
* Write the Boot Record Volume Descriptor (ECMA-119, 8.2)
*/
@ -1155,7 +1188,6 @@ static
int eltorito_writer_write_vol_desc(IsoImageWriter *writer)
{
Ecma119Image *t;
struct el_torito_boot_catalog *cat;
struct ecma119_boot_rec_vol_desc vol;
if (writer == NULL) {
@ -1163,7 +1195,6 @@ int eltorito_writer_write_vol_desc(IsoImageWriter *writer)
}
t = writer->target;
cat = t->catalog;
iso_msg_debug(t->image->id, "Write El-Torito boot record");
memset(&vol, 0, sizeof(struct ecma119_boot_rec_vol_desc));
@ -1192,7 +1223,7 @@ int eltorito_writer_free_data(IsoImageWriter *writer)
int eltorito_writer_create(Ecma119Image *target)
{
int ret, idx;
int ret, idx, outsource_efi = 0;
IsoImageWriter *writer;
IsoFile *bootimg;
IsoFileSrc *src;
@ -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++) {
bootimg = target->catalog->bootimages[idx]->image;
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 */
if (target->catalog->bootimages[idx]->isolinux_options & 0x01) {
src->prev_img = 0;
src->no_write = 0;
}
/* If desired: Recognize first EFI boot image that will be newly
written, and mark it as claimed for being a partition.
*/
if (outsource_efi &&
target->catalog->bootimages[idx]->platform_id == 0xef &&
src->no_write == 0) {
target->efi_boot_part_filesrc = src;
src->sections[0].block = 0xfffffffe;
((IsoNode *) bootimg)->hidden |=
LIBISO_HIDE_ON_HFSPLUS | LIBISO_HIDE_ON_FAT;
outsource_efi = 0;
}
}
/* we need the bootable volume descriptor */
target->curblock++;
if (outsource_efi) {
/* Disable EFI Boot partition and complain */
free(target->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;
}

View File

@ -26,6 +26,14 @@
struct Iso_Boot
{
IsoNode node;
/* Want to get content of loaded boot catalog.
Vreixo took care not to make it an IsoFile at load time.
So this is implemented independently of IsoStream.
*/
uint32_t lba;
off_t size;
char *content;
};
/* Not more than 32 so that all entries fit into 2048 bytes */
@ -55,8 +63,14 @@ struct el_torito_boot_image {
* bit 0 -> whether to patch image
* bit 1 -> whether to put built-in isolinux 3.72 isohybrid-MBR into image
* System Area (deprecated)
*
* bit2-7= Mentioning in isohybrid GPT
* 0= do not mention in GPT
* 1= mention as EFI partition
* 2= Mention as HFS+ partition
* bit8= Mention in isohybrid Apple partition map
*/
unsigned int isolinux_options:2;
unsigned int isolinux_options;
unsigned char type; /**< The type of image */
unsigned char partition_type; /**< type of partition for HD-emul images */
short load_seg; /**< Load segment for the initial boot image. */
@ -67,6 +81,7 @@ struct el_torito_boot_image {
uint8_t platform_id;
uint8_t id_string[28];
uint8_t selection_crit[20];
};
/** 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,
uint32_t boot_lba, uint32_t imgsize);
/* Patch the boot images if indicated.
*/
int iso_patch_eltoritos(Ecma119Image *t);
#endif /* LIBISO_ELTORITO_H */

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* 2010 Thomas Schmitt
* 2010 - 2012 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -26,6 +26,8 @@
#include <string.h>
#include <limits.h>
/* <<< */
#include <stdio.h>
#ifdef Xorriso_standalonE
@ -66,7 +68,7 @@ int iso_file_src_cmp(const void *n1, const void *n2)
int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
{
int ret;
int ret, i;
IsoFileSrc *fsrc;
unsigned int fs_id;
dev_t dev_id;
@ -86,7 +88,7 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
}
/* 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) {
/*
* On multisession discs we keep file sections from old image.
@ -110,7 +112,14 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
} else {
fsrc->nsections = 1;
}
fsrc->sections = calloc(fsrc->nsections, sizeof(struct iso_file_section));
fsrc->sections = calloc(fsrc->nsections,
sizeof(struct iso_file_section));
if (fsrc->sections == NULL) {
free(fsrc);
return ISO_OUT_OF_MEM;
}
for (i = 0; i < fsrc->nsections; i++)
fsrc->sections[i].block = 0;
}
fsrc->sort_weight = file->sort_weight;
fsrc->stream = file->stream;
@ -212,16 +221,15 @@ static int cmp_by_weight(const void *f1, const void *f2)
}
static
int is_ms_file(void *arg)
int shall_be_written(void *arg)
{
IsoFileSrc *f = (IsoFileSrc *)arg;
return f->prev_img ? 0 : 1;
return f->no_write ? 0 : 1;
}
static
int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
int filesrc_writer_pre_compute(IsoImageWriter *writer)
{
size_t i, size;
size_t i, size, is_external;
Ecma119Image *t;
IsoFileSrc **filelist;
int (*inc_item)(void *);
@ -231,10 +239,17 @@ int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
}
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 */
if (t->appendable) {
inc_item = is_ms_file;
inc_item = shall_be_written;
} else {
inc_item = NULL;
}
@ -254,10 +269,18 @@ int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
for (i = 0; i < size; ++i) {
int extent = 0;
IsoFileSrc *file = filelist[i];
off_t section_size;
off_t section_size = iso_stream_get_size(file->stream);
/* 0xfffffffe in emerging image means that this is an external
partition. Only assess extent sizes but do not count as part
of filesrc_writer output.
*/
is_external = (file->no_write == 0 &&
file->sections[0].block == 0xfffffffe);
section_size = iso_stream_get_size(file->stream);
for (extent = 0; extent < file->nsections - 1; ++extent) {
file->sections[extent].block = t->curblock + extent *
file->sections[extent].block = t->filesrc_blocks + extent *
(ISO_EXTENT_SIZE / BLOCK_SIZE);
file->sections[extent].size = ISO_EXTENT_SIZE;
section_size -= (off_t) ISO_EXTENT_SIZE;
@ -267,14 +290,29 @@ int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
* final section
*/
if (section_size <= 0) {
file->sections[extent].block = t->empty_file_block;
/* Will become t->empty_file_block
in filesrc_writer_compute_data_blocks()
Special use of 0xffffffe0 to 0xffffffff is covered by
mspad_writer which enforces a minimum start of filesrc at
block 0x00000020.
*/
file->sections[extent].block = 0xffffffff;
} else {
file->sections[extent].block =
t->curblock + extent * (ISO_EXTENT_SIZE / BLOCK_SIZE);
t->filesrc_blocks + extent * (ISO_EXTENT_SIZE / BLOCK_SIZE);
}
file->sections[extent].size = (uint32_t)section_size;
t->curblock += DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE);
/* 0xfffffffe in emerging image means that this is an external
partition. Others will take care of the content data.
*/
if (is_external) {
file->sections[0].block = 0xfffffffe;
file->no_write = 1; /* Ban for filesrc_writer */
continue;
}
t->filesrc_blocks += DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE);
}
/* the list is only needed by this writer, store locally */
@ -282,6 +320,43 @@ int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
return ISO_SUCCESS;
}
static
int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
{
Ecma119Image *t;
int extent = 0;
size_t i;
IsoFileSrc *file;
IsoFileSrc **filelist;
if (writer == NULL) {
return ISO_ASSERT_FAILURE;
}
t = writer->target;
filelist = (IsoFileSrc **) writer->data;
t->filesrc_start = t->curblock;
/* Give all extent addresses their final absolute value */
i = 0;
while ((file = filelist[i++]) != NULL) {
/* Skip external partitions */
if (file->no_write)
continue;
for (extent = 0; extent < file->nsections; ++extent) {
if (file->sections[extent].block == 0xffffffff)
file->sections[extent].block = t->empty_file_block;
else
file->sections[extent].block += t->curblock;
}
}
t->curblock += t->filesrc_blocks;
return ISO_SUCCESS;
}
static
int filesrc_writer_write_vol_desc(IsoImageWriter *writer)
{
@ -324,123 +399,175 @@ int filesrc_make_md5(Ecma119Image *t, IsoFileSrc *file, char md5[16], int flag)
return iso_stream_make_md5(file->stream, md5, 0);
}
static
int filesrc_writer_write_data(IsoImageWriter *writer)
/* name must be NULL or offer at least PATH_MAX characters.
buffer must be NULL or offer at least BLOCK_SIZE characters.
*/
int iso_filesrc_write_data(Ecma119Image *t, IsoFileSrc *file,
char *name, char *buffer, int flag)
{
int res, ret, was_error;
size_t i, b;
Ecma119Image *t;
IsoFileSrc *file;
IsoFileSrc **filelist;
char name[PATH_MAX];
char buffer[BLOCK_SIZE];
char *name_data = NULL;
char *buffer_data = NULL;
size_t b;
off_t file_size;
uint32_t nblocks;
void *ctx= NULL;
char md5[16], pre_md5[16];
int pre_md5_valid = 0;
IsoStream *stream, *inp;
#ifdef Libisofs_with_libjtE
int jte_begun = 0;
#endif
if (writer == NULL) {
return ISO_ASSERT_FAILURE;
if (name == NULL) {
LIBISO_ALLOC_MEM(name_data, char, PATH_MAX);
name = name_data;
}
if (buffer == NULL) {
LIBISO_ALLOC_MEM(buffer_data, char, BLOCK_SIZE);
buffer = buffer_data;
}
t = writer->target;
filelist = writer->data;
was_error = 0;
file_size = iso_file_src_get_size(file);
nblocks = DIV_UP(file_size, BLOCK_SIZE);
pre_md5_valid = 0;
if (file->checksum_index > 0 && (t->md5_file_checksums & 2)) {
/* Obtain an MD5 of content by a first read pass */
pre_md5_valid = filesrc_make_md5(t, file, pre_md5, 0);
}
res = filesrc_open(file);
iso_msg_debug(t->image->id, "Writing Files...");
i = 0;
while ((file = filelist[i++]) != NULL) {
was_error = 0;
file_size = iso_file_src_get_size(file);
nblocks = DIV_UP(file_size, BLOCK_SIZE);
pre_md5_valid = 0;
if (file->checksum_index > 0 && (t->md5_file_checksums & 2)) {
/* Obtain an MD5 of content by a first read pass */
pre_md5_valid = filesrc_make_md5(t, file, pre_md5, 0);
}
res = filesrc_open(file);
iso_stream_get_file_name(file->stream, name);
/* Get file name from end of filter chain */
for (stream = file->stream; ; stream = inp) {
inp = iso_stream_get_input_stream(stream, 0);
if (inp == NULL)
break;
}
iso_stream_get_file_name(stream, name);
if (res < 0) {
/*
* UPS, very ugly error, the best we can do is just to write
* 0's to image
*/
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
was_error = 1;
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
"File \"%s\" can't be opened. Filling with 0s.", name);
if (res < 0) {
/*
* UPS, very ugly error, the best we can do is just to write
* 0's to image
*/
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
was_error = 1;
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
"File \"%s\" can't be opened. Filling with 0s.", name);
ret = res; /* aborted due to error severity */
goto ex;
}
memset(buffer, 0, BLOCK_SIZE);
for (b = 0; b < nblocks; ++b) {
res = iso_write(t, buffer, BLOCK_SIZE);
if (res < 0) {
ret = res; /* aborted due to error severity */
goto ex;
}
memset(buffer, 0, BLOCK_SIZE);
for (b = 0; b < nblocks; ++b) {
res = iso_write(t, buffer, BLOCK_SIZE);
if (res < 0) {
/* ko, writer error, we need to go out! */
ret = res;
goto ex;
}
}
continue;
} else if (res > 1) {
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
was_error = 1;
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
"Size of file \"%s\" has changed. It will be %s", name,
(res == 2 ? "truncated" : "padded with 0's"));
if (res < 0) {
filesrc_close(file);
ret = res; /* aborted due to error severity */
/* ko, writer error, we need to go out! */
ret = res;
goto ex;
}
}
ret = ISO_SUCCESS;
goto ex;
} else if (res > 1) {
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
was_error = 1;
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
"Size of file \"%s\" has changed. It will be %s", name,
(res == 2 ? "truncated" : "padded with 0's"));
if (res < 0) {
filesrc_close(file);
ret = res; /* aborted due to error severity */
goto ex;
}
}
#ifdef LIBISOFS_VERBOSE_DEBUG
else {
iso_msg_debug(t->image->id, "Writing file %s", name);
}
else {
iso_msg_debug(t->image->id, "Writing file %s", name);
}
#endif
#ifdef Libisofs_with_libjtE
if (t->libjte_handle != NULL) {
res = libjte_begin_data_file(t->libjte_handle, name,
BLOCK_SIZE, file_size);
if (res <= 0) {
res = iso_libjte_forward_msgs(t->libjte_handle, t->image->id,
ISO_LIBJTE_FILE_FAILED, 0);
if (res < 0) {
filesrc_close(file);
ret = ISO_LIBJTE_FILE_FAILED;
goto ex;
}
if (t->libjte_handle != NULL) {
res = libjte_begin_data_file(t->libjte_handle, name,
BLOCK_SIZE, file_size);
if (res <= 0) {
res = iso_libjte_forward_msgs(t->libjte_handle, t->image->id,
ISO_LIBJTE_FILE_FAILED, 0);
if (res < 0) {
filesrc_close(file);
ret = ISO_LIBJTE_FILE_FAILED;
goto ex;
}
jte_begun = 1;
}
jte_begun = 1;
}
#endif /* Libisofs_with_libjtE */
if (file->checksum_index > 0) {
/* initialize file checksum */
res = iso_md5_start(&ctx);
if (res <= 0)
file->checksum_index = 0;
}
/* write file contents to image */
for (b = 0; b < nblocks; ++b) {
int wres;
res = filesrc_read(file, buffer, BLOCK_SIZE);
if (res < 0) {
/* read error */
break;
}
wres = iso_write(t, buffer, BLOCK_SIZE);
if (wres < 0) {
/* ko, writer error, we need to go out! */
filesrc_close(file);
ret = wres;
goto ex;
}
if (file->checksum_index > 0) {
/* initialize file checksum */
res = iso_md5_start(&ctx);
/* Add to file checksum */
if (file_size - b * BLOCK_SIZE > BLOCK_SIZE)
res = BLOCK_SIZE;
else
res = file_size - b * BLOCK_SIZE;
res = iso_md5_compute(ctx, buffer, res);
if (res <= 0)
file->checksum_index = 0;
}
/* write file contents to image */
for (b = 0; b < nblocks; ++b) {
int wres;
res = filesrc_read(file, buffer, BLOCK_SIZE);
}
filesrc_close(file);
if (b < nblocks) {
/* premature end of file, due to error or eof */
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
was_error = 1;
if (res < 0) {
/* error */
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
"Read error in file %s.", name);
} else {
/* eof */
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
"Premature end of file %s.", name);
}
if (res < 0) {
ret = res; /* aborted due error severity */
goto ex;
}
/* fill with 0s */
iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
"Filling with 0");
memset(buffer, 0, BLOCK_SIZE);
while (b++ < nblocks) {
res = iso_write(t, buffer, BLOCK_SIZE);
if (res < 0) {
/* read error */
break;
}
wres = iso_write(t, buffer, BLOCK_SIZE);
if (wres < 0) {
/* ko, writer error, we need to go out! */
filesrc_close(file);
ret = wres;
ret = res;
goto ex;
}
if (file->checksum_index > 0) {
@ -454,89 +581,30 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
file->checksum_index = 0;
}
}
filesrc_close(file);
if (b < nblocks) {
/* premature end of file, due to error or eof */
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
was_error = 1;
if (res < 0) {
/* error */
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
"Read error in file %s.", name);
} else {
/* eof */
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
"Premature end of file %s.", name);
}
if (res < 0) {
ret = res; /* aborted due error severity */
goto ex;
}
/* fill with 0s */
iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
"Filling with 0");
memset(buffer, 0, BLOCK_SIZE);
while (b++ < nblocks) {
res = iso_write(t, buffer, BLOCK_SIZE);
}
if (file->checksum_index > 0 &&
file->checksum_index <= t->checksum_idx_counter) {
/* Obtain checksum and dispose checksum context */
res = iso_md5_end(&ctx, md5);
if (res <= 0)
file->checksum_index = 0;
if ((t->md5_file_checksums & 2) && pre_md5_valid > 0 &&
!was_error) {
if (! iso_md5_match(md5, pre_md5)) {
/* Issue MISHAP event */
iso_report_errfile(name, ISO_MD5_STREAM_CHANGE, 0, 0);
was_error = 1;
res = iso_msg_submit(t->image->id, ISO_MD5_STREAM_CHANGE,0,
"Content of file '%s' changed while it was written into the image.",
name);
if (res < 0) {
/* ko, writer error, we need to go out! */
ret = res;
ret = res; /* aborted due to error severity */
goto ex;
}
if (file->checksum_index > 0) {
/* Add to file checksum */
if (file_size - b * BLOCK_SIZE > BLOCK_SIZE)
res = BLOCK_SIZE;
else
res = file_size - b * BLOCK_SIZE;
res = iso_md5_compute(ctx, buffer, res);
if (res <= 0)
file->checksum_index = 0;
}
}
}
if (file->checksum_index > 0 &&
file->checksum_index <= t->checksum_idx_counter) {
/* Obtain checksum and dispose checksum context */
res = iso_md5_end(&ctx, md5);
if (res <= 0)
file->checksum_index = 0;
if ((t->md5_file_checksums & 2) && pre_md5_valid > 0 &&
!was_error) {
if (! iso_md5_match(md5, pre_md5)) {
/* Issue MISHAP event */
iso_report_errfile(name, ISO_MD5_STREAM_CHANGE, 0, 0);
was_error = 1;
res = iso_msg_submit(t->image->id, ISO_MD5_STREAM_CHANGE,0,
"Content of file '%s' changed while it was written into the image.",
name);
if (res < 0) {
ret = res; /* aborted due to error severity */
goto ex;
}
}
}
/* Write md5 into checksum buffer at file->checksum_index */
memcpy(t->checksum_buffer + 16 * file->checksum_index, md5, 16);
}
#ifdef Libisofs_with_libjtE
if (t->libjte_handle != NULL) {
res = libjte_end_data_file(t->libjte_handle);
if (res <= 0) {
iso_libjte_forward_msgs(t->libjte_handle, t->image->id,
ISO_LIBJTE_FILE_FAILED, 0);
ret = ISO_LIBJTE_FILE_FAILED;
goto ex;
}
jte_begun = 0;
}
#endif /* Libisofs_with_libjtE */
/* Write md5 into checksum buffer at file->checksum_index */
memcpy(t->checksum_buffer + 16 * file->checksum_index, md5, 16);
}
ret = ISO_SUCCESS;
@ -546,15 +614,75 @@ ex:;
#ifdef Libisofs_with_libjtE
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_END_FAILED, 0);
if (res <= 0 && ret >= 0)
ret = ISO_LIBJTE_FILE_FAILED;
}
#endif /* Libisofs_with_libjtE */
LIBISO_FREE_MEM(buffer_data);
LIBISO_FREE_MEM(name_data);
return ret;
}
static
int filesrc_writer_write_data(IsoImageWriter *writer)
{
int ret;
size_t i;
Ecma119Image *t = NULL;
IsoFileSrc *file;
IsoFileSrc **filelist;
char *name = NULL;
char *buffer = NULL;
if (writer == NULL) {
ret = ISO_ASSERT_FAILURE; goto ex;
}
LIBISO_ALLOC_MEM(name, char, PATH_MAX);
LIBISO_ALLOC_MEM(buffer, char, BLOCK_SIZE);
t = writer->target;
filelist = writer->data;
iso_msg_debug(t->image->id, "Writing Files...");
/* Normally write a single zeroed block as block address target for all
files which have no block address:
symbolic links, device files, empty data files.
*/
if (! t->old_empty) {
ret = iso_write(t, buffer, BLOCK_SIZE);
if (ret < 0)
goto ex;
}
i = 0;
while ((file = filelist[i++]) != NULL) {
if (file->no_write) {
/* Do not write external partitions */
iso_msg_debug(t->image->id,
"filesrc_writer: Skipping no_write-src [%.f , %.f]",
(double) file->sections[0].block,
(double) (file->sections[0].block - 1 +
(file->sections[0].size + 2047) / BLOCK_SIZE));
continue;
}
ret = iso_filesrc_write_data(t, file, name, buffer, 0);
if (ret < 0)
goto ex;
}
ret = ISO_SUCCESS;
ex:;
LIBISO_FREE_MEM(buffer);
LIBISO_FREE_MEM(name);
return ret;
}
static
int filesrc_writer_free_data(IsoImageWriter *writer)
{

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* 2012 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -13,14 +14,41 @@
#include "stream.h"
#include "ecma119.h"
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#endif
/* Abstraction of data file content in the emerging image.
*/
struct Iso_File_Src
{
unsigned int prev_img :1; /**< if the file comes from a previous image */
/* This marks an IsoFileSrc which shall only expose its extent addresses
and sizes but shall not be counted or written by filesrc_writer.
*/
unsigned int no_write :1;
unsigned int checksum_index :31;
/** File Sections of the file in the image */
/* Special sections[0].block values while they are relative
before filesrc_writer_compute_data_blocks().
Valid only with .no_write == 0:
0xfffffffe This Iso_File_Src is claimed as external partition.
Others will take care of the content data.
filesrc_writer shall neither count nor write it.
At write_data time it is already converted to
a fileadress between Ecma119Image.ms_block and
Ecma119Image.filesrc_start - 1.
0xffffffff This is the block to which empty files shall point.
Normal data files have relative addresses from 0 to 0xffffffdf.
They cannot be higher, because mspad_writer forces the absolute
filesrc addresses to start at least at 0x20.
*/
struct iso_file_section *sections;
int nsections;
@ -87,4 +115,21 @@ off_t iso_file_src_get_size(IsoFileSrc *file);
*/
int iso_file_src_writer_create(Ecma119Image *target);
/**
* Determine number of filesrc blocks in the image and compute extent addresses
* relative to start of the file source writer area.
* filesrc_writer_compute_data_blocks() later makes them absolute.
*/
int filesrc_writer_pre_compute(IsoImageWriter *writer);
/**
* Write the content of file into the output stream of t.
* name must be NULL or offer at least PATH_MAX characters of storage.
* buffer must be NULL or offer at least BLOCK_SIZE characters of storage.
* flag is not used yet, submit 0.
*/
int iso_filesrc_write_data(Ecma119Image *t, IsoFileSrc *file,
char *name, char *buffer, int flag);
#endif /*LIBISO_FILESRC_H_*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009 Thomas Schmitt
* Copyright (c) 2009 - 2011 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -20,6 +20,7 @@
#include "../libisofs.h"
#include "../filter.h"
#include "../fsource.h"
#include "../stream.h"
#include <sys/types.h>
#include <sys/time.h>
@ -40,7 +41,7 @@
* for classical pipe filtering.
*/
/* IMPORTANT: Any change must be reflected by extf_clone_stream() */
/*
* Individual runtime properties exist only as long as the stream is opened.
*/
@ -598,6 +599,36 @@ IsoStream *extf_get_input_stream(IsoStream *stream, int flag)
return data->orig;
}
static
int extf_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag)
{
int ret;
IsoStream *new_input_stream, *stream;
ExternalFilterStreamData *stream_data, *old_stream_data;
if (flag)
return ISO_STREAM_NO_CLONE; /* unknown option required */
stream_data = calloc(1, sizeof(ExternalFilterStreamData));
if (stream_data == NULL)
return ISO_OUT_OF_MEM;
ret = iso_stream_clone_filter_common(old_stream, &stream,
&new_input_stream, 0);
if (ret < 0) {
free((char *) stream_data);
return ret;
}
old_stream_data = (ExternalFilterStreamData *) old_stream->data;
stream_data->id = ++extf_ino_id;
stream_data->orig = new_input_stream;
stream_data->cmd = old_stream_data->cmd;
stream_data->cmd->refcount++;
stream_data->size = old_stream_data->size;
stream_data->running = NULL;
stream->data = stream_data;
*new_stream = stream;
return ISO_SUCCESS;
}
static
int extf_cmp_ino(IsoStream *s1, IsoStream *s2);
@ -605,7 +636,7 @@ int extf_cmp_ino(IsoStream *s1, IsoStream *s2);
IsoStreamIface extf_stream_class = {
3,
4,
"extf",
extf_stream_open,
extf_stream_close,
@ -616,7 +647,8 @@ IsoStreamIface extf_stream_class = {
extf_stream_free,
extf_update_size,
extf_get_input_stream,
extf_cmp_ino
extf_cmp_ino,
extf_clone_stream
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009 Thomas Schmitt
* Copyright (c) 2009 - 2011 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -25,6 +25,7 @@
#include "../filter.h"
#include "../fsource.h"
#include "../util.h"
#include "../stream.h"
#include <sys/types.h>
#include <sys/time.h>
@ -153,6 +154,7 @@ static int gzip_compression_level = 6;
/*
* The data payload of an individual Gzip Filter IsoStream
*/
/* IMPORTANT: Any change must be reflected by gzip_clone_stream() */
typedef struct
{
IsoStream *orig;
@ -392,7 +394,7 @@ int gzip_stream_convert(IsoStream *stream, void *buf, size_t desired, int flag)
if (cnv_ret == Z_STREAM_ERROR || cnv_ret == Z_BUF_ERROR) {
return (rng->error_ret = ISO_ZLIB_COMPR_ERR);
}
if (strm->avail_out < rng->out_buffer_size)
if ((int) strm->avail_out < rng->out_buffer_size)
break; /* output is available */
if (strm->avail_in == 0) /* all pending input consumed */
break;
@ -529,12 +531,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
int gzip_cmp_ino(IsoStream *s1, IsoStream *s2);
IsoStreamIface gzip_stream_compress_class = {
3,
4,
"gzip",
gzip_stream_open,
gzip_stream_close,
@ -545,12 +586,13 @@ IsoStreamIface gzip_stream_compress_class = {
gzip_stream_free,
gzip_update_size,
gzip_get_input_stream,
gzip_cmp_ino
gzip_cmp_ino,
gzip_clone_stream
};
IsoStreamIface gzip_stream_uncompress_class = {
3,
4,
"pizg",
gzip_stream_open,
gzip_stream_close,
@ -561,7 +603,8 @@ IsoStreamIface gzip_stream_uncompress_class = {
gzip_stream_free,
gzip_update_size,
gzip_get_input_stream,
gzip_cmp_ino
gzip_cmp_ino,
gzip_clone_stream
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009 Thomas Schmitt
* Copyright (c) 2009 - 2011 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -22,6 +22,7 @@
#include "../filter.h"
#include "../fsource.h"
#include "../util.h"
#include "../stream.h"
#include <sys/types.h>
#include <sys/time.h>
@ -167,6 +168,7 @@ static int ziso_compression_level = 6;
/*
* The common data payload of an individual Zisofs Filter IsoStream
* IMPORTANT: Any change must be reflected by ziso_clone_stream().
*/
typedef struct
{
@ -183,6 +185,7 @@ typedef struct
/*
* The data payload of an individual Zisofs Filter Compressor IsoStream
* IMPORTANT: Any change must be reflected by ziso_clone_stream().
*/
typedef struct
{
@ -198,6 +201,7 @@ typedef struct
/*
* The data payload of an individual Zisofs Filter Uncompressor IsoStream
* IMPORTANT: Any change must be reflected by ziso_clone_stream().
*/
typedef struct
{
@ -572,7 +576,8 @@ int ziso_stream_uncompress(IsoStream *stream, void *buf, size_t desired)
rng->block_pointers[i] =
iso_read_lsb((uint8_t *) (rng->block_pointers + i), 4);
if (i > 0)
if (rng->block_pointers[i] - rng->block_pointers[i - 1]
if ((int) (rng->block_pointers[i] -
rng->block_pointers[i - 1])
> block_max)
block_max = rng->block_pointers[i]
- rng->block_pointers[i - 1];
@ -615,7 +620,7 @@ int ziso_stream_uncompress(IsoStream *stream, void *buf, size_t desired)
if (ret != Z_OK)
return (rng->error_ret = ISO_ZLIB_COMPR_ERR);
rng->buffer_fill = buf_len;
if (buf_len < rng->block_size &&
if ((int) buf_len < rng->block_size &&
i != rng->block_pointer_fill - 1)
return (rng->error_ret = ISO_ZISOFS_WRONG_INPUT);
} else if(ret == 0) {
@ -779,13 +784,63 @@ IsoStream *ziso_get_input_stream(IsoStream *stream, int flag)
return data->orig;
}
static
int ziso_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag)
{
int ret;
IsoStream *new_input_stream = NULL, *stream = NULL;
ZisofsFilterStreamData *stream_data, *old_stream_data;
ZisofsUncomprStreamData *uncompr, *old_uncompr;
ZisofsComprStreamData *compr, *old_compr;
if (flag)
return ISO_STREAM_NO_CLONE; /* unknown option required */
ret = iso_stream_clone_filter_common(old_stream, &stream,
&new_input_stream, 0);
if (ret < 0)
return ret;
if (old_stream->class->read == &ziso_stream_uncompress) {
uncompr = calloc(1, sizeof(ZisofsUncomprStreamData));
if (uncompr == NULL)
goto no_mem;
stream_data = (ZisofsFilterStreamData *) uncompr;
old_uncompr = (ZisofsUncomprStreamData *) old_stream->data;
uncompr->header_size_div4 = old_uncompr->header_size_div4;
uncompr->block_size_log2 = old_uncompr->block_size_log2;
} else {
compr = calloc(1, sizeof(ZisofsComprStreamData));
if (compr == NULL)
goto no_mem;
stream_data = (ZisofsFilterStreamData *) compr;
old_compr = (ZisofsComprStreamData *) old_stream->data;
compr->orig_size = old_compr->orig_size;
compr->block_pointers = NULL;
}
old_stream_data = (ZisofsFilterStreamData *) old_stream->data;
stream_data->orig = new_input_stream;
stream_data->size = old_stream_data->size;
stream_data->running = NULL;
stream_data->id = ++ziso_ino_id;
stream->data = stream_data;
*new_stream = stream;
return ISO_SUCCESS;
no_mem:
if (new_input_stream != NULL)
iso_stream_unref(new_input_stream);
if (stream != NULL)
iso_stream_unref(stream);
return ISO_OUT_OF_MEM;
}
static
int ziso_cmp_ino(IsoStream *s1, IsoStream *s2);
IsoStreamIface ziso_stream_compress_class = {
3,
4,
"ziso",
ziso_stream_open,
ziso_stream_close,
@ -796,12 +851,13 @@ IsoStreamIface ziso_stream_compress_class = {
ziso_stream_free,
ziso_update_size,
ziso_get_input_stream,
ziso_cmp_ino
ziso_cmp_ino,
ziso_clone_stream
};
IsoStreamIface ziso_stream_uncompress_class = {
3,
4,
"osiz",
ziso_stream_open,
ziso_stream_close,
@ -812,7 +868,8 @@ IsoStreamIface ziso_stream_uncompress_class = {
ziso_stream_free,
ziso_update_size,
ziso_get_input_stream,
ziso_cmp_ino
ziso_cmp_ino,
ziso_clone_stream
};

View File

@ -141,11 +141,12 @@ void update_next(IsoDirIter *iter)
static
int find_iter_next(IsoDirIter *iter, IsoNode **node)
{
struct find_iter_data *data = iter->data;
struct find_iter_data *data;
if (iter == NULL || node == NULL) {
return ISO_NULL_POINTER;
}
data = iter->data;
if (data->err < 0) {
return data->err;

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt
* Copyright (c) 2009 - 2011 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -39,7 +39,7 @@ int iso_file_source_new_lfs(IsoFileSource *parent, const char *name,
*/
IsoFilesystem *lfs= NULL;
/* IMPORTANT: Any change must be reflected by lfs_clone_src() */
typedef struct
{
/** reference to the parent (if root it points to itself) */
@ -95,14 +95,14 @@ char* lfs_get_name(IsoFileSource *src)
static
int lfs_lstat(IsoFileSource *src, struct stat *info)
{
_LocalFsFileSource *data;
char *path;
if (src == NULL || info == NULL) {
return ISO_NULL_POINTER;
}
data = src->data;
path = lfs_get_path(src);
if (path == NULL)
return ISO_OUT_OF_MEM;
if (lstat(path, info) != 0) {
int err;
@ -128,6 +128,7 @@ int lfs_lstat(IsoFileSource *src, struct stat *info)
err = ISO_FILE_ERROR;
break;
}
free(path);
return err;
}
free(path);
@ -137,14 +138,14 @@ int lfs_lstat(IsoFileSource *src, struct stat *info)
static
int lfs_stat(IsoFileSource *src, struct stat *info)
{
_LocalFsFileSource *data;
char *path;
if (src == NULL || info == NULL) {
return ISO_NULL_POINTER;
}
data = src->data;
path = lfs_get_path(src);
if (path == NULL)
return ISO_OUT_OF_MEM;
if (stat(path, info) != 0) {
int err;
@ -170,6 +171,7 @@ int lfs_stat(IsoFileSource *src, struct stat *info)
err = ISO_FILE_ERROR;
break;
}
free(path);
return err;
}
free(path);
@ -180,13 +182,11 @@ static
int lfs_access(IsoFileSource *src)
{
int ret;
_LocalFsFileSource *data;
char *path;
if (src == NULL) {
return ISO_NULL_POINTER;
}
data = src->data;
path = lfs_get_path(src);
ret = iso_eaccess(path);
@ -412,8 +412,7 @@ int lfs_readdir(IsoFileSource *src, IsoFileSource **child)
static
int lfs_readlink(IsoFileSource *src, char *buf, size_t bufsiz)
{
int size;
_LocalFsFileSource *data;
int size, ret;
char *path;
if (src == NULL || buf == NULL) {
@ -424,14 +423,13 @@ int lfs_readlink(IsoFileSource *src, char *buf, size_t bufsiz)
return ISO_WRONG_ARG_VALUE;
}
data = src->data;
path = lfs_get_path(src);
/*
* invoke readlink, with bufsiz -1 to reserve an space for
* the NULL character
*/
size = readlink(path, buf, bufsiz - 1);
size = readlink(path, buf, bufsiz);
free(path);
if (size < 0) {
/* error */
@ -455,8 +453,13 @@ int lfs_readlink(IsoFileSource *src, char *buf, size_t bufsiz)
}
/* NULL-terminate the buf */
ret = ISO_SUCCESS;
if ((size_t) size >= bufsiz) {
ret = ISO_RR_PATH_TOO_LONG;
size = bufsiz - 1;
}
buf[size] = '\0';
return ISO_SUCCESS;
return ret;
}
static
@ -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;
char *path = NULL, **names = NULL, **values = NULL;
unsigned char *result = NULL;
_LocalFsFileSource *data;
data = src->data;
*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.
*/
path = iso_file_source_get_path(src);
if (path == NULL) {
ret = ISO_NULL_POINTER;
goto ex;
}
ret = aaip_get_attr_list(path, &num_attrs, &names,
&value_lengths, &values,
(!(flag & 2)) | 2 | (flag & 4) | 16);
if (ret <= 0) {
ret = ISO_FILE_ERROR;
if (ret == -2)
ret = ISO_AAIP_NO_GET_LOCAL;
else
ret = ISO_FILE_ERROR;
goto ex;
}
if (num_attrs == 0)
@ -534,10 +541,56 @@ ex:;
return ret;
}
static
int lfs_clone_src(IsoFileSource *old_source,
IsoFileSource **new_source, int flag)
{
IsoFileSource *src = NULL;
char *new_name = NULL;
_LocalFsFileSource *old_data, *new_data = NULL;
if (flag)
return ISO_STREAM_NO_CLONE; /* unknown option required */
old_data = (_LocalFsFileSource *) old_source->data;
*new_source = NULL;
src = calloc(1, sizeof(IsoFileSource));
if (src == NULL)
goto no_mem;
new_name = strdup(old_data->name);
if (new_name == NULL)
goto no_mem;
new_data = calloc(1, sizeof(_LocalFsFileSource));
if (new_data == NULL)
goto no_mem;
new_data->openned = 0;
new_data->info.fd = -1; /* the value does not matter with (openned == 0) */
new_data->name = new_name;
new_data->parent = old_data->parent;
src->class = old_source->class;
src->refcount = 1;
src->data = new_data;
*new_source = src;
iso_file_source_ref(new_data->parent);
iso_filesystem_ref(lfs);
return ISO_SUCCESS;
no_mem:;
if (src != NULL)
free((char *) src);
if (new_data != NULL)
free((char *) new_data);
if (new_name != NULL)
free(new_name);
return ISO_OUT_OF_MEM;
}
IsoFileSourceIface lfs_class = {
1, /* version */
2, /* version */
lfs_get_path,
lfs_get_name,
lfs_lstat,
@ -551,7 +604,8 @@ IsoFileSourceIface lfs_class = {
lfs_get_filesystem,
lfs_free,
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 ret;
@ -805,13 +868,19 @@ int iso_local_set_attrs(char *disk_path, size_t num_attrs, char **names,
int ret;
ret = aaip_set_attr_list(disk_path, num_attrs, names, value_lengths,
values, (flag & (8 | 32)) | !(flag & 1));
values, (flag & (8 | 32 | 64)) | !(flag & 1));
if (ret <= 0) {
if (ret == -1)
return ISO_OUT_OF_MEM;
if (ret == -2)
return ISO_AAIP_BAD_AASTRING;
return ISO_AAIP_NO_SET_LOCAL;
if (ret >= -5)
return ISO_AAIP_NO_SET_LOCAL;
if (ret == -6 || ret == -7)
return ISO_AAIP_NOT_ENABLED;
if (ret == -8)
return ISO_AAIP_BAD_ATTR_NAME;
return ret;
}
return 1;
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt
* Copyright (c) 2009 - 2011 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -33,9 +33,16 @@
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.
*/
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_*/

1844
libisofs/hfsplus.c Normal file

File diff suppressed because it is too large Load Diff

197
libisofs/hfsplus.h Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt
* Copyright (c) 2009 - 2012 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -32,7 +32,7 @@
* @param image
* Location where the image pointer will be stored.
* @return
* 1 sucess, < 0 error
* 1 success, < 0 error
*/
int iso_image_new(const char *name, IsoImage **image)
{
@ -93,6 +93,9 @@ int iso_image_new(const char *name, IsoImage **image)
img->checksum_idx_count = 0;
img->checksum_array = NULL;
img->generator_is_running = 0;
for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++)
img->hfsplus_blessed[i] = NULL;
*image = img;
return ISO_SUCCESS;
}
@ -112,20 +115,22 @@ void iso_image_ref(IsoImage *image)
*/
void iso_image_unref(IsoImage *image)
{
if (--image->refcount == 0) {
int nexcl;
int nexcl, i;
if (--image->refcount == 0) {
/* we need to free the image */
if (image->user_data_free != NULL) {
/* free attached data */
image->user_data_free(image->user_data);
}
for (nexcl = 0; nexcl < image->nexcludes; ++nexcl) {
free(image->excludes[nexcl]);
}
free(image->excludes);
for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++)
if (image->hfsplus_blessed[i] != NULL)
iso_node_unref(image->hfsplus_blessed[i]);
iso_node_unref((IsoNode*)image->root);
iso_node_builder_unref(image->builder);
iso_filesystem_unref(image->fs);
@ -142,6 +147,8 @@ void iso_image_unref(IsoImage *image)
free(image->biblio_file_id);
if (image->used_inodes != NULL)
free(image->used_inodes);
if (image->system_area_data != NULL)
free(image->system_area_data);
iso_image_free_checksums(image, 0);
free(image);
}
@ -655,3 +662,73 @@ int iso_image_give_up_mips_boot(IsoImage *image, int flag)
image->num_mips_boot_files = 0;
return ISO_SUCCESS;
}
static void unset_blessing(IsoImage *img, unsigned int idx)
{
if (img->hfsplus_blessed[idx] != NULL)
iso_node_unref(img->hfsplus_blessed[idx]);
img->hfsplus_blessed[idx] = NULL;
}
/* API */
int iso_image_hfsplus_bless(IsoImage *img, enum IsoHfsplusBlessings blessing,
IsoNode *node, int flag)
{
unsigned int i, ok = 0;
if (flag & 2) {
/* Delete any blessing */
for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++) {
if (img->hfsplus_blessed[i] == node || node == NULL) {
unset_blessing(img, i);
ok = 1;
}
}
return ok;
}
if (blessing == ISO_HFSPLUS_BLESS_MAX)
return ISO_WRONG_ARG_VALUE;
if (flag & 1) {
/* Delete a particular blessing */
if (img->hfsplus_blessed[blessing] == node || node == NULL) {
unset_blessing(img, (unsigned int) blessing);
return 1;
}
return 0;
}
if (node == NULL) {
unset_blessing(img, (unsigned int) blessing);
return 1;
}
/* No two hats on one node */
for (i = 0; i < ISO_HFSPLUS_BLESS_MAX && node != NULL; i++)
if (i != blessing && img->hfsplus_blessed[i] == node)
return 0;
/* Enforce correct file type */
if (blessing == ISO_HFSPLUS_BLESS_INTEL_BOOTFILE) {
if (node->type != LIBISO_FILE)
return 0;
} else {
if (node->type != LIBISO_DIR)
return 0;
}
unset_blessing(img, (unsigned int) blessing);
img->hfsplus_blessed[blessing] = node;
if (node != NULL)
iso_node_ref(node);
return 1;
}
/* API */
int iso_image_hfsplus_get_blessed(IsoImage *img, IsoNode ***blessed_nodes,
int *bless_max, int flag)
{
*blessed_nodes = img->hfsplus_blessed;
*bless_max = ISO_HFSPLUS_BLESS_MAX;
return 1;
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt
* Copyright (c) 2009 - 2012 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -180,6 +180,13 @@ struct Iso_Image
*/
int generator_is_running;
/* Pointers to directories or files which shall be get a HFS+ blessing.
* libisofs/hfsplus.c et.al. will compare these pointers
* with the ->node pointer of Ecma119Nodes.
* See libisofs.h
*/
IsoNode *hfsplus_blessed[ISO_HFSPLUS_BLESS_MAX];
};

View File

@ -1,5 +1,6 @@
/*
* 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
* modify it under the terms of the GNU General Public License version 2
@ -17,6 +18,8 @@
#include "image.h"
#include "filesrc.h"
#include "eltorito.h"
#include "util.h"
#include "ecma119.h"
#include <stdlib.h>
#include <stdio.h>
@ -73,7 +76,7 @@ void iso1999_node_free(Iso1999Node *node)
return;
}
if (node->type == ISO1999_DIR) {
int i;
size_t i;
for (i = 0; i < node->info.dir->nchildren; i++) {
iso1999_node_free(node->info.dir->children[i]);
}
@ -307,7 +310,10 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
Iso1999Node **children;
IsoHTable *table;
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;
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,
(compare_function_t)strcmp, &table);
if (ret < 0) {
return ret;
goto ex;
}
for (i = 0; i < nchildren; ++i) {
char *name = children[i]->name;
ret = iso_htable_add(table, name, name);
if (ret < 0) {
goto mangle_cleanup;
goto ex;
}
}
for (i = 0; i < nchildren; ++i) {
char *name, *ext;
char full_name[208];
int max; /* computed max len for name, without extension */
int j = i;
int digits = 1; /* characters to change per name */
@ -384,7 +389,7 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
* This can't happen with current limit of digits.
*/
ret = ISO_ERROR;
goto mangle_cleanup;
goto ex;
}
}
/* ok, reduce name by digits */
@ -398,7 +403,7 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
}
max = 207 - digits;
name = full_name;
if (max < strlen(name)) {
if ((size_t) max < strlen(name)) {
name[max] = '\0';
}
/* let ext be an empty string */
@ -408,7 +413,6 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
ok = 1;
/* change name of each file */
for (k = i; k <= j; ++k) {
char tmp[208];
char fmt[16];
if (dot != NULL) {
sprintf(fmt, "%%s%%0%dd.%%s", digits);
@ -431,7 +435,7 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
char *new = strdup(tmp);
if (new == NULL) {
ret = ISO_OUT_OF_MEM;
goto mangle_cleanup;
goto ex;
}
iso_msg_debug(img->image->id, "\"%s\" renamed to \"%s\"",
children[k]->name, new);
@ -459,7 +463,7 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
}
if (digits == 8) {
ret = ISO_MANGLE_TOO_MUCH_FILES;
goto mangle_cleanup;
goto ex;
}
i = j;
}
@ -473,8 +477,10 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir)
ret = ISO_SUCCESS;
mangle_cleanup : ;
ex:;
iso_htable_destroy(table, NULL);
LIBISO_FREE_MEM(tmp);
LIBISO_FREE_MEM(full_name);
return ret;
}
@ -683,8 +689,9 @@ void write_one_dir_record(Ecma119Image *t, Iso1999Node *node, int file_id,
: (uint8_t*)node->name;
struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf;
IsoNode *iso;
len_dr = 33 + len_fi + (len_fi % 2 ? 0 : 1);
len_dr = 33 + len_fi + ((len_fi % 2) ? 0 : 1);
memcpy(rec->file_id, name, len_fi);
@ -714,7 +721,15 @@ void write_one_dir_record(Ecma119Image *t, Iso1999Node *node, int file_id,
rec->len_dr[0] = len_dr;
iso_bb(rec->block, block, 4);
iso_bb(rec->length, len, 4);
iso_datetime_7(rec->recording_time, t->now, t->always_gmt);
/* was: iso_datetime_7(rec->recording_time, t->now, t->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);
iso_bb(rec->vol_seq_number, (uint32_t) 1, 2);
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.bibliographic_file_id, biblio_file_id, 37);
iso_datetime_17(vol.vol_creation_time, t->now, t->always_gmt);
iso_datetime_17(vol.vol_modification_time, t->now, t->always_gmt);
iso_datetime_17(vol.vol_effective_time, t->now, t->always_gmt);
vol.file_structure_version[0] = 1;
ecma119_set_voldescr_times(writer, (struct ecma119_pri_vol_desc *) &vol);
vol.file_structure_version[0] = 2;
free(vol_id);
free(volset_id);
@ -810,15 +823,15 @@ static
int write_one_dir(Ecma119Image *t, Iso1999Node *dir)
{
int ret;
uint8_t buffer[BLOCK_SIZE];
uint8_t *buffer = NULL;
size_t i;
size_t fi_len, len;
/* buf will point to current write position on buffer */
uint8_t *buf = buffer;
uint8_t *buf;
/* initialize buffer with 0s */
memset(buffer, 0, BLOCK_SIZE);
LIBISO_ALLOC_MEM(buffer, uint8_t, BLOCK_SIZE);
buf = buffer;
/* write the "." and ".." entries first */
write_one_dir_record(t, dir, 0, buf, 1, 0);
@ -832,7 +845,7 @@ int write_one_dir(Ecma119Image *t, Iso1999Node *dir)
/* compute len of directory entry */
fi_len = strlen(child->name);
len = fi_len + 33 + (fi_len % 2 ? 0 : 1);
len = fi_len + 33 + ((fi_len % 2) ? 0 : 1);
nsections = (child->type == ISO1999_FILE) ? child->info.file->nsections : 1;
for (section = 0; section < nsections; ++section) {
@ -840,7 +853,7 @@ int write_one_dir(Ecma119Image *t, Iso1999Node *dir)
/* dir doesn't fit in current block */
ret = iso_write(t, buffer, BLOCK_SIZE);
if (ret < 0) {
return ret;
goto ex;
}
memset(buffer, 0, BLOCK_SIZE);
buf = buffer;
@ -853,6 +866,8 @@ int write_one_dir(Ecma119Image *t, Iso1999Node *dir)
/* write the last block */
ret = iso_write(t, buffer, BLOCK_SIZE);
ex:;
LIBISO_FREE_MEM(buffer);
return ret;
}
@ -885,13 +900,17 @@ static
int write_path_table(Ecma119Image *t, Iso1999Node **pathlist, int l_type)
{
size_t i, len;
uint8_t buf[256]; /* 256 is just a convenient size larger enought */
uint8_t *buf = NULL;
struct ecma119_path_table_record *rec;
void (*write_int)(uint8_t*, uint32_t, int);
Iso1999Node *dir;
uint32_t path_table_size;
int parent = 0;
int ret= ISO_SUCCESS;
uint8_t *zeros = NULL;
/* 256 is just a convenient size large enought */
LIBISO_ALLOC_MEM(buf, uint8_t, 256);
path_table_size = 0;
write_int = l_type ? iso_lsb : iso_msb;
@ -918,7 +937,7 @@ int write_path_table(Ecma119Image *t, Iso1999Node **pathlist, int l_type)
ret = iso_write(t, buf, len);
if (ret < 0) {
/* error */
return ret;
goto ex;
}
path_table_size += len;
}
@ -926,11 +945,14 @@ int write_path_table(Ecma119Image *t, Iso1999Node **pathlist, int l_type)
/* we need to fill the last block with zeros */
path_table_size %= BLOCK_SIZE;
if (path_table_size) {
uint8_t zeros[BLOCK_SIZE];
LIBISO_ALLOC_MEM(zeros, uint8_t, BLOCK_SIZE);
len = BLOCK_SIZE - path_table_size;
memset(zeros, 0, len);
ret = iso_write(t, zeros, len);
}
ex:;
LIBISO_FREE_MEM(zeros);
LIBISO_FREE_MEM(buf);
return ret;
}

View File

@ -1,6 +1,7 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* 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
* modify it under the terms of the GNU General Public License version 2
@ -19,6 +20,8 @@
#include "filesrc.h"
#include "eltorito.h"
#include "libisofs.h"
#include "util.h"
#include "ecma119.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);
return ret;
}
/* TODO #00022 : support relaxed constraints in joliet filenames */
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 {
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);
if (jname != NULL) {
@ -69,7 +71,7 @@ void joliet_node_free(JolietNode *node)
return;
}
if (node->type == JOLIET_DIR) {
int i;
size_t i;
for (i = 0; i < node->info.dir->nchildren; i++) {
joliet_node_free(node->info.dir->children[i]);
}
@ -303,8 +305,15 @@ int joliet_create_mangled_name(uint16_t *dest, uint16_t *src, int digits,
int ret, pos;
uint16_t *ucsnumber;
char fmt[16];
char nstr[72]; /* The only caller of this function allocates dest with 66
elements and limits digits to < 8 */
char nstr[72];
/* was: The only caller of this function allocates dest
with 66 elements and limits digits to < 8
But this does not match the usage of nstr which has to take
the decimal representation of an int.
*/
if (digits >= 8)
return ISO_ASSERT_FAILURE;
sprintf(fmt, "%%0%dd", digits);
sprintf(nstr, fmt, number);
@ -324,11 +333,12 @@ int joliet_create_mangled_name(uint16_t *dest, uint16_t *src, int digits,
if (ext[0] != (uint16_t)0) {
size_t extlen = ucslen(ext);
dest[pos++] = (uint16_t)0x2E00; /* '.' in big endian UCS */
iso_msb((uint8_t *) (dest + pos), 0x002E, 2); /* '.' in UCS */
pos++;
ucsncpy(dest + pos, ext, extlen);
pos += extlen;
}
dest[pos] = (uint16_t)0;
iso_msb((uint8_t *) (dest + pos), 0, 2);
free(ucsnumber);
return ISO_SUCCESS;
}
@ -337,19 +347,26 @@ static
int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
{
int ret;
int i, nchildren;
int i, nchildren, maxchar = 64;
JolietNode **children;
IsoHTable *table;
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;
children = dir->info.dir->children;
if (t->joliet_long_names)
maxchar = 103;
/* a hash table will temporary hold the names, for fast searching */
ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash,
(compare_function_t)ucscmp, &table);
if (ret < 0) {
return ret;
goto ex;
}
for (i = 0; i < nchildren; ++i) {
uint16_t *name = children[i]->name;
@ -361,7 +378,6 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
for (i = 0; i < nchildren; ++i) {
uint16_t *name, *ext;
uint16_t full_name[66];
int max; /* computed max len for name, without extension */
int j = i;
int digits = 1; /* characters to change per name */
@ -380,7 +396,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
* A max of 7 characters is good enought, it allows handling up to
* 9,999,999 files with same name.
*/
/* Important: joliet_create_mangled_name() relies on digits < 72 */
/* Important: joliet_create_mangled_name() relies on digits < 8 */
while (digits < 8) {
int ok, k;
@ -403,7 +419,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
ext = dot + 1;
extlen = ucslen(ext);
max = 65 - extlen - 1 - digits;
max = maxchar + 1 - extlen - 1 - digits;
if (max <= 0) {
/* this can happen if extension is too long */
if (extlen + max > 3) {
@ -413,7 +429,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
*/
extlen = extlen + max - 1;
ext[extlen] = 0;
max = 66 - extlen - 1 - digits;
max = maxchar + 2 - extlen - 1 - digits;
} else {
/*
* error, we don't support extensions < 3
@ -430,13 +446,13 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
} else {
/* Directory, or file without extension */
if (children[i]->type == JOLIET_DIR) {
max = 65 - digits;
max = maxchar + 1 - digits;
dot = NULL; /* dots have no meaning in dirs */
} else {
max = 65 - digits;
max = maxchar + 1 - digits;
}
name = full_name;
if (max < ucslen(name)) {
if ((size_t) max < ucslen(name)) {
name[max] = 0;
}
/* let ext be an empty string */
@ -446,7 +462,6 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
ok = 1;
/* change name of each file */
for (k = i; k <= j; ++k) {
uint16_t tmp[66];
while (1) {
ret = joliet_create_mangled_name(tmp, name, digits,
change, ext);
@ -508,7 +523,10 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
ret = ISO_SUCCESS;
mangle_cleanup : ;
ex:;
iso_htable_destroy(table, NULL);
LIBISO_FREE_MEM(tmp);
LIBISO_FREE_MEM(full_name);
return ret;
}
@ -742,8 +760,9 @@ void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id,
: (uint8_t*)node->name;
struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf;
IsoNode *iso;
len_dr = 33 + len_fi + (len_fi % 2 ? 0 : 1);
len_dr = 33 + len_fi + ((len_fi % 2) ? 0 : 1);
memcpy(rec->file_id, name, len_fi);
@ -781,7 +800,15 @@ void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id,
rec->len_dr[0] = len_dr;
iso_bb(rec->block, block - t->eff_partition_offset, 4);
iso_bb(rec->length, len, 4);
iso_datetime_7(rec->recording_time, t->now, t->always_gmt);
/* was: iso_datetime_7(rec->recording_time, t->now, t->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);
iso_bb(rec->vol_seq_number, (uint32_t) 1, 2);
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.bibliographic_file_id, biblio_file_id, 37);
iso_datetime_17(vol.vol_creation_time, t->now, t->always_gmt);
iso_datetime_17(vol.vol_modification_time, t->now, t->always_gmt);
iso_datetime_17(vol.vol_effective_time, t->now, t->always_gmt);
ecma119_set_voldescr_times(writer, (struct ecma119_pri_vol_desc *) &vol);
vol.file_structure_version[0] = 1;
free(vol_id);
@ -909,15 +934,16 @@ static
int write_one_dir(Ecma119Image *t, JolietNode *dir)
{
int ret;
uint8_t buffer[BLOCK_SIZE];
uint8_t *buffer = NULL;
size_t i;
size_t fi_len, len;
/* buf will point to current write position on buffer */
uint8_t *buf = buffer;
uint8_t *buf;
/* initialize buffer with 0s */
memset(buffer, 0, BLOCK_SIZE);
LIBISO_ALLOC_MEM(buffer, uint8_t, BLOCK_SIZE);
buf = buffer;
/* write the "." and ".." entries first */
write_one_dir_record(t, dir, 0, buf, 1, 0);
@ -944,7 +970,7 @@ int write_one_dir(Ecma119Image *t, JolietNode *dir)
/* dir doesn't fit in current block */
ret = iso_write(t, buffer, BLOCK_SIZE);
if (ret < 0) {
return ret;
goto ex;
}
memset(buffer, 0, BLOCK_SIZE);
buf = buffer;
@ -957,6 +983,8 @@ int write_one_dir(Ecma119Image *t, JolietNode *dir)
/* write the last block */
ret = iso_write(t, buffer, BLOCK_SIZE);
ex:;
LIBISO_FREE_MEM(buffer);
return ret;
}
@ -989,14 +1017,18 @@ static
int write_path_table(Ecma119Image *t, JolietNode **pathlist, int l_type)
{
size_t i, len;
uint8_t buf[256]; /* 256 is just a convenient size larger enought */
uint8_t *buf = NULL;
struct ecma119_path_table_record *rec;
void (*write_int)(uint8_t*, uint32_t, int);
JolietNode *dir;
uint32_t path_table_size;
int parent = 0;
int ret= ISO_SUCCESS;
uint8_t *zeros = NULL;
/* 256 is just a convenient size large enought */
LIBISO_ALLOC_MEM(buf, uint8_t, 256);
LIBISO_ALLOC_MEM(zeros, uint8_t, BLOCK_SIZE);
path_table_size = 0;
write_int = l_type ? iso_lsb : iso_msb;
@ -1023,7 +1055,7 @@ int write_path_table(Ecma119Image *t, JolietNode **pathlist, int l_type)
ret = iso_write(t, buf, len);
if (ret < 0) {
/* error */
return ret;
goto ex;
}
path_table_size += len;
}
@ -1031,11 +1063,13 @@ int write_path_table(Ecma119Image *t, JolietNode **pathlist, int l_type)
/* we need to fill the last block with zeros */
path_table_size %= BLOCK_SIZE;
if (path_table_size) {
uint8_t zeros[BLOCK_SIZE];
len = BLOCK_SIZE - path_table_size;
memset(zeros, 0, len);
ret = iso_write(t, zeros, len);
}
ex:;
LIBISO_FREE_MEM(zeros);
LIBISO_FREE_MEM(buf);
return ret;
}

View File

@ -18,6 +18,10 @@
#include "libisofs.h"
#include "ecma119.h"
/* was formerly 66 = 64 + 2. Now 105 = 103 + 2.
*/
#define LIBISO_JOLIET_NAME_MAX 105
enum joliet_node_type {
JOLIET_FILE,
JOLIET_DIR

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
LIBISOFS6 {
global:
aaip_xinfo_cloner;
aaip_xinfo_func;
el_torito_get_bootable;
el_torito_get_boot_media_type;
@ -64,9 +65,12 @@ iso_file_source_unref;
iso_filesystem_ref;
iso_filesystem_unref;
iso_finish;
iso_fs_global_id;
iso_get_local_charset;
iso_get_messenger;
iso_gzip_get_refcounts;
iso_hfsplus_xinfo_func;
iso_hfsplus_xinfo_new;
iso_image_add_boot_image;
iso_image_add_mips_boot_file;
iso_image_attach_data;
@ -87,6 +91,7 @@ iso_image_get_all_boot_imgs;
iso_image_get_application_id;
iso_image_get_attached_data;
iso_image_get_biblio_file_id;
iso_image_get_bootcat;
iso_image_get_boot_image;
iso_image_get_copyright_file_id;
iso_image_get_data_preparer_id;
@ -100,6 +105,8 @@ iso_image_get_system_id;
iso_image_get_volset_id;
iso_image_get_volume_id;
iso_image_give_up_mips_boot;
iso_image_hfsplus_bless;
iso_image_hfsplus_get_blessed;
iso_image_import;
iso_image_new;
iso_image_ref;
@ -123,6 +130,7 @@ iso_init;
iso_init_with_flag;
iso_lib_is_compatible;
iso_lib_version;
iso_local_attr_support;
iso_local_get_acl_text;
iso_local_get_attrs;
iso_local_get_perms_wo_acl;
@ -133,6 +141,7 @@ iso_md5_compute;
iso_md5_end;
iso_md5_match;
iso_md5_start;
iso_memory_stream_new;
iso_msgs_submit;
iso_new_find_conditions_and;
iso_new_find_conditions_atime;
@ -155,6 +164,7 @@ iso_node_get_hidden;
iso_node_get_mode;
iso_node_get_mtime;
iso_node_get_name;
iso_node_get_next_xinfo;
iso_node_get_old_image_lba;
iso_node_get_parent;
iso_node_get_permissions;
@ -165,6 +175,8 @@ iso_node_get_xinfo;
iso_node_lookup_attr;
iso_node_ref;
iso_node_remove;
iso_node_remove_all_xinfo;
iso_node_remove_tree;
iso_node_remove_xinfo;
iso_node_set_acl_text;
iso_node_set_atime;
@ -179,6 +191,8 @@ iso_node_set_sort_weight;
iso_node_set_uid;
iso_node_take;
iso_node_unref;
iso_node_xinfo_get_cloner;
iso_node_xinfo_make_clonable;
iso_node_zf_by_magic;
iso_obtain_msgs;
iso_read_image_features_destroy;
@ -209,6 +223,7 @@ iso_set_local_charset;
iso_set_msgs_severities;
iso_sev_to_text;
iso_special_get_dev;
iso_stream_clone;
iso_stream_close;
iso_stream_cmp_ino;
iso_stream_get_external_filter;
@ -234,6 +249,7 @@ iso_tree_add_new_node;
iso_tree_add_new_special;
iso_tree_add_new_symlink;
iso_tree_add_node;
iso_tree_clone;
iso_tree_get_follow_symlinks;
iso_tree_get_ignore_hidden;
iso_tree_get_ignore_special;
@ -241,6 +257,7 @@ iso_tree_get_node_path;
iso_tree_get_replace_mode;
iso_tree_path_to_node;
iso_tree_remove_exclude;
iso_tree_resolve_symlink;
iso_tree_set_follow_symlinks;
iso_tree_set_ignore_hidden;
iso_tree_set_ignore_special;
@ -254,7 +271,9 @@ iso_write_opts_get_data_start;
iso_write_opts_new;
iso_write_opts_set_aaip;
iso_write_opts_set_aaip_susp_1_10;
iso_write_opts_set_allow_7bit_ascii;
iso_write_opts_set_allow_deep_paths;
iso_write_opts_set_allow_dir_id_ext;
iso_write_opts_set_allow_full_ascii;
iso_write_opts_set_allow_longer_paths;
iso_write_opts_set_allow_lowercase;
@ -267,35 +286,46 @@ iso_write_opts_set_default_timestamp;
iso_write_opts_set_default_uid;
iso_write_opts_set_dir_rec_mtime;
iso_write_opts_set_disc_label;
iso_write_opts_set_efi_bootp;
iso_write_opts_set_fat;
iso_write_opts_set_fifo_size;
iso_write_opts_set_hardlinks;
iso_write_opts_set_hfsp_block_size;
iso_write_opts_set_hfsp_serial_number;
iso_write_opts_set_hfsplus;
iso_write_opts_set_iso1999;
iso_write_opts_set_iso_level;
iso_write_opts_set_joliet;
iso_write_opts_set_joliet_long_names;
iso_write_opts_set_joliet_longer_paths;
iso_write_opts_set_max_37_char_filenames;
iso_write_opts_set_ms_block;
iso_write_opts_set_no_force_dots;
iso_write_opts_set_old_empty;
iso_write_opts_set_omit_version_numbers;
iso_write_opts_set_output_charset;
iso_write_opts_set_overwrite_buf;
iso_write_opts_set_part_offset;
iso_write_opts_set_partition_img;
iso_write_opts_set_prep_img;
iso_write_opts_set_pvd_times;
iso_write_opts_set_record_md5;
iso_write_opts_set_relaxed_vol_atts;
iso_write_opts_set_replace_mode;
iso_write_opts_set_replace_timestamps;
iso_write_opts_set_rockridge;
iso_write_opts_set_rr_reloc;
iso_write_opts_set_rrip_1_10_px_ino;
iso_write_opts_set_rrip_version_1_10;
iso_write_opts_set_scdbackup_tag;
iso_write_opts_set_sort_files;
iso_write_opts_set_system_area;
iso_write_opts_set_tail_blocks;
iso_write_opts_set_untranslated_name_len;
iso_write_opts_set_will_cancel;
iso_zisofs_get_params;
iso_zisofs_get_refcounts;
iso_zisofs_set_params;
serial_id;
local: *;
};

View File

@ -4,7 +4,15 @@
#endif
#include <ctype.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#endif
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
@ -15,6 +23,11 @@
/* for gettimeofday() */
#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
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:
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,
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;
int i, warn_size = 0, id;
int i, id;
char *wpt;
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;
c = imgsize / cylsize;
if (c > 1024) {
warn_size = 1;
cc = 1024;
} else
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
int lba512chs_to_buf(char **wpt, off_t lba, int head_count, int sector_count)
{
@ -370,29 +388,206 @@ 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;
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;
for (i = 0; i < t->catalog->num_bootimages; 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
*/
int make_isolinux_mbr(int32_t *img_blocks, uint32_t boot_lba,
uint32_t mbr_id, int head_count, int sector_count,
int make_isolinux_mbr(int32_t *img_blocks, Ecma119Image *t,
int part_offset, int part_number, int fs_type,
uint8_t *buf, int flag)
{
uint32_t spc, id, part, nominal_part_size;
uint32_t id, part, nominal_part_size;
off_t hd_img_blocks, hd_boot_lba;
char *wpt;
uint32_t boot_lba, mbr_id;
int head_count, sector_count, ret;
int gpt_count = 0, gpt_idx[128], apm_count = 0, gpt_cursor;
/* For generating a weak random number */
struct timeval tv;
struct timezone tz;
/* Pad image_size to a multiple of sector_count*head_count
*/
spc = head_count * sector_count;
hd_img_blocks = ((off_t) *img_blocks) * (off_t) 4;
if (hd_img_blocks % spc) {
hd_img_blocks += spc - (hd_img_blocks % spc);
*img_blocks = hd_img_blocks / 4 + !!(hd_img_blocks % 4);
}
boot_lba = t->bootsrc[0]->sections[0].block;
mbr_id = 0;
head_count = t->partition_heads_per_cyl;
sector_count = t->partition_secs_per_head;
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;
@ -417,10 +612,21 @@ int make_isolinux_mbr(int32_t *img_blocks, uint32_t boot_lba,
/* # Offset 446
*/
gpt_cursor= 0;
for (part = 1 ; part <= 4; part++) {
if (part != part_number) {
/* if this_partition != partition_number: write 16 zero bytes */
if ((int) part != part_number) {
/* if this_partition != partition_number: write 16 zero bytes
(this is now overriden by the eventual desire to announce
EFI and HFS boot images.)
*/
memset(wpt, 0, 16);
if (gpt_cursor < gpt_count) {
ret = gpt_images_as_mbr_partitions(t, wpt, gpt_idx,
&gpt_cursor);
if (ret < 0)
return ret;
}
wpt+= 16;
continue;
}

View File

@ -12,7 +12,14 @@
#include "../config.h"
#endif
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@ -222,10 +229,10 @@ static int md5_init(libisofs_md5_ctx *ctx, int flag)
static int md5_update(libisofs_md5_ctx *ctx, unsigned char *data,
int datalen, int flag)
{
unsigned int i, index, partlen;
int i, index, partlen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((ctx->count[0] >> 3) & 0x3F);
index = ((ctx->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((ctx->count[0] += ((uint32_t) datalen << 3)) <
((uint32_t) datalen << 3))
@ -417,6 +424,22 @@ int checksum_cx_xinfo_func(void *data, int flag)
return 1;
}
/* The iso_node_xinfo_cloner function which gets associated to
* checksum_cx_xinfo_func by iso_init() resp. iso_init_with_flag() via
* iso_node_xinfo_make_clonable()
*/
int checksum_cx_xinfo_cloner(void *old_data, void **new_data, int flag)
{
*new_data = NULL;
if (flag)
return ISO_XINFO_NO_CLONE;
if (old_data == NULL)
return 0;
/* data is an int disguised as pointer. It does not point to memory. */
*new_data = old_data;
return 0;
}
/* Function to identify and manage md5 sums of unspecified providence stored
* directly in this xinfo.
@ -429,6 +452,24 @@ int checksum_md5_xinfo_func(void *data, int flag)
return 1;
}
/* The iso_node_xinfo_cloner function which gets associated to
* checksum_md5_xinfo_func by iso_init() resp. iso_init_with_flag() via
* iso_node_xinfo_make_clonable()
*/
int checksum_md5_xinfo_cloner(void *old_data, void **new_data, int flag)
{
*new_data = NULL;
if (flag)
return ISO_XINFO_NO_CLONE;
if (old_data == NULL)
return 0;
*new_data = calloc(1, 16);
if (*new_data == NULL)
return ISO_OUT_OF_MEM;
memcpy(*new_data, old_data, 16);
return 16;
}
/* ----------------------------------------------------------------------- */
@ -580,11 +621,6 @@ int checksum_writer_write_data(IsoImageWriter *writer)
void *ctx = NULL;
char md5[16];
#ifdef NIX
char tag_block[2048];
int l;
#endif
if (writer == NULL) {
return ISO_ASSERT_FAILURE;
}
@ -683,15 +719,16 @@ int iso_md5_write_scdbackup_tag(Ecma119Image *t, char *tag_block, int flag)
{
void *ctx = NULL;
off_t pos = 0, line_start;
int record_len, block_len, res, i;
char postext[40], md5[16], record[160];
int record_len, block_len, ret, i;
char postext[40], md5[16], *record = NULL;
LIBISO_ALLOC_MEM(record, char, 160);
line_start = strlen(tag_block);
iso_md5_compute(t->checksum_ctx, tag_block, line_start);
res = iso_md5_clone(t->checksum_ctx, &ctx);
if (res < 0)
ret = iso_md5_clone(t->checksum_ctx, &ctx);
if (ret < 0)
goto ex;
res = iso_md5_end(&ctx, md5);
ret = iso_md5_end(&ctx, md5);
pos = (off_t) t->checksum_tag_pos * (off_t) 2048 + line_start;
if(pos >= 1000000000)
@ -706,8 +743,8 @@ int iso_md5_write_scdbackup_tag(Ecma119Image *t, char *tag_block, int flag)
"%2.2x", ((unsigned char *) md5)[i]);
record_len += 32;
res = iso_md5_start(&ctx);
if (res < 0)
ret = iso_md5_start(&ctx);
if (ret < 0)
goto ex;
iso_md5_compute(ctx, record, record_len);
iso_md5_end(&ctx, md5);
@ -724,11 +761,12 @@ int iso_md5_write_scdbackup_tag(Ecma119Image *t, char *tag_block, int flag)
if (t->scdbackup_tag_written != NULL)
strncpy(t->scdbackup_tag_written, tag_block + line_start,
block_len - line_start);
res = ISO_SUCCESS;
ret = ISO_SUCCESS;
ex:;
if (ctx != NULL)
iso_md5_end(&ctx, md5);
return res;
LIBISO_FREE_MEM(record);
return ret;
}
@ -742,20 +780,20 @@ ex:;
*/
int iso_md5_write_tag(Ecma119Image *t, int flag)
{
int res, mode, l, i, wres, tag_id_len;
int ret, mode, l, i, wres, tag_id_len;
void *ctx = NULL;
char md5[16], tag_block[2048], *tag_id;
char md5[16], *tag_block = NULL, *tag_id;
uint32_t size = 0, pos = 0, start;
LIBISO_ALLOC_MEM(tag_block, char, 2048);
start = t->checksum_range_start;
memset(tag_block, 0, 2048);
mode = flag & 255;
if (mode < 1 || mode > 4)
return ISO_WRONG_ARG_VALUE;
res = iso_md5_clone(t->checksum_ctx, &ctx);
if (res < 0)
return res;
res = iso_md5_end(&ctx, md5);
{ret = ISO_WRONG_ARG_VALUE; goto ex;}
ret = iso_md5_clone(t->checksum_ctx, &ctx);
if (ret < 0)
goto ex;
ret = iso_md5_end(&ctx, md5);
if (mode == 1) {
size = t->checksum_range_size;
pos = t->checksum_tag_pos;
@ -770,7 +808,7 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
}
size = pos - start;
}
if (res < 0)
if (ret < 0)
goto ex;
iso_util_tag_magic(mode, &tag_id, &tag_id_len, 0);
@ -792,8 +830,8 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
((unsigned char *) md5)[i]);
l+= 32;
res = iso_md5_start(&ctx);
if (res > 0) {
ret = iso_md5_start(&ctx);
if (ret > 0) {
iso_md5_compute(ctx, tag_block, l);
iso_md5_end(&ctx, md5);
strcpy(tag_block + l, " self=");
@ -808,8 +846,8 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
if (t->ms_block > 0) {
iso_msg_submit(t->image->id, ISO_SCDBACKUP_TAG_NOT_0, 0, NULL);
} else {
res = iso_md5_write_scdbackup_tag(t, tag_block, 0);
if (res < 0)
ret = iso_md5_write_scdbackup_tag(t, tag_block, 0);
if (ret < 0)
goto ex;
}
}
@ -820,16 +858,17 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
} else {
wres = iso_write(t, tag_block, 2048);
if (wres < 0) {
res = wres;
ret = wres;
goto ex;
}
}
res = ISO_SUCCESS;
ret = ISO_SUCCESS;
ex:;
if (ctx != NULL)
iso_md5_end(&ctx, md5);
return res;
LIBISO_FREE_MEM(tag_block);
return ret;
}

View File

@ -1,5 +1,6 @@
/*
* 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
* modify it under the terms of the GNU General Public License version 2
@ -36,6 +37,7 @@
#include "messages.h"
#include "util.h"
#include "node.h"
/*
@ -79,11 +81,76 @@ int abort_threshold = LIBISO_MSGS_SEV_FAILURE;
struct libiso_msgs *libiso_msgr = NULL;
/* ------------- List of xinfo clone functions ----------- */
struct iso_xinfo_cloner_assoc {
iso_node_xinfo_func proc;
iso_node_xinfo_cloner cloner;
struct iso_xinfo_cloner_assoc *next;
};
struct iso_xinfo_cloner_assoc *iso_xinfo_cloner_list = NULL;
/* API */
int iso_node_xinfo_make_clonable(iso_node_xinfo_func proc,
iso_node_xinfo_cloner cloner, int flag)
{
struct iso_xinfo_cloner_assoc *assoc;
/* Look for existing assoc of proc */
for (assoc = iso_xinfo_cloner_list; assoc != NULL; assoc = assoc->next)
if (assoc->proc == proc)
break;
if (assoc == NULL) {
assoc = calloc(1, sizeof(struct iso_xinfo_cloner_assoc));
if (assoc == NULL)
return ISO_OUT_OF_MEM;
assoc->proc = proc;
assoc->next = iso_xinfo_cloner_list;
iso_xinfo_cloner_list = assoc;
}
assoc->cloner = cloner;
return ISO_SUCCESS;
}
/* API */
int iso_node_xinfo_get_cloner(iso_node_xinfo_func proc,
iso_node_xinfo_cloner *cloner, int flag)
{
struct iso_xinfo_cloner_assoc *assoc;
*cloner = NULL;
for (assoc = iso_xinfo_cloner_list; assoc != NULL; assoc = assoc->next) {
if (assoc->proc != proc)
continue;
*cloner = assoc->cloner;
return 1;
}
return 0;
}
static
int iso_node_xinfo_dispose_cloners(int flag)
{
struct iso_xinfo_cloner_assoc *assoc, *next;
for (assoc = iso_xinfo_cloner_list; assoc != NULL; assoc = next) {
next = assoc->next;
free((char *) assoc);
}
return(1);
}
/* ------------- End of xinfo clone functions list ----------- */
/*
@param flag bit0= do not set up locale by LC_* environment variables
*/
int iso_init_with_flag(int flag)
{
int ret;
#ifdef Libisofs_with_libjtE
@ -119,7 +186,6 @@ LIBJTE_MISCONFIGURATION_ = 0;
#endif /* Libisofs_with_libjtE */
if (! (flag & 1)) {
iso_init_locale(0);
}
@ -129,10 +195,33 @@ LIBJTE_MISCONFIGURATION_ = 0;
}
libiso_msgs_set_severities(libiso_msgr, LIBISO_MSGS_SEV_NEVER,
LIBISO_MSGS_SEV_FATAL, "libisofs: ", 0);
ret = iso_node_xinfo_make_clonable(aaip_xinfo_func, aaip_xinfo_cloner, 0);
if (ret < 0)
return ret;
ret = iso_node_xinfo_make_clonable(checksum_cx_xinfo_func,
checksum_cx_xinfo_cloner, 0);
if (ret < 0)
return ret;
ret = iso_node_xinfo_make_clonable(checksum_md5_xinfo_func,
checksum_md5_xinfo_cloner, 0);
if (ret < 0)
return ret;
ret = iso_node_xinfo_make_clonable(zisofs_zf_xinfo_func,
zisofs_zf_xinfo_cloner, 0);
if (ret < 0)
return ret;
ret = iso_node_xinfo_make_clonable(iso_px_ino_xinfo_func,
iso_px_ino_xinfo_cloner, 0);
if (ret < 0)
return ret;
ret = iso_node_xinfo_make_clonable(iso_hfsplus_xinfo_func,
iso_hfsplus_xinfo_cloner, 0);
if (ret < 0)
return ret;
return 1;
}
int iso_init()
{
return iso_init_with_flag(0);
@ -141,6 +230,7 @@ int iso_init()
void iso_finish()
{
libiso_msgs_destroy(&libiso_msgr, 0);
iso_node_xinfo_dispose_cloners(0);
}
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, ...)
{
char msg[MAX_MSG_LEN];
char *msg = NULL;
va_list ap;
LIBISO_ALLOC_MEM_VOID(msg, char, MAX_MSG_LEN);
va_start(ap, fmt);
vsnprintf(msg, MAX_MSG_LEN, fmt, ap);
va_end(ap);
libiso_msgs_submit(libiso_msgr, imgid, 0x00000002, LIBISO_MSGS_SEV_DEBUG,
LIBISO_MSGS_PRIO_ZERO, msg, 0, 0);
ex:;
LIBISO_FREE_MEM(msg);
}
const char *iso_error_to_msg(int errcode)
@ -358,9 +451,55 @@ const char *iso_error_to_msg(int errcode)
case ISO_BAD_PARTITION_FILE:
return "Cannot open data file for appended partition";
case ISO_NON_MBR_SYS_AREA:
return "May not combine appended partition with non-MBR system area";
return "May not combine MBR partition with non-MBR system area";
case ISO_DISPLACE_ROLLOVER:
return "Displacement offset leads outside 32 bit range";
case ISO_NAME_NEEDS_TRANSL:
return "File name cannot be written into ECMA-119 untranslated";
case ISO_STREAM_NO_CLONE:
return "Data file input stream object offers no cloning method";
case ISO_XINFO_NO_CLONE:
return "Extended information class offers no cloning method";
case ISO_MD5_TAG_COPIED:
return "Found copied superblock checksum tag";
case ISO_RR_NAME_TOO_LONG:
return "Rock Ridge leaf name too long";
case ISO_RR_NAME_RESERVED:
return "Reserved Rock Ridge leaf name";
case ISO_RR_PATH_TOO_LONG:
return "Rock Ridge path too long";
case ISO_AAIP_BAD_ATTR_NAME:
return "Attribute name cannot be represented";
case ISO_AAIP_ACL_MULT_OBJ:
return "ACL text contains multiple entries of user::, group::, other::";
case ISO_SECT_SCATTERED:
return "File sections do not form consecutive array of blocks";
case ISO_BOOT_TOO_MANY_APM:
return "Too many Apple Partition Map entries requested";
case ISO_BOOT_APM_OVERLAP:
return "Overlapping Apple Partition Map entries requested";
case ISO_BOOT_TOO_MANY_GPT:
return "Too many GPT entries requested";
case ISO_BOOT_GPT_OVERLAP:
return "Overlapping GPT entries requested";
case ISO_BOOT_TOO_MANY_MBR:
return "Too many MBR partition entries requested";
case ISO_BOOT_MBR_OVERLAP:
return "Overlapping MBR partition entries requested";
case ISO_BOOT_MBR_COLLISION:
return "Attempt to use an MBR partition entry twice";
case ISO_BOOT_NO_EFI_ELTO:
return "No suitable El Torito EFI boot image for exposure as GPT partition";
case ISO_BOOT_HFSP_BAD_BSIZE:
return "Not a supported HFS+ or APM block size";
case ISO_BOOT_APM_GPT_BSIZE:
return "APM block size prevents coexistence with GPT";
case ISO_HFSP_NO_MANGLE:
return "Name collision in HFS+, mangling not possible";
case ISO_DEAD_SYMLINK:
return "Symbolic link cannot be resolved";
case ISO_DEEP_SYMLINK:
return "Too many chained symbolic links";
default:
return "Unknown error";
}
@ -380,7 +519,7 @@ int iso_msg_submit(int imgid, int errcode, int causedby, const char *fmt, ...)
va_list ap;
/* when called with ISO_CANCELED, we don't need to submit any message */
if (errcode == ISO_CANCELED && fmt == NULL) {
if (errcode == (int) ISO_CANCELED && fmt == NULL) {
return ISO_CANCELED;
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt
* Copyright (c) 2009 - 2011 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -19,6 +19,7 @@
#include "aaip_0_2.h"
#include "messages.h"
#include "util.h"
#include "eltorito.h"
#include <stdlib.h>
@ -28,11 +29,6 @@
#include <stdio.h>
#ifndef PATH_MAX
#define PATH_MAX Libisofs_default_path_maX
#endif
struct dir_iter_data
{
/* points to the last visited child, to NULL before start */
@ -59,6 +55,8 @@ void iso_node_ref(IsoNode *node)
*/
void iso_node_unref(IsoNode *node)
{
if (node == NULL)
return;
if (--node->refcount == 0) {
switch (node->type) {
case LIBISO_DIR:
@ -83,6 +81,14 @@ void iso_node_unref(IsoNode *node)
IsoSymlink *link = (IsoSymlink*) node;
free(link->dest);
}
break;
case LIBISO_BOOT:
{
IsoBoot *bootcat = (IsoBoot *) node;
if (bootcat->content != NULL)
free(bootcat->content);
}
break;
default:
/* other kind of nodes does not need to delete anything here */
break;
@ -226,6 +232,89 @@ int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data)
return 0;
}
/* API */
int iso_node_get_next_xinfo(IsoNode *node, void **handle,
iso_node_xinfo_func *proc, void **data)
{
IsoExtendedInfo *xinfo;
if (node == NULL || handle == NULL || proc == NULL || data == NULL)
return ISO_NULL_POINTER;
*proc = NULL;
*data = NULL;
xinfo = (IsoExtendedInfo *) *handle;
if (xinfo == NULL)
xinfo = node->xinfo;
else
xinfo = xinfo->next;
*handle = xinfo;
if (xinfo == NULL)
return 0;
*proc = xinfo->process;
*data = xinfo->data;
return ISO_SUCCESS;
}
int iso_node_remove_all_xinfo(IsoNode *node, int flag)
{
IsoExtendedInfo *pos, *next;
for (pos = node->xinfo; pos != NULL; pos = next) {
next = pos->next;
pos->process(pos->data, 1);
free((char *) pos);
}
node->xinfo = NULL;
return ISO_SUCCESS;
}
static
int iso_node_revert_xinfo_list(IsoNode *node, int flag)
{
IsoExtendedInfo *pos, *next, *prev = NULL;
for (pos = node->xinfo; pos != NULL; pos = next) {
next = pos->next;
pos->next = prev;
prev = pos;
}
node->xinfo = prev;
return ISO_SUCCESS;
}
int iso_node_clone_xinfo(IsoNode *from_node, IsoNode *to_node, int flag)
{
void *handle = NULL, *data, *new_data;
iso_node_xinfo_func proc;
iso_node_xinfo_cloner cloner;
int ret;
iso_node_remove_all_xinfo(to_node, 0);
while (1) {
ret = iso_node_get_next_xinfo(from_node, &handle, &proc, &data);
if (ret <= 0)
break;
ret = iso_node_xinfo_get_cloner(proc, &cloner, 0);
if (ret == 0)
return ISO_XINFO_NO_CLONE;
if (ret < 0)
return ret;
ret = (*cloner)(data, &new_data, 0);
if (ret < 0)
break;
ret = iso_node_add_xinfo(to_node, proc, new_data);
if (ret < 0)
break;
}
if (ret < 0) {
iso_node_remove_all_xinfo(to_node, 0);
} else {
ret = iso_node_revert_xinfo_list(to_node, 0);
}
return ret;
}
/**
* Get the type of an IsoNode.
*/
@ -242,6 +331,7 @@ enum IsoNodeType iso_node_get_type(IsoNode *node)
int iso_node_set_name(IsoNode *node, const char *name)
{
char *new;
int ret;
if ((IsoNode*)node->parent == 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 */
if (!iso_node_is_valid_name(name)) {
return ISO_WRONG_ARG_VALUE;
}
ret = iso_node_is_valid_name(name);
if (ret < 0)
return ret;
if (node->parent != NULL) {
/* check if parent already has a node with same name */
@ -651,6 +741,9 @@ int iso_node_take(IsoNode *node)
if (dir == NULL) {
return ISO_NODE_NOT_ADDED_TO_DIR;
}
/* >>> Do not take root directory ! (dir == node) ? */;
pos = iso_dir_find_node(dir, node);
if (pos == NULL) {
/* should never occur */
@ -686,6 +779,44 @@ int iso_node_remove(IsoNode *node)
return ret;
}
/* API */
int iso_node_remove_tree(IsoNode *node, IsoDirIter *boss_iter)
{
IsoDirIter *iter = NULL;
IsoNode *sub_node;
int ret;
if (node->type != LIBISO_DIR) {
/* >>> Do not remove root directory ! (node->parent == node) ? */;
ret = iso_dir_get_children((IsoDir *) node, &iter);
if (ret < 0)
goto ex;
while(1) {
ret = iso_dir_iter_next(iter, &sub_node);
if (ret == 0)
break;
ret = iso_node_remove_tree(sub_node, iter);
if (ret < 0)
goto ex;
}
if (node->parent == NULL) {
/* node is not grafted into a boss directory */
iso_node_unref(node);
goto ex;
}
}
if (boss_iter != NULL)
ret = iso_dir_iter_remove(boss_iter);
else
ret = iso_node_remove(node);
ex:;
if (iter != NULL)
iso_dir_iter_free(iter);
return ret;
}
/*
* Get the parent of the given iso tree node. No extra ref is added to the
* returned directory, you must take your ref. with iso_node_ref() if you
@ -881,10 +1012,11 @@ const char *iso_symlink_get_dest(const IsoSymlink *link)
int iso_symlink_set_dest(IsoSymlink *link, const char *dest)
{
char *d;
if (!iso_node_is_valid_link_dest(dest)) {
/* guard against null or empty dest */
return ISO_WRONG_ARG_VALUE;
}
int ret;
ret = iso_node_is_valid_link_dest(dest);
if (ret < 0)
return ret;
d = strdup(dest);
if (d == NULL) {
return ISO_OUT_OF_MEM;
@ -1035,22 +1167,23 @@ int iso_node_is_valid_name(const char *name)
{
/* a name can't be NULL */
if (name == NULL) {
return 0;
return ISO_NULL_POINTER;
}
/* guard against the empty string or big names... */
if (name[0] == '\0' || strlen(name) > 255) {
return 0;
}
if (name[0] == '\0')
return ISO_RR_NAME_RESERVED;
if (strlen(name) > LIBISOFS_NODE_NAME_MAX)
return ISO_RR_NAME_TOO_LONG;
/* ...against "." and ".." names... */
if (!strcmp(name, ".") || !strcmp(name, "..")) {
return 0;
return ISO_RR_NAME_RESERVED;
}
/* ...and against names with '/' */
if (strchr(name, '/') != NULL) {
return 0;
return ISO_RR_NAME_RESERVED;
}
return 1;
}
@ -1068,13 +1201,14 @@ int iso_node_is_valid_link_dest(const char *dest)
/* a dest can't be NULL */
if (dest == NULL) {
return 0;
return ISO_NULL_POINTER;
}
/* guard against the empty string or big dest... */
if (dest[0] == '\0' || strlen(dest) > PATH_MAX) {
return 0;
}
if (dest[0] == '\0')
return ISO_RR_NAME_RESERVED;
if (strlen(dest) > LIBISOFS_NODE_PATH_MAX)
return ISO_RR_PATH_TOO_LONG;
/* check that all components are valid */
if (!strcmp(dest, "/")) {
@ -1084,7 +1218,7 @@ int iso_node_is_valid_link_dest(const char *dest)
ptr = strdup(dest);
if (ptr == NULL) {
return 0;
return ISO_OUT_OF_MEM;
}
ret = 1;
@ -1092,7 +1226,7 @@ int iso_node_is_valid_link_dest(const char *dest)
while (component) {
if (strcmp(component, ".") && strcmp(component, "..")) {
ret = iso_node_is_valid_name(component);
if (ret == 0) {
if (ret < 0) {
break;
}
}
@ -1251,15 +1385,16 @@ int iso_node_new_root(IsoDir **root)
int iso_node_new_dir(char *name, IsoDir **dir)
{
IsoDir *new;
int ret;
if (dir == NULL || name == NULL) {
return ISO_NULL_POINTER;
}
/* check if the name is valid */
if (!iso_node_is_valid_name(name)) {
return ISO_WRONG_ARG_VALUE;
}
ret = iso_node_is_valid_name(name);
if (ret < 0)
return ret;
new = calloc(1, sizeof(IsoDir));
if (new == NULL) {
@ -1276,15 +1411,16 @@ int iso_node_new_dir(char *name, IsoDir **dir)
int iso_node_new_file(char *name, IsoStream *stream, IsoFile **file)
{
IsoFile *new;
int ret;
if (file == NULL || name == NULL || stream == NULL) {
return ISO_NULL_POINTER;
}
/* check if the name is valid */
if (!iso_node_is_valid_name(name)) {
return ISO_WRONG_ARG_VALUE;
}
ret = iso_node_is_valid_name(name);
if (ret < 0)
return ret;
new = calloc(1, sizeof(IsoFile));
if (new == NULL) {
@ -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)
{
IsoSymlink *new;
int ret;
if (link == NULL || name == NULL || dest == NULL) {
return ISO_NULL_POINTER;
}
/* check if the name is valid */
if (!iso_node_is_valid_name(name)) {
return ISO_WRONG_ARG_VALUE;
}
ret = iso_node_is_valid_name(name);
if (ret < 0)
return ret;
/* check if destination is valid */
if (!iso_node_is_valid_link_dest(dest)) {
/* guard against null or empty dest */
return ISO_WRONG_ARG_VALUE;
}
ret = iso_node_is_valid_link_dest(dest);
if (ret < 0)
return ret;
new = calloc(1, sizeof(IsoSymlink));
if (new == NULL) {
@ -1340,6 +1476,7 @@ int iso_node_new_special(char *name, mode_t mode, dev_t dev,
IsoSpecial **special)
{
IsoSpecial *new;
int ret;
if (special == NULL || name == NULL) {
return ISO_NULL_POINTER;
@ -1349,9 +1486,9 @@ int iso_node_new_special(char *name, mode_t mode, dev_t dev,
}
/* check if the name is valid */
if (!iso_node_is_valid_name(name)) {
return ISO_WRONG_ARG_VALUE;
}
ret = iso_node_is_valid_name(name);
if (ret < 0)
return ret;
new = calloc(1, sizeof(IsoSpecial));
if (new == NULL) {
@ -1447,7 +1584,7 @@ int iso_aa_get_attrs(unsigned char *aa_string, size_t *num_attrs,
goto ex;
}
if (rpt - aa_string != len) {
if ((size_t) (rpt - aa_string) != len) {
/* aaip_decode_attrs() returns 2 but still bytes are left */
ret = ISO_AAIP_BAD_AASTRING;
goto ex;
@ -1489,13 +1626,15 @@ int iso_aa_lookup_attr(unsigned char *aa_string, char *name,
ret = iso_aa_get_attrs(aa_string, &num_attrs, &names,
&value_lengths, &values, 0);
for (i = 0; i < num_attrs; i++) {
if (ret < 0)
return ret;
for (i = 0; i < (int) num_attrs; i++) {
if (strcmp(names[i], name))
continue;
*value_length = value_lengths[i];
*value = calloc(*value_length + 1, 1);
if (*value == NULL) {
ret = ISO_OUT_OF_MEM;
found = ISO_OUT_OF_MEM;
break;
}
if (*value_length > 0)
@ -1588,6 +1727,7 @@ int attr_enlarge_list(char ***names, size_t **value_lengths, char ***values,
bit2= delete the given names rather than overwrite
their content
bit4= do not overwrite value of empty name
bit5= do not overwrite isofs attributes
bit15= release memory and return 1
*/
static
@ -1636,6 +1776,8 @@ int iso_node_merge_xattr(IsoNode *node, size_t num_attrs, char **names,
continue;
if (names[i][0] == 0 && (flag & 16))
continue;
if ((flag & 32) && strncmp(names[i], "isofs.", 6) == 0)
continue;
for (j = 0; j < *m_num_attrs; j++) {
if ((*m_names)[j] == NULL)
continue;
@ -1681,6 +1823,8 @@ int iso_node_merge_xattr(IsoNode *node, size_t num_attrs, char **names,
continue;
if (names[i][0] == 0 && (flag & 16))
continue;
if ((flag & 32) && strncmp(names[i], "isofs.", 6) == 0)
continue;
for (j = 0; j < *m_num_attrs; j++) {
if ((*m_names)[j] == NULL)
continue;
@ -1731,13 +1875,13 @@ int iso_node_set_attrs(IsoNode *node, size_t num_attrs, char **names,
for (i = 0; i < num_attrs; i++)
if (strncmp(names[i], "user.", 5) != 0 && names[i][0] != 0)
return ISO_AAIP_NON_USER_NAME;
if ((flag & (2 | 4)) || !(flag & 8)) {
if ((flag & (2 | 4 | 16)) || !(flag & 8)) {
/* Merge old and new lists */
ret = iso_node_merge_xattr(
node, num_attrs, names, value_lengths, values,
&m_num, &m_names, &m_value_lengths, &m_values,
(flag & 4) | (!(flag & 2)) | ((!(flag & 1)) << 4));
(flag & 4) | (!(flag & 2)) | ((!(flag & 1)) << 4) |
((flag & 16) << 1));
if (ret < 0)
goto ex;
num_attrs = m_num;
@ -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,
&acl_len, &acl, 2 | 8);
}
if (ret <= 0) {
if (ret == -1)
ret = ISO_OUT_OF_MEM;
else if (ret <= 0 && ret >= -3)
ret = ISO_AAIP_BAD_ACL_TEXT;
if (ret <= 0)
goto ex;
}
if(acl == NULL) { /* Delete whole ACL attribute */
/* Update S_IRWXG by eventual "group::" ACL entry.
@ -2068,6 +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,
st_mode, &acl_len, &acl, 2 | 8);
if (ret < -3)
goto ex;
if (ret <= 0) {
ret = ISO_AAIP_BAD_ACL_TEXT;
goto ex;
@ -2153,6 +2301,23 @@ int zisofs_zf_xinfo_func(void *data, int flag)
return 1;
}
/* The iso_node_xinfo_cloner function which gets associated to
* zisofs_zf_xinfo_func by iso_init() resp. iso_init_with_flag() via
* iso_node_xinfo_make_clonable()
*/
int zisofs_zf_xinfo_cloner(void *old_data, void **new_data, int flag)
{
*new_data = NULL;
if (flag)
return ISO_XINFO_NO_CLONE;
if (old_data == NULL)
return 0;
*new_data = calloc(1, sizeof(struct zisofs_zf_info));
if (*new_data == NULL)
return ISO_OUT_OF_MEM;
memcpy(*new_data, old_data, sizeof(struct zisofs_zf_info));
return (int) sizeof(struct zisofs_zf_info);
}
/* Checks whether a file effectively bears a zisofs file header and eventually
* marks this by a struct zisofs_zf_info as xinfo of the file node.
@ -2274,6 +2439,21 @@ int iso_px_ino_xinfo_func(void *data, int flag)
return 1;
}
/* The iso_node_xinfo_cloner function which gets associated to
* iso_px_ino_xinfo_func by iso_init() resp. iso_init_with_flag() via
* iso_node_xinfo_make_clonable()
*/
int iso_px_ino_xinfo_cloner(void *old_data, void **new_data, int flag)
{
*new_data = NULL;
if (flag)
return ISO_XINFO_NO_CLONE;
*new_data = calloc(1, sizeof(ino_t));
if (*new_data == NULL)
return ISO_OUT_OF_MEM;
memcpy(*new_data, old_data, sizeof(ino_t));
return (int) sizeof(ino_t);
}
/*
* @param flag
@ -2364,7 +2544,6 @@ int iso_node_set_ino_xinfo(IsoNode *node, ino_t ino, int flag)
return ret;
}
int iso_node_set_ino(IsoNode *node, ino_t ino, int flag)
{
int ret;
@ -2693,7 +2872,7 @@ int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag)
ret = 0;
goto ex;
}
for (i = 0; i < value_len; i++)
for (i = 0; i < (int) value_len; i++)
idx = (idx << 8) | ((unsigned char *) value)[i];
if (idx == 0 || idx > image->checksum_idx_count - 1) {
/* (last index is not MD5 of a file) */

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt
* Copyright (c) 2009 - 2011 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -20,7 +20,38 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#endif
/* Maximum length of a leaf name in the libisofs node tree. This is currently
restricted by the implemented maximum length of a Rock Ridge name.
This might later become larger and may then be limited to smaller values.
Rock Ridge specs do not impose an explicit limit on name length.
But 255 is also specified by
http://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html
which says
NAME_MAX >= _XOPEN_NAME_MAX = 255
*/
#define LIBISOFS_NODE_NAME_MAX 255
/* Maximum length of a path in the libisofs node tree.
Rock Ridge specs do not impose an explicit limit on path length.
http://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html
says
PATH_MAX >= _XOPEN_PATH_MAX = 1024
*/
#define LIBISOFS_NODE_PATH_MAX 1024
/**
* The extended information is a way to attach additional information to each
@ -113,6 +144,7 @@ struct Iso_Dir
IsoNode *children; /**< list of children. ptr to first child */
};
/* IMPORTANT: Any change must be reflected by iso_tree_clone_file. */
struct Iso_File
{
IsoNode node;
@ -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.
*
* @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);
@ -473,4 +505,35 @@ int iso_root_get_isofsca(IsoNode *node, uint32_t *start_lba, uint32_t *end_lba,
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_*/

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* 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
* modify it under the terms of the GNU General Public License version 2
@ -13,6 +13,9 @@
#include "../config.h"
#endif
#include <string.h>
#include <stdio.h>
#include "rockridge.h"
#include "node.h"
#include "ecma119_tree.h"
@ -22,7 +25,12 @@
#include "aaip_0_2.h"
#include "libisofs.h"
#include <string.h>
#ifdef Libisofs_with_rrip_rR
#define ISO_ROCKRIDGE_IN_DIR_REC 128
#else
#define ISO_ROCKRIDGE_IN_DIR_REC 124
#endif
static
@ -329,7 +337,12 @@ static
int rrip_add_NM(Ecma119Image *t, struct susp_info *susp, char *name, int size,
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) {
return ISO_OUT_OF_MEM;
}
@ -393,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
/**
* Add to the given tree node a RR System Use Entry. This is an obsolete
* entry from before RRIP-1.10. Nevertheless mkisofs produces it and there
* is the suspicion that Solaris takes it as indication for Rock Ridge.
* 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. There
* 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 same constant 5 bytes as produced by mkisofs.
* The meaning of the payload byte is documented e.g. in
* /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
int rrip_add_RR(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp)
@ -413,7 +429,14 @@ int rrip_add_RR(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp)
RR[1] = 'R';
RR[2] = 5;
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);
}
@ -437,8 +460,8 @@ static
int rrip_add_SL(Ecma119Image *t, struct susp_info *susp, uint8_t **comp,
size_t n, int ce)
{
int ret, i, j;
int ret;
size_t i, j;
int total_comp_len = 0;
size_t pos, written = 0;
@ -897,7 +920,7 @@ int add_zf_field(Ecma119Image *t, Ecma119Node *n, struct susp_info *info,
return 1;
}
/* API */
int aaip_xinfo_func(void *data, int flag)
{
if (flag & 1) {
@ -906,6 +929,23 @@ int aaip_xinfo_func(void *data, int flag)
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
@ -920,6 +960,7 @@ int aaip_xinfo_func(void *data, int flag)
* (*su_size and *ce stay unaltered in this case)
* <0= error:
* -1= not enough SUA space for 28 bytes of CE entry
* -2= out of memory
*/
static
int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
@ -956,6 +997,12 @@ int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
if (!(flag & 1))
goto unannounced_ca;
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;
*su_size = space;
}
@ -968,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 ? */
dest = get_rr_fname(t, ((IsoSymlink*)n->node)->dest);
if (dest == NULL)
return -2;
prev = dest;
cur = strchr(prev, '/');
while (1) {
@ -996,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
* will be completelly moved into the CA
*/
if (!(flag & 1))
if (!(flag & 1)) {
free(dest);
goto unannounced_ca;
}
cew = 1;
} else {
sl_len += clen;
@ -1016,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
* SL field
*/
int fit = 255 - sl_len - 2;
if (clen - 250 <= fit) {
ssize_t fit = 255 - sl_len - 2;
if ((ssize_t) (clen - 250) <= fit) {
/*
* the component can be divided between this
* and another SL entry
@ -1097,134 +1148,8 @@ unannounced_ca:;
}
/**
* Compute the length needed for write all RR and SUSP entries for a given
* node.
*
* @param type
* 0 normal entry, 1 "." entry for that node (it is a dir), 2 ".."
* for that node (i.e., it will refer to the parent)
* @param space
* Available space in the System Use Area for the directory record.
* @param ce
* Will be filled with the space needed in a CE
* @return
* The size needed for the RR entries in the System Use Area
*/
size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t space,
size_t *ce)
{
size_t su_size;
int ret;
/* space min is 255 - 33 - 37 = 185
* At the same time, it is always an odd number, but we need to pad it
* propertly to ensure the length of a directory record is a even number
* (ECMA-119, 9.1.13). Thus, in fact the real space is always space - 1
*/
space--;
*ce = 0;
su_size = 0;
/* If AAIP enabled and announced by ER : account for 5 bytes of ES */;
if (t->aaip && !t->aaip_susp_1_10)
su_size += 5;
#ifdef Libisofs_with_rrip_rR
/* obsolete RR field (once in RRIP-1.09) */
su_size += 5;
#endif
/* PX and TF, we are sure they always fit in SUA */
if (t->rrip_1_10_px_ino || !t->rrip_version_1_10) {
su_size += 44 + 26;
} else {
su_size += 36 + 26;
}
if (n->type == ECMA119_DIR) {
if (n->info.dir->real_parent != NULL) {
/* it is a reallocated entry */
if (type == 2) {
/* we need to add a PL entry */
su_size += 12;
} else if (type == 0) {
/* we need to add a RE entry */
su_size += 4;
}
}
} else if (n->type == ECMA119_SPECIAL) {
if (S_ISBLK(n->node->mode) || S_ISCHR(n->node->mode)) {
/* block or char device, we need a PN entry */
su_size += 20;
}
} else if (n->type == ECMA119_PLACEHOLDER) {
/* we need the CL entry */
su_size += 12;
}
if (type == 0) {
/* Try without CE */
ret = susp_calc_nm_sl_al(t, n, space, &su_size, ce, 0);
if (ret == 0) /* Retry with CE */
susp_calc_nm_sl_al(t, n, space, &su_size, ce, 1);
} else {
/* "." or ".." entry */
su_size += 5; /* NM field */
if (type == 1 && n->parent == NULL) {
/*
* "." for root directory
* we need to write SP and ER entries. The first fits in SUA,
* ER needs a Continuation Area, thus we also need a CE entry
*/
su_size += 7 + 28; /* SP + CE */
/* ER of RRIP */
if (t->rrip_version_1_10) {
*ce = 237;
} else {
*ce = 182;
}
if (t->aaip) {
*ce += 160; /* ER of AAIP */
}
}
}
/*
* The System Use field inside the directory record must be padded if
* it is an odd number (ECMA-119, 9.1.13)
*/
su_size += (su_size % 2);
return su_size;
}
/**
* Free all info in a struct susp_info.
*/
static
void susp_info_free(struct susp_info* susp)
{
size_t i;
for (i = 0; i < susp->n_susp_fields; ++i) {
free(susp->susp_fields[i]);
}
free(susp->susp_fields);
for (i = 0; i < susp->n_ce_susp_fields; ++i) {
free(susp->ce_susp_fields[i]);
}
free(susp->ce_susp_fields);
}
/* @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,
@ -1261,6 +1186,150 @@ int add_aa_string(Ecma119Image *t, Ecma119Node *n, struct susp_info *info,
}
/**
* Compute the length needed for write all RR and SUSP entries for a given
* node.
*
* @param type
* 0 normal entry, 1 "." entry for that node (it is a dir), 2 ".."
* for that node (i.e., it will refer to the parent)
* @param used_up
* Already occupied space in the directory record.
* @param ce
* Will be filled with the space needed in a CE
* @return
* The size needed for the RR entries in the System Use Area
*/
size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t used_up,
size_t *ce)
{
size_t su_size, space;
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.
*/
space = 254 - used_up - (used_up % 2);
if (type < 0 || type > 2 || space < ISO_ROCKRIDGE_IN_DIR_REC) {
iso_msg_submit(t->image->id, ISO_ASSERT_FAILURE, 0,
"Unknown node type %d or short RR space %d < %d in directory record",
type, (int) space, ISO_ROCKRIDGE_IN_DIR_REC);
return ISO_ASSERT_FAILURE;
}
*ce = 0;
su_size = 0;
/* If AAIP enabled and announced by ER : account for 5 bytes of ES */;
if (t->aaip && !t->aaip_susp_1_10)
su_size += 5;
#ifdef Libisofs_with_rrip_rR
/* obsolete RR field (once in RRIP-1.09) */
su_size += 5;
#endif
/* PX and TF, we are sure they always fit in SUA */
if (t->rrip_1_10_px_ino || !t->rrip_version_1_10) {
su_size += 44 + 26;
} else {
su_size += 36 + 26;
}
if (n->type == ECMA119_DIR) {
if (n->info.dir->real_parent != NULL) {
/* it is a reallocated entry */
if (type == 2) {
/* we need to add a PL entry */
su_size += 12;
} else if (type == 0) {
/* we need to add a RE entry */
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) {
if (S_ISBLK(n->node->mode) || S_ISCHR(n->node->mode)) {
/* block or char device, we need a PN entry */
su_size += 20;
}
} else if (n->type == ECMA119_PLACEHOLDER) {
/* we need the CL entry */
su_size += 12;
}
if (type == 0) {
/* Try without CE */
ret = susp_calc_nm_sl_al(t, n, space, &su_size, ce, 0);
if (ret == 0) /* Retry with CE */
ret = susp_calc_nm_sl_al(t, n, space, &su_size, ce, 1);
if (ret == -2)
return ISO_OUT_OF_MEM;
} else {
/* "." or ".." entry */
if (!t->rrip_version_1_10)
su_size += 5; /* NM field */
if (type == 1 && n->parent == NULL) {
/*
* "." for root directory
* we need to write SP and ER entries. The first fits in SUA,
* ER needs a Continuation Area, thus we also need a CE entry
*/
su_size += 7 + 28; /* SP + CE */
/* ER of RRIP */
if (t->rrip_version_1_10) {
*ce = 237;
} else {
*ce = 182;
}
if (t->aaip && !t->aaip_susp_1_10) {
*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;
}
}
/*
* The System Use field inside the directory record must be padded if
* it is an odd number (ECMA-119, 9.1.13)
*/
su_size += (su_size % 2);
return su_size;
}
/**
* Free all info in a struct susp_info.
*/
static
void susp_info_free(struct susp_info* susp)
{
size_t i;
for (i = 0; i < susp->n_susp_fields; ++i) {
free(susp->susp_fields[i]);
}
free(susp->susp_fields);
for (i = 0; i < susp->n_ce_susp_fields; ++i) {
free(susp->ce_susp_fields[i]);
}
free(susp->ce_susp_fields);
}
/**
* Fill a struct susp_info with the RR/SUSP entries needed for a given
* node.
@ -1268,8 +1337,8 @@ int add_aa_string(Ecma119Image *t, Ecma119Node *n, struct susp_info *info,
* @param type
* 0 normal entry, 1 "." entry for that node (it is a dir), 2 ".."
* for that node (i.e., it will refer to the parent)
* @param space
* Available space in the System Use Area for the directory record.
* @param used_up
* Already occupied space in the directory record.
* @param info
* Pointer to the struct susp_info where the entries will be stored.
* If some entries need to go to a Continuation Area, they will be added
@ -1279,7 +1348,7 @@ int add_aa_string(Ecma119Image *t, Ecma119Node *n, struct susp_info *info,
* 1 success, < 0 error
*/
int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
size_t space, struct susp_info *info)
size_t used_up, struct susp_info *info)
{
int ret;
size_t i;
@ -1291,13 +1360,20 @@ 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 */
int ce_is_predicted = 0;
size_t aaip_sua_free= 0, aaip_len= 0;
int space;
if (t == NULL || n == NULL || info == NULL) {
return ISO_NULL_POINTER;
}
if (type < 0 || type > 2 || space < 185) {
/* space min is 255 - 33 - 37 = 185 */
return ISO_WRONG_ARG_VALUE;
/* Directory record length must be even (ECMA-119, 9.1.13). Maximum is 254.
*/
space = 254 - used_up - (used_up % 2);
if (type < 0 || type > 2 || space < ISO_ROCKRIDGE_IN_DIR_REC) {
iso_msg_submit(t->image->id, ISO_ASSERT_FAILURE, 0,
"Unknown node type %d or short RR space %d < %d in directory record",
type, space, ISO_ROCKRIDGE_IN_DIR_REC);
return ISO_ASSERT_FAILURE;
}
if (type == 2 && n->parent != NULL) {
@ -1306,13 +1382,6 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
node = n;
}
/* space min is 255 - 33 - 37 = 185
* At the same time, it is always an odd number, but we need to pad it
* propertly to ensure the length of a directory record is a even number
* (ECMA-119, 9.1.13). Thus, in fact the real space is always space - 1
*/
space--;
/*
* SP must be the first entry for the "." record of the root directory
* (SUSP, 5.3)
@ -1367,6 +1436,12 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
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) {
if (S_ISBLK(n->node->mode) || S_ISCHR(n->node->mode)) {
@ -1384,6 +1459,13 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
}
}
if (info->suf_len + 28 > space) {
iso_msg_submit(t->image->id, ISO_ASSERT_FAILURE, 0,
"Directory Record overflow. name='%s' , suf_len=%d > space=%d - 28\n",
node->iso_name, (int) info->suf_len, space);
return ISO_ASSERT_FAILURE;
}
if (type == 0) {
size_t sua_free; /* free space in the SUA */
int nm_type = 0; /* 0 whole entry in SUA, 1 part in CE */
@ -1402,12 +1484,18 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
/* Try whether NM, SL, AL will fit into SUA */
su_size_pd = info->suf_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 */
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;
ce_is_predicted = 1;
}
if (ret == -2) {
ret = ISO_OUT_OF_MEM;
goto add_susp_cleanup;
}
/* NM entry */
if (5 + namelen <= sua_free) {
@ -1492,8 +1580,8 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
* First, we check how many bytes fit in current
* SL field
*/
int fit = 255 - sl_len - 2;
if (clen - 250 <= fit) {
ssize_t fit = 255 - sl_len - 2;
if ((ssize_t) (clen - 250) <= fit) {
/*
* the component can be divided between this
* and another SL entry
@ -1605,6 +1693,12 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
/*
* ..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),
0, 1);
if (ret < 0) {
@ -1646,9 +1740,36 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
/* "." or ".." entry */
/* write the NM entry */
ret = rrip_add_NM(t, info, NULL, 0, 1 << type, 0);
if (ret < 0) {
goto add_susp_cleanup;
if (t->rrip_version_1_10) {
/* RRIP-1.10:
"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) {
@ -1670,7 +1791,7 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
/* Compute length of AAIP string of root node */
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)
goto add_susp_cleanup;
@ -1756,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)
{
size_t i;
uint8_t padding[BLOCK_SIZE];
uint8_t *padding = NULL;
int ret= ISO_SUCCESS;
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++) {
ret = iso_write(t, info->ce_susp_fields[i],
@ -1787,6 +1909,8 @@ int rrip_write_ce_fields(Ecma119Image *t, struct susp_info *info)
info->ce_susp_fields = NULL;
info->n_ce_susp_fields = 0;
info->ce_len = 0;
ex:;
LIBISO_FREE_MEM(padding);
return ret;
}

View File

@ -81,8 +81,7 @@ int susp_iter_next(SuspIterator *iter, struct susp_sys_user_entry **sue)
* (IEEE 1281, SUSP. section 4)
*/
if (iter->ce_len) {
uint32_t block;
int nblocks;
uint32_t block, nblocks;
/* A CE has found, there is another continuation area */
nblocks = DIV_UP(iter->ce_off + iter->ce_len, BLOCK_SIZE);
@ -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,
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,
unsigned char **aa_string, size_t *aa_size, size_t *aa_len,

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt
* Copyright (c) 2009 - 2011 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -16,6 +16,7 @@
#include "stream.h"
#include "fsource.h"
#include "util.h"
#include "node.h"
#include <stdlib.h>
#include <string.h>
@ -157,8 +158,65 @@ int fsrc_update_size(IsoStream *stream)
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 = {
1, /* update_size is defined for this stream */
4, /* version */
"fsrc",
fsrc_open,
fsrc_close,
@ -167,7 +225,10 @@ IsoStreamIface fsrc_stream_class = {
fsrc_is_repeatable,
fsrc_get_id,
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)
@ -338,7 +399,7 @@ static
int cut_out_read(IsoStream *stream, void *buf, size_t count)
{
struct cut_out_stream *data = stream->data;
count = (size_t)MIN(data->size - data->pos, count);
count = (size_t) MIN((size_t) (data->size - data->pos), count);
if (count == 0) {
return 0;
}
@ -375,11 +436,77 @@ void cut_out_free(IsoStream *stream)
free(data);
}
static
int cut_out_update_size(IsoStream *stream)
{
return ISO_SUCCESS;
}
static
IsoStream* cut_out_get_input_stream(IsoStream *stream, int flag)
{
return NULL;
}
static
int cut_out_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.
*/
static
IsoStreamIface cut_out_stream_class = {
0,
4, /* version */
"cout",
cut_out_open,
cut_out_close,
@ -387,7 +514,12 @@ IsoStreamIface cut_out_stream_class = {
cut_out_read,
cut_out_is_repeatable,
cut_out_get_id,
cut_out_free
cut_out_free,
cut_out_update_size,
cut_out_get_input_stream,
cut_out_cmp_ino,
cut_out_clone_stream
};
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;
}
if (data->offset >= data->size) {
if (data->offset >= (ssize_t) data->size) {
return 0; /* EOF */
}
@ -549,12 +681,78 @@ void mem_free(IsoStream *stream)
{
MemStreamData *data;
data = (MemStreamData*)stream->data;
free(data->buf);
if (data->buf != NULL)
free(data->buf);
free(data);
}
static
int mem_update_size(IsoStream *stream)
{
return ISO_SUCCESS;
}
static
IsoStream* mem_get_input_stream(IsoStream *stream, int flag)
{
return NULL;
}
static
int mem_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 = {
0,
4, /* version */
"mem ",
mem_open,
mem_close,
@ -562,7 +760,12 @@ IsoStreamIface mem_stream_class = {
mem_read,
mem_is_repeatable,
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).
*
* @return
* 1 sucess, < 0 error
* 1 success, < 0 error
*/
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)) {
FSrcStreamData *data = stream->data;
char *path = iso_file_source_get_path(data->src);
strncpy(name, path, PATH_MAX);
if (path == NULL) {
name[0] = 0;
return;
}
strncpy(name, path, PATH_MAX - 1);
name[PATH_MAX - 1] = 0;
free(path);
} else if (!strncmp(type, "boot", 4)) {
strcpy(name, "BOOT CATALOG");
@ -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 res, is_open = 0;
char buffer[2048];
int ret, is_open = 0;
char * buffer = NULL;
void *ctx= NULL;
off_t file_size;
uint32_t b, nblocks;
size_t got_bytes;
IsoStream *input_stream;
LIBISO_ALLOC_MEM(buffer, char, 2048);
if (flag & 1) {
while(1) {
input_stream = iso_stream_get_input_stream(stream, 0);
@ -893,34 +1102,74 @@ int iso_stream_make_md5(IsoStream *stream, char md5[16], int flag)
}
if (! iso_stream_is_repeatable(stream))
return 0;
res = iso_md5_start(&ctx);
if (res < 0)
return res;
res = iso_stream_open(stream);
if (res < 0)
return 0;
{ret = 0; goto ex;}
ret = iso_md5_start(&ctx);
if (ret < 0)
goto ex;
ret = iso_stream_open(stream);
if (ret < 0)
goto ex;
is_open = 1;
file_size = iso_stream_get_size(stream);
nblocks = DIV_UP(file_size, 2048);
for (b = 0; b < nblocks; ++b) {
res = iso_stream_read_buffer(stream, buffer, 2048, &got_bytes);
if (res < 0) {
res = 0;
ret = iso_stream_read_buffer(stream, buffer, 2048, &got_bytes);
if (ret < 0) {
ret = 0;
goto ex;
}
/* Do not use got_bytes to stay closer to IsoFileSrc processing */
if (file_size - b * 2048 > 2048)
res = 2048;
ret = 2048;
else
res = file_size - b * 2048;
iso_md5_compute(ctx, buffer, res);
ret = file_size - b * 2048;
iso_md5_compute(ctx, buffer, ret);
}
res = 1;
ret = 1;
ex:;
if (is_open)
iso_stream_close(stream);
if (ctx != NULL)
iso_md5_end(&ctx, md5);
return res;
LIBISO_FREE_MEM(buffer);
return ret;
}
/* API */
int iso_stream_clone(IsoStream *old_stream, IsoStream **new_stream, int flag)
{
int ret;
if (old_stream->class->version < 4)
return ISO_STREAM_NO_CLONE;
ret = old_stream->class->clone_stream(old_stream, new_stream, 0);
return ret;
}
int iso_stream_clone_filter_common(IsoStream *old_stream,
IsoStream **new_stream,
IsoStream **new_input, int flag)
{
IsoStream *stream, *input_stream;
int ret;
*new_stream = NULL;
*new_input = NULL;
input_stream = iso_stream_get_input_stream(old_stream, 0);
if (input_stream == NULL)
return ISO_STREAM_NO_CLONE;
stream = calloc(1, sizeof(IsoStream));
if (stream == NULL)
return ISO_OUT_OF_MEM;
ret = iso_stream_clone(input_stream, new_input, 0);
if (ret < 0) {
free((char *) stream);
return ret;
}
stream->class = old_stream->class;
stream->refcount = 1;
stream->data = NULL;
*new_stream = stream;
return ISO_SUCCESS;
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt
* Copyright (c) 2009 - 2011 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -15,6 +15,7 @@
*/
#include "fsource.h"
/* IMPORTANT: Any change must be reflected by fsrc_clone_stream */
typedef struct
{
IsoFileSource *src;
@ -28,7 +29,8 @@ typedef struct
/**
* Get an identifier for the file of the source, for debug purposes
* @param name
* Should provide at least PATH_MAX bytes
* Must provide at least PATH_MAX bytes. If no PATH_MAX is defined
* then assume PATH_MAX = Libisofs_default_path_maX from libisofs.h
*/
void iso_stream_get_file_name(IsoStream *stream, char *name);
@ -55,15 +57,6 @@ int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream);
int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
IsoStream **stream);
/**
* Create a stream for reading from a arbitrary memory buffer.
* When the Stream refcount reach 0, the buffer is free(3).
*
* @return
* 1 sucess, < 0 error
*/
int iso_memory_stream_new(unsigned char *buf, size_t size, IsoStream **stream);
/**
* Obtain eventual zisofs ZF field entry parameters from a file source out
* of a loaded ISO image.
@ -103,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);
/**
* 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_*/

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2008 Vreixo Formoso
* 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
@ -46,6 +47,11 @@ int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag);
*/
int iso_write_system_area(Ecma119Image *t, uint8_t *buf);
/**
* Adjust t->tail_blocks to the eventual alignment needs of isohybrid booting.
*/
int iso_align_isohybrid(Ecma119Image *t, int flag);
/**
* Read the necessary ELF information from the first MIPS boot file.
@ -58,4 +64,210 @@ int iso_read_mipsel_elf(Ecma119Image *t, int flag);
*/
int iso_compute_append_partitions(Ecma119Image *t, int flag);
/* The parameter struct for production of a single MBR partition entry.
See also the description of MBR in doc/boot_sectors.txt.
No sorting by start sector and gap filling is done before the System Area
gets written. But the entries may get assigned to a desired slot number
in the table.
Requested entries with block_count == 0 get expanded to the start of
the next requested entry resp. to image end, if no entry follows.
start_block of a follwing entry must be at least a high as the sum of
start_block and block_count of the previous entry.
Empty requested entries will be represented as 16 bytes of 0.
*/
struct iso_mbr_partition_request {
/* Always given in blocks of 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]);
/* Produces a weakly random variation of a hardcoded real random template
*/
void iso_random_8byte(Ecma119Image *t, uint8_t result[8]);
/* 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_ */

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2011 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -31,11 +32,6 @@
#include <fnmatch.h>
#ifndef PATH_MAX
#define PATH_MAX Libisofs_default_path_maX
#endif
/**
* 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;
}
for (i = 0; i < image->nexcludes; ++i) {
for (i = 0; (int) i < image->nexcludes; ++i) {
if (strcmp(image->excludes[i], path) == 0) {
/* exclude found */
free(image->excludes[i]);
--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 = realloc(image->excludes, image->nexcludes *
@ -578,20 +574,19 @@ int iso_tree_add_new_node(IsoImage *image, IsoDir *parent, const char *name,
*node = NULL;
}
fs = image->fs;
result = fs->get_by_path(fs, path, &file);
if (result < 0) {
return result;
}
/* find place where to insert */
result = iso_dir_exists(parent, name, &pos);
if (result) {
/* a node with same name already exists */
iso_file_source_unref(file);
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);
/* 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);
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 */
ret = iso_msg_submit(image->id, ISO_FILE_CANT_ADD, ret,
"Can't open dir %s", path);
free(path);
if (path != NULL) {
ret = iso_msg_submit(image->id, ISO_FILE_CANT_ADD, ret,
"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;
}
@ -790,6 +790,11 @@ int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir)
}
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;
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);
if (ret < 0) {
iso_node_unref(new);
if (ret != ISO_NODE_NAME_NOT_UNIQUE) {
if (ret != (int) ISO_NODE_NAME_NOT_UNIQUE) {
/* error */
goto dir_rec_continue;
} 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)
{
if (node == NULL || node->parent == NULL) {
char *path = NULL, *parent_path = NULL;
if (node == NULL || node->parent == NULL)
return NULL;
}
if ((IsoNode*)node->parent == node) {
return strdup("/");
} else {
char path[PATH_MAX];
char *parent_path = iso_tree_get_node_path((IsoNode*)node->parent);
if (parent_path == NULL) {
return NULL;
}
parent_path = iso_tree_get_node_path((IsoNode*)node->parent);
if (parent_path == NULL)
goto ex;
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 {
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;
}

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* 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
* modify it under the terms of the GNU General Public License version 2
@ -16,6 +16,7 @@
#include "util.h"
#include "libisofs.h"
#include "messages.h"
#include "joliet.h"
#include "../version.h"
#include <stdlib.h>
@ -218,7 +219,7 @@ int strconv(const char *str, const char *icharset, const char *ocharset,
src = (char *)str;
ret = (char *)out;
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
if (n == -1) {
if (n == (size_t) -1) {
/* error */
iso_iconv_close(&conv, 0);
retval = ISO_CHARSET_CONV_ERROR;
@ -268,7 +269,7 @@ int strnconv(const char *str, const char *icharset, const char *ocharset,
src = (char *)str;
ret = (char *)out;
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
if (n == -1) {
if (n == (size_t) -1) {
/* error */
iso_iconv_close(&conv, 0);
retval = ISO_CHARSET_CONV_ERROR;
@ -335,7 +336,7 @@ int str2wchar(const char *icharset, const char *input, wchar_t **output)
src = (char *)input;
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
while (n == -1) {
while (n == (size_t) -1) {
if (errno == E2BIG) {
/* error, should never occur */
@ -381,12 +382,13 @@ conv_error:;
int str2ascii(const char *icharset, const char *input, char **output)
{
int result;
wchar_t *wsrc_;
char *ret;
char *ret_;
wchar_t *wsrc_ = NULL;
char *ret = NULL;
char *ret_ = NULL;
char *src;
struct iso_iconv_handle conv;
int conv_ret;
int direct_conv = 0;
/* That while loop smells like a potential show stopper */
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;
}
/* 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
* is in fact the number of characters in the string and doesn't
* include the last NULL character.
*/
conv_ret = 0;
result = str2wchar(icharset, input, &wsrc_);
if (result < 0) {
goto fallback;
}
src = (char *)wsrc_;
numchars = wcslen(wsrc_);
if (result == (int) ISO_SUCCESS) {
src = (char *)wsrc_;
numchars = wcslen(wsrc_);
inbytes = numchars * sizeof(wchar_t);
loop_limit = inbytes + 3;
inbytes = numchars * sizeof(wchar_t);
loop_limit = inbytes + 3;
ret_ = malloc(numchars + 1);
if (ret_ == NULL) {
return ISO_OUT_OF_MEM;
}
outbytes = numchars;
ret = ret_;
ret_ = malloc(numchars + 1);
if (ret_ == NULL) {
return ISO_OUT_OF_MEM;
}
outbytes = numchars;
ret = ret_;
/* initialize iconv */
conv_ret = iso_iconv_open(&conv, "ASCII", "WCHAR_T", 0);
/* initialize iconv */
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) {
free(wsrc_);
free(ret_);
goto fallback;
conv_ret = iso_iconv_open(&conv, "ASCII", (char *) icharset, 0);
if (conv_ret <= 0)
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);
while (n == -1) {
while (n == (size_t) -1) {
/* The destination buffer is too small. Stops here. */
if (errno == E2BIG)
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
* to be converted. That's probably a multibyte character.
* See above comment. */
src += sizeof(wchar_t);
inbytes -= sizeof(wchar_t);
if (direct_conv) {
src++;
inbytes--;
} else {
src += sizeof(wchar_t);
inbytes -= sizeof(wchar_t);
}
if (!inbytes)
break;
@ -470,8 +498,9 @@ int str2ascii(const char *icharset, const char *input, char **output)
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
}
iso_iconv_close(&conv, 0);
*ret='\0';
free(wsrc_);
*ret = 0;
if (wsrc_ != NULL)
free(wsrc_);
*output = ret_;
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 result;
wchar_t *wsrc_;
wchar_t *wsrc_ = NULL;
char *src;
char *ret;
char *ret_;
char *ret = NULL;
char *ret_ = NULL;
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 */
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
* 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_);
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;
}
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 this did not succeed : Try the untraditional direct conversion.
*/
if (conv_ret <= 0) {
free(wsrc_);
free(ret_);
return ISO_CHARSET_CONV_ERROR;
conv_ret = iso_iconv_open(&conv, "UCS-2BE", (char *) icharset, 0);
if (conv_ret <= 0) {
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);
while (n == -1) {
while (n == (size_t) -1) {
/* The destination buffer is too small. Stops here. */
if (errno == E2BIG)
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
* to be converted. That's probably a multibyte character.
* See above comment. */
src += sizeof(wchar_t);
inbytes -= sizeof(wchar_t);
if (direct_conv) {
src++;
inbytes--;
} else {
src += sizeof(wchar_t);
inbytes -= sizeof(wchar_t);
}
if (!inbytes)
break;
@ -604,7 +660,8 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
/* close the ucs string */
set_ucsbe((uint16_t*) ret, '\0');
free(wsrc_);
if (wsrc_ != NULL)
free(wsrc_);
*output = (uint16_t*)ret_;
return ISO_SUCCESS;
@ -628,36 +685,75 @@ static int valid_j_char(uint16_t 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
char *iso_dirid(const char *src, int size)
char *iso_dirid(const char *src, int size, int relaxed)
{
size_t len, i;
char name[32];
len = strlen(src);
if (len > size) {
if ((int) len > size) {
len = size;
}
for (i = 0; i < len; i++) {
#ifdef Libisofs_old_ecma119_nameS
char c= toupper(src[i]);
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';
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)
{
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
* to calculate lname and lext. */
@ -668,7 +764,8 @@ char *iso_1_fileid(const char *src)
return NULL;
}
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;
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. */
for (i = 0; i < lname && i < 8; i++) {
#ifdef Libisofs_old_ecma119_nameS
char c= toupper(src[i]);
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. */
dest[pos++] = '.';
if (force_dots || lext > 0)
dest[pos++] = '.';
/* Convert up to 3 characters of the extension, if any. */
for (i = 0; i < lext && i < 3; i++) {
#ifdef Libisofs_old_ecma119_nameS
char c= toupper(src[lname + 1 + i]);
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';
@ -760,8 +881,11 @@ char *iso_2_fileid(const char *src)
* @param size
* Max len for the name
* @param relaxed
* 0 only allow d-characters, 1 allow also lowe case chars,
* 2 allow all characters
* bit0+1: 0 only allow d-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)
{
@ -769,11 +893,16 @@ char *iso_r_dirid(const char *src, int size, int relaxed)
char *dest;
len = strlen(src);
if (len > size) {
if ((int) len > size) {
len = size;
}
dest = malloc(len + 1);
if (dest == NULL)
return NULL;
for (i = 0; i < len; i++) {
#ifdef Libisofs_old_ecma119_nameS
char c= src[i];
if (relaxed == 2) {
/* all chars are allowed */
@ -794,6 +923,13 @@ char *iso_r_dirid(const char *src, int size, int relaxed)
dest[i] = '_';
}
}
#else /* Libisofs_old_ecma119_nameS */
dest[i] = map_fileid_char(src[i], relaxed);
#endif /* ! Libisofs_old_ecma119_nameS */
}
dest[len] = '\0';
@ -801,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
* Max len for the name, without taken the "." into account.
* @param relaxed
* 0 only allow d-characters, 1 allow also lowe case chars,
* 2 allow all characters
* bit0+1: 0 only allow d-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
* Whether to ensure that "." is added
*/
@ -835,15 +975,15 @@ char *iso_r_fileid(const char *src, size_t len, int relaxed, int forcedot)
*/
if (dot == NULL || *(dot + 1) == '\0') {
lname = strlen(src);
lnname = (lname > len) ? len : lname;
lnname = (lname > (int) len) ? (int) len : lname;
lext = lnext = 0;
} else {
lext = strlen(dot + 1);
lname = strlen(src) - lext - 1;
lnext = (strlen(src) > len + 1 && lext > 3) ?
(lname < len - 3 ? len - lname : 3)
(lname < (int) len - 3 ? (int) len - lname : 3)
: lext;
lnname = (strlen(src) > len + 1) ? len - lnext : lname;
lnname = (strlen(src) > len + 1) ? (int) len - lnext : lname;
}
if (lnname == 0 && lnext == 0) {
@ -854,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. */
for (i = 0; i < lnname; i++) {
#ifdef Libisofs_old_ecma119_nameS
char c= src[i];
if (relaxed == 2) {
/* all chars are allowed */
@ -874,6 +1017,13 @@ char *iso_r_fileid(const char *src, size_t len, int relaxed, int forcedot)
dest[pos++] = '_';
}
}
#else /* Libisofs_old_ecma119_nameS */
dest[pos++] = map_fileid_char(src[i], relaxed);
#endif /* ! Libisofs_old_ecma119_nameS */
}
if (lnext > 0 || forcedot) {
dest[pos++] = '.';
@ -881,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. */
for (i = lname + 1; i < lname + 1 + lnext; i++) {
#ifdef Libisofs_old_ecma119_nameS
char c= src[i];
if (relaxed == 2) {
/* all chars are allowed */
@ -901,6 +1054,13 @@ char *iso_r_fileid(const char *src, size_t len, int relaxed, int forcedot)
dest[pos++] = '_';
}
}
#else /* Libisofs_old_ecma119_nameS */
dest[pos++] = map_fileid_char(src[i], relaxed);
#endif /* ! Libisofs_old_ecma119_nameS */
}
dest[pos] = '\0';
@ -914,16 +1074,22 @@ ex:;
/*
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 *dot;
size_t lname, lext, lnname, lnext, pos, i;
uint16_t dest[66]; /* 66 = 64 (name + ext) + 1 (.) + 1 (\0) */
uint16_t *dot, *retval = NULL;
size_t lname, lext, lnname, lnext, pos, i, maxchar = 64;
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) {
return NULL;
goto ex;
}
if (flag & 2)
maxchar = 103;
dot = ucsrchr(src, '.');
@ -935,18 +1101,19 @@ uint16_t *iso_j_file_id(const uint16_t *src, int flag)
*/
if (dot == NULL || cmp_ucsbe(dot + 1, '\0') == 0) {
lname = ucslen(src);
lnname = (lname > 64) ? 64 : lname;
lnname = (lname > maxchar) ? maxchar : lname;
lext = lnext = 0;
} else {
lext = ucslen(dot + 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;
lnname = (ucslen(src) > 65) ? 64 - lnext : lname;
lnname = (ucslen(src) > maxchar + 1) ? maxchar - lnext : lname;
}
if (lnname == 0 && lnext == 0) {
return NULL;
goto ex;
}
pos = 0;
@ -981,21 +1148,30 @@ uint16_t *iso_j_file_id(const uint16_t *src, int flag)
is_done:;
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;
uint16_t dest[65]; /* 65 = 64 + 1 (\0) */
size_t len, i, maxchar = 64;
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) {
return NULL;
goto ex;
}
if (flag & 2)
maxchar = 103;
len = ucslen(src);
if (len > 64) {
len = 64;
if (len > maxchar) {
len = maxchar;
}
for (i = 0; i < len; i++) {
uint16_t c = src[i];
@ -1006,7 +1182,10 @@ uint16_t *iso_j_dir_id(const uint16_t *src)
}
}
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)
@ -1036,6 +1215,8 @@ uint16_t *ucsdup(const uint16_t *str)
size_t len = ucslen(str);
ret = malloc(2 * (len + 1));
if (ret == NULL)
return NULL;
if (ret != NULL) {
memcpy(ret, str, 2 * (len + 1));
}
@ -1044,12 +1225,13 @@ uint16_t *ucsdup(const uint16_t *str)
/**
* 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)
{
const char *s = (const char*)s1;
const char *t = (const char*)s2;
const uint8_t *s = (const uint8_t*)s1;
const uint8_t *t = (const uint8_t*)s2;
size_t len1 = ucslen(s1);
size_t len2 = ucslen(s2);
size_t i, len = MIN(len1, len2) * 2;
@ -1173,6 +1355,18 @@ void iso_bb(uint8_t *buf, uint32_t num, int 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)
{
int i;
@ -1294,12 +1488,41 @@ void iso_datetime_17(unsigned char *buf, time_t t, int always_gmt)
}
#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
time_t timegm(struct tm *tm)
time_t env_timegm(struct tm *tm)
{
time_t ret;
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");
setenv("TZ", "", 1);
tzset();
@ -1309,9 +1532,92 @@ time_t timegm(struct tm *tm)
else
unsetenv("TZ");
tzset();
#endif /* ! Libisofs_use_putenV */
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)
{
@ -1323,6 +1629,7 @@ time_t iso_datetime_read_7(const uint8_t *buf)
tm.tm_hour = buf[3];
tm.tm_min = buf[4];
tm.tm_sec = buf[5];
return timegm(&tm) - ((int8_t)buf[6]) * 60 * 15;
}
@ -1409,16 +1716,17 @@ char *iso_util_strcopy(const char *buf, size_t len)
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;
int len;
str = iso_util_strcopy(buf, len);
str = iso_util_strcopy(buf, len_in);
if (str == NULL) {
return NULL;
}
/* remove trailing spaces */
for (len = len-1; len >= 0; --len) {
for (len = len_in - 1; len >= 0; --len) {
if (str[len] != ' ')
break;
str[len] = 0;
@ -1436,12 +1744,12 @@ void strncpy_pad(char *dest, const char *src, size_t max)
if (src != NULL) {
len = MIN(strlen(src), max);
for (i = 0; i < len; ++i)
dest[i] = src[i];
} else {
len = 0;
}
for (i = 0; i < len; ++i)
dest[i] = src[i];
for (i = len; i < max; ++i)
dest[i] = ' ';
}
@ -1460,6 +1768,8 @@ char *ucs2str(const char *buf, size_t len)
/* ensure enought space */
out = calloc(outbytes, 1);
if (out == NULL)
return NULL;
/* convert to local charset */
conv_ret = iso_iconv_open(&conv, iso_get_local_charset(0), "UCS-2BE", 0);
@ -1471,7 +1781,7 @@ char *ucs2str(const char *buf, size_t len)
n = iso_iconv(&conv, &src, &inbytes, &str, &outbytes, 0);
iso_iconv_close(&conv, 0);
if (n == -1) {
if (n == (size_t) -1) {
/* error */
goto ex;
}
@ -1708,12 +2018,12 @@ int iso_util_eval_md5_tag(char *block, int desired, uint32_t lba,
*tag_type = 0;
decode_ret = iso_util_decode_md5_tag(block, tag_type, &pos,
&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;
if (*tag_type > 30)
goto unexpected_type;
if (decode_ret == ISO_MD5_AREA_CORRUPTED) {
if (decode_ret == (int) ISO_MD5_AREA_CORRUPTED) {
ret = decode_ret;
goto ex;
} else if (!((1 << *tag_type) & desired)) {
@ -1721,10 +2031,24 @@ unexpected_type:;
iso_msg_submit(-1, ISO_MD5_TAG_UNEXPECTED, 0, NULL);
ret = 0;
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;
goto ex;
} else if(range_start != ctx_start_lba) {
} else if (range_start != ctx_start_lba) {
ret = ISO_MD5_TAG_MISPLACED;
}
ret = iso_md5_clone(ctx, &cloned_ctx);
@ -1742,4 +2066,29 @@ ex:;
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;
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt
* Copyright (c) 2009 - 2012 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -11,7 +11,14 @@
#ifndef LIBISO_UTIL_H_
#define LIBISO_UTIL_H_
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#endif
#include <time.h>
#ifndef MAX
@ -86,8 +93,11 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output);
*
* @param src
* The identifier, in ASCII encoding.
* @param relaxed
* 0 only allow d-characters, 1 allow also lowe case chars,
* 2 allow all characters
*/
char *iso_1_dirid(const char *src);
char *iso_1_dirid(const char *src, int relaxed);
/**
* Create a level 2 directory identifier.
@ -117,8 +127,13 @@ char *iso_r_dirid(const char *src, int size, int relaxed);
*
* @param src
* The identifier, in ASCII encoding.
* @param relaxed
* 0 only allow d-characters, 1 allow also lowe case chars,
* 2 allow all characters
* @param force_dots
* If 1 then prepend empty extension by SEPARATOR1 = '.'
*/
char *iso_1_fileid(const char *src);
char *iso_1_fileid(const char *src, int relaxed, int force_dots);
/**
* Create a level 2 file identifier.
@ -146,13 +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
* combined name and extension length will not exceed 128 bytes, and the
* name and extension will be separated (.). All characters consist of
* 2 bytes and the resulting string is NULL-terminated by a 2-byte NULL.
* combined name and extension length will normally not exceed 64 characters
* (= 128 bytes). The name and the extension will be separated (.).
* All characters consist of 2 bytes and the resulting string is
* NULL-terminated by a 2-byte NULL.
*
* Note that version number and (;1) is not appended.
* @param flag
* bit0= no_force_dots
* bit1= allow 103 characters rather than 64
* @return
* NULL if the original name and extension both are of length 0.
*/
@ -164,10 +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
* 2 bytes and the resulting string is NULL-terminated by a 2-byte NULL.
*
* @param flag
* bit1= allow 103 characters rather than 64
* @return
* NULL if the original name and extension both are of length 0.
*/
uint16_t *iso_j_dir_id(const uint16_t *src);
uint16_t *iso_j_dir_id(const uint16_t *src, int flag);
/**
* Like strlen, but for Joliet strings.
@ -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_bb(uint8_t *buf, uint32_t num, int bytes);
/* An alternative to iso_lsb() which advances the write pointer
*/
int iso_lsb_to_buf(char **wpt, uint32_t value, int bytes, int flag);
uint32_t iso_read_lsb(const uint8_t *buf, int bytes);
uint32_t iso_read_msb(const uint8_t *buf, int bytes);
@ -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);
/* The iso_node_xinfo_cloner function which gets associated to
* checksum_cx_xinfo_func by iso_init() resp. iso_init_with_flag() via
* iso_node_xinfo_make_clonable()
*/
int checksum_cx_xinfo_cloner(void *old_data, void **new_data, int flag);
/* Function to identify and manage md5 sums of unspecified providence stored
* directly in this xinfo. This is supposed to override any other recorded
* MD5 of the node unless data get copied and checksummed during that copying.
*/
int checksum_md5_xinfo_func(void *data, int flag);
/* The iso_node_xinfo_cloner function which gets associated to
* checksum_md5_xinfo_func by iso_init() resp. iso_init_with_flag() via
* iso_node_xinfo_make_clonable()
*/
int checksum_md5_xinfo_cloner(void *old_data, void **new_data, int flag);
/* The iso_node_xinfo_cloner function which gets associated to
* iso_hfsplus_xinfo_func by iso_init() resp. iso_init_with_flag() via
* iso_node_xinfo_make_clonable()
*/
int iso_hfsplus_xinfo_cloner(void *old_data, void **new_data, int flag);
/* ------------------------------------------------------------------------- */
void *iso_alloc_mem(size_t size, size_t count, int flag);
#define LIBISO_ALLOC_MEM(pt, typ, count) { \
pt= (typ *) iso_alloc_mem(sizeof(typ), (size_t) (count), 0); \
if(pt == NULL) { \
ret= ISO_OUT_OF_MEM; goto ex; \
} }
#define LIBISO_ALLOC_MEM_VOID(pt, typ, count) { \
pt= (typ *) iso_alloc_mem(sizeof(typ), (size_t) (count), 0); \
if(pt == NULL) { \
goto ex; \
} }
#define LIBISO_FREE_MEM(pt) { \
if(pt != NULL) \
free((char *) pt); \
}
/* ------------------------------------------------------------------------- */
/* 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_*/

View File

@ -164,7 +164,7 @@ int iso_rbtree_insert(IsoRBTree *tree, void *data, void **item)
new = data;
added = 1;
} else {
struct iso_rbnode head = { 0 }; /* False tree root */
struct iso_rbnode head = { 0, {NULL, NULL}, 0 }; /* False tree root */
struct iso_rbnode *g, *t; /* Grandparent & parent */
struct iso_rbnode *p, *q; /* Iterator & parent */