Compare commits

...

45 Commits

Author SHA1 Message Date
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
33 changed files with 2317 additions and 260 deletions

View File

@ -1,7 +1,40 @@
bzr branch lp:libisofs/for-libisoburn (to become libisofs-0.6.42.tar.gz)
bzr branch lp:libisofs/for-libisoburn (to become libisofs-1.0.6.tar.gz)
===============================================================================
- no novelties yet
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
===============================================================================
* New API call iso_write_opts_set_disc_label(), new system area type

View File

@ -1,4 +1,4 @@
AC_INIT([libisofs], [0.6.40], [http://libburnia-project.org])
AC_INIT([libisofs], [1.0.4], [http://libburnia-project.org])
AC_PREREQ([2.50])
dnl AC_CONFIG_HEADER([config.h])
@ -38,9 +38,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=0
LIBISOFS_MICRO_VERSION=4
LIBISOFS_VERSION=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION.$LIBISOFS_MICRO_VERSION
AC_SUBST(LIBISOFS_MAJOR_VERSION)
@ -50,10 +50,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
# 2011.03.10 development jump has not yet happened
# SONAME = 48 - 42 = 6 . Library name = libisofs.6.42.0
LT_CURRENT=48
LT_AGE=42
LT_REVISION=0
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
@ -133,15 +133,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 $CFLAGS"
fi
CFLAGS="$CFLAGS -DDEBUG"
CFLAGS="-DDEBUG $CFLAGS"
fi
dnl Verbose debug to make libisofs issue more debug messages

View File

@ -157,8 +157,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 +210,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.

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 |
@ -150,7 +152,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,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,7 +1,7 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2007 Mario Danic
* Copyright (c) 2009 - 2010 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
@ -141,7 +141,7 @@ static int show_chunk_to_jte(Ecma119Image *target, char *buf, int count)
static
int need_version_number(Ecma119Image *t, Ecma119Node *n)
{
if (t->omit_version_numbers & 1) {
if ((t->omit_version_numbers & 1) || t->untranslated_name_len > 0) {
return 0;
}
if (n->type == ECMA119_DIR || n->type == ECMA119_PLACEHOLDER) {
@ -188,9 +188,9 @@ size_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce)
/* size of "." and ".." entries */
len = 34 + 34;
if (t->rockridge) {
len += rrip_calc_len(t, dir, 1, 255 - 34, &ce_len);
len += rrip_calc_len(t, dir, 1, 34, &ce_len);
*ce += ce_len;
len += rrip_calc_len(t, dir, 2, 255 - 34, &ce_len);
len += rrip_calc_len(t, dir, 2, 34, &ce_len);
*ce += ce_len;
}
@ -203,7 +203,7 @@ size_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce)
for (section = 0; section < nsections; ++section) {
size_t dirent_len = calc_dirent_len(t, child);
if (t->rockridge) {
dirent_len += rrip_calc_len(t, child, 0, 255 - dirent_len, &ce_len);
dirent_len += rrip_calc_len(t, child, 0, dirent_len, &ce_len);
*ce += ce_len;
}
remaining = BLOCK_SIZE - (len % BLOCK_SIZE);
@ -329,6 +329,9 @@ int ecma119_writer_compute_data_blocks(IsoImageWriter *writer)
image start and not for the partition */;
}
target->tree_end_block = target->curblock;
return ISO_SUCCESS;
}
@ -380,11 +383,14 @@ void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id,
multi_extend = (node->info.file->nsections - 1 == extent) ? 0 : 1;
} else {
/*
* for nodes other than files and dirs, we set both
* len and block to 0
* for nodes other than files and dirs, we set len to 0, and
* the content block address to a dummy value.
*/
len = 0;
block = 0;
if (! t->old_empty)
block = t->empty_file_block;
else
block = 0;
}
/*
@ -594,7 +600,7 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *parent)
/* write the "." and ".." entries first */
if (t->rockridge) {
ret = rrip_get_susp_fields(t, dir, 1, 255 - 32, &info);
ret = rrip_get_susp_fields(t, dir, 1, 34, &info);
if (ret < 0) {
return ret;
}
@ -604,7 +610,7 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *parent)
buf += len;
if (t->rockridge) {
ret = rrip_get_susp_fields(t, dir, 2, 255 - 32, &info);
ret = rrip_get_susp_fields(t, dir, 2, 34, &info);
if (ret < 0) {
return ret;
}
@ -630,7 +636,7 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *parent)
/* get the SUSP fields if rockridge is enabled */
if (t->rockridge) {
ret = rrip_get_susp_fields(t, child, 0, 255 - len, &info);
ret = rrip_get_susp_fields(t, child, 0, len, &info);
if (ret < 0) {
return ret;
}
@ -871,6 +877,7 @@ int ecma119_writer_write_data(IsoImageWriter *writer)
{
int ret;
Ecma119Image *t;
uint32_t curblock;
if (writer == NULL) {
return ISO_ASSERT_FAILURE;
@ -888,6 +895,20 @@ int ecma119_writer_write_data(IsoImageWriter *writer)
if (ret < 0)
return ret;
}
curblock = (t->bytes_written / 2048) + t->ms_block;
if (curblock != t->tree_end_block) {
char msg[100];
sprintf(msg,
"Calculated and written ECMA-119 tree end differ: %lu <> %lu",
(unsigned long) t->tree_end_block,
(unsigned long) curblock);
iso_msgs_submit(0, msg, 0, "WARNING", 0);
t->tree_end_block = 1;/* Mark for harsher reaction at end of writing */
}
return ISO_SUCCESS;
}
@ -1087,7 +1108,36 @@ int zero_writer_free_data(IsoImageWriter *writer)
}
static
int zero_writer_create(Ecma119Image *target, uint32_t num_blocks)
int tail_writer_compute_data_blocks(IsoImageWriter *writer)
{
int ret;
Ecma119Image *target;
struct iso_zero_writer_data_struct *data;
char msg[160];
target = writer->target;
ret = iso_align_isohybrid(target, 0);
if (ret < 0)
return ret;
data = (struct iso_zero_writer_data_struct *) writer->data;
if (data->num_blocks != target->tail_blocks) {
sprintf(msg, "Aligned image size to cylinder size by %d blocks",
target->tail_blocks - data->num_blocks);
iso_msgs_submit(0, msg, 0, "NOTE", 0);
data->num_blocks = target->tail_blocks;
}
if (target->tail_blocks <= 0)
return ISO_SUCCESS;
ret = zero_writer_compute_data_blocks(writer);
return ret;
}
/*
@param flag bit0= use tail_writer_compute_data_blocks rather than
zero_writer_compute_data_blocks
*/
static
int zero_writer_create(Ecma119Image *target, uint32_t num_blocks, int flag)
{
IsoImageWriter *writer;
struct iso_zero_writer_data_struct *data;
@ -1103,7 +1153,11 @@ int zero_writer_create(Ecma119Image *target, uint32_t num_blocks)
}
data->num_blocks = num_blocks;
writer->compute_data_blocks = zero_writer_compute_data_blocks;
if (flag & 1) {
writer->compute_data_blocks = tail_writer_compute_data_blocks;
} else {
writer->compute_data_blocks = zero_writer_compute_data_blocks;
}
writer->write_vol_desc = zero_writer_write_vol_desc;
writer->write_data = zero_writer_write_data;
writer->free_data = zero_writer_free_data;
@ -1135,6 +1189,8 @@ int write_vol_desc_terminator(Ecma119Image *target)
uint8_t buf[BLOCK_SIZE];
struct ecma119_vol_desc_terminator *vol;
memset(buf, 0, BLOCK_SIZE);
vol = (struct ecma119_vol_desc_terminator *) buf;
vol->vol_desc_type[0] = 255;
@ -1209,7 +1265,7 @@ int write_head_part2(Ecma119Image *target, int *write_count, int flag)
return ISO_SUCCESS;
/* Write multi-session padding up to target->partition_offset + 16 */
memset(buf, 0, 2048);
memset(buf, 0, BLOCK_SIZE);
for(; *write_count < target->partition_offset + 16; (*write_count)++) {
res = iso_write(target, buf, BLOCK_SIZE);
if (res < 0)
@ -1400,6 +1456,12 @@ void *write_function(void *arg)
Eventually free target */
ecma119_image_free(target);
if (target->tree_end_block == 1) {
iso_msgs_submit(0,
"Image is most likely damaged. Calculated/written block address mismatch.",
0, "FATAL", 0);
}
#ifdef Libisofs_with_pthread_exiT
pthread_exit(NULL);
#else
@ -1575,6 +1637,9 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
target->hardlinks = opts->hardlinks;
target->aaip = opts->aaip;
target->always_gmt = opts->always_gmt;
target->old_empty = opts->old_empty;
target->untranslated_name_len = opts->untranslated_name_len;
target->allow_dir_id_ext = opts->allow_dir_id_ext;
target->omit_version_numbers = opts->omit_version_numbers
| opts->max_37_char_filenames;
target->allow_deep_paths = opts->allow_deep_paths;
@ -1634,7 +1699,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
system_area = src->system_area_data;
system_area_options = src->system_area_options;
} else {
system_area_options = opts->system_area_options & 0xfc;
system_area_options = opts->system_area_options & 0xfffffffc;
}
sa_type = (system_area_options >> 2) & 0x3f;
if (sa_type != 0 && sa_type != 3)
@ -1663,9 +1728,9 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
target->partition_secs_per_head = opts->partition_secs_per_head;
target->partition_heads_per_cyl = opts->partition_heads_per_cyl;
if (target->partition_secs_per_head == 0)
target->partition_secs_per_head = 63;
target->partition_secs_per_head = 32;
if (target->partition_heads_per_cyl == 0)
target->partition_heads_per_cyl = 255;
target->partition_heads_per_cyl = 64;
target->eff_partition_offset = 0;
target->partition_root = NULL;
target->partition_l_table_pos = 0;
@ -1731,6 +1796,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
target->mipsel_p_filesz = 0;
target->empty_file_block = 0;
target->tree_end_block = 0;
target->wthread_is_running = 0;
@ -1777,8 +1843,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
if (target->iso1999) {
nwriters++;
}
if (target->tail_blocks > 0)
nwriters++;
nwriters++; /* Tail padding writer */
if ((target->md5_file_checksums & 1) || target->md5_session_checksum) {
nwriters++;
image_checksums_mad = 1; /* from here on the loaded checksums are
@ -1860,11 +1925,9 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
/* IMPORTANT: This must be the last writer before the checksum writer */
if (target->tail_blocks > 0) {
ret = zero_writer_create(target, target->tail_blocks);
if (ret < 0)
goto target_cleanup;
}
ret = zero_writer_create(target, target->tail_blocks, 1);
if (ret < 0)
goto target_cleanup;
if ((target->md5_file_checksums & 1) || target->md5_session_checksum) {
ret = checksum_writer_create(target);
@ -1918,8 +1981,15 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
if (i == el_torito_writer_index)
continue;
/* Exposing address of data start to IsoWriteOpts */
/* Exposing address of data start to IsoWriteOpts and memorizing
this address for all files which have no block address:
symbolic links, device files, empty data files.
filesrc_writer_compute_data_blocks() and filesrc_writer_write_data()
will account resp. write this single block.
*/
if (i == file_src_writer_index) {
if (! target->old_empty)
target->empty_file_block = target->curblock;
opts->data_start_lba = target->curblock;
}
@ -2266,6 +2336,8 @@ int iso_write(Ecma119Image *target, void *buf, size_t count)
/* reader cancelled */
return ISO_CANCELED;
}
if (ret < 0)
return ret;
if (target->checksum_ctx != NULL) {
/* Add to image checksum */
target->checksum_counter += count;
@ -2277,7 +2349,7 @@ int iso_write(Ecma119Image *target, void *buf, size_t count)
return ret;
/* total size is 0 when writing the overwrite buffer */
if (ret > 0 && (target->total_size != (off_t) 0)){
if (target->total_size != (off_t) 0){
unsigned int kbw, kbt;
int percent;
@ -2294,7 +2366,7 @@ int iso_write(Ecma119Image *target, void *buf, size_t count)
}
}
return ret;
return ISO_SUCCESS;
}
int iso_write_opts_new(IsoWriteOpts **opts, int profile)
@ -2363,6 +2435,9 @@ int iso_write_opts_new(IsoWriteOpts **opts, int profile)
wopts->appended_partitions[i] = NULL;
wopts->ascii_disc_label[0] = 0;
wopts->will_cancel = 0;
wopts->allow_dir_id_ext = 0;
wopts->old_empty = 0;
wopts->untranslated_name_len = 0;
*opts = wopts;
return ISO_SUCCESS;
@ -2451,6 +2526,40 @@ int iso_write_opts_set_aaip(IsoWriteOpts *opts, int enable)
return ISO_SUCCESS;
}
int iso_write_opts_set_old_empty(IsoWriteOpts *opts, int enable)
{
if (opts == NULL) {
return ISO_NULL_POINTER;
}
opts->old_empty = enable ? 1 : 0;
return ISO_SUCCESS;
}
int iso_write_opts_set_untranslated_name_len(IsoWriteOpts *opts, int len)
{
if (opts == NULL) {
return ISO_NULL_POINTER;
}
if (len == -1)
opts->untranslated_name_len = ISO_UNTRANSLATED_NAMES_MAX;
else if(len == 0)
opts->untranslated_name_len = 0;
else if(len > ISO_UNTRANSLATED_NAMES_MAX || len < 0)
return ISO_WRONG_ARG_VALUE;
else
opts->untranslated_name_len = len;
return opts->untranslated_name_len;
}
int iso_write_opts_set_allow_dir_id_ext(IsoWriteOpts *opts, int allow)
{
if (opts == NULL) {
return ISO_NULL_POINTER;
}
opts->allow_dir_id_ext = allow ? 1 : 0;
return ISO_SUCCESS;
}
int iso_write_opts_set_omit_version_numbers(IsoWriteOpts *opts, int omit)
{
if (opts == NULL) {
@ -2801,7 +2910,7 @@ int iso_write_opts_set_system_area(IsoWriteOpts *opts, char data[32768],
memcpy(opts->system_area_data, data, 32768);
}
if (!(flag & 4))
opts->system_area_options = options & 0xff;
opts->system_area_options = options & 0x3ff;
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,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,17 @@
#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
/**
* Holds the options for the image generation.
*/
@ -76,6 +94,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.
@ -218,6 +244,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
@ -399,6 +445,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;
@ -443,6 +490,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
*/
@ -475,6 +525,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
@ -519,19 +575,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;

View File

@ -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, max_len;
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,8 +59,18 @@ 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 (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) {
if (relaxed) {
@ -60,32 +80,40 @@ int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name)
}
} 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) {
if (relaxed) {
isoname = iso_r_fileid(ascii_name, 11, relaxed,
(img->no_force_dots & 1) ? 0 : 1);
if (relaxed || !force_dots) {
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);
}
} 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;
@ -416,8 +444,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 +563,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 +591,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,10 +635,10 @@ 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;
}
@ -716,7 +755,9 @@ int mangle_tree(Ecma119Image *img, 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 */
@ -1033,11 +1074,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);

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"

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* 2010 Thomas Schmitt
* 2010 - 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
@ -232,6 +232,12 @@ int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
t = writer->target;
/* 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->curblock++;
/* on appendable images, ms files shouldn't be included */
if (t->appendable) {
inc_item = is_ms_file;
@ -347,11 +353,22 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
return ISO_ASSERT_FAILURE;
}
memset(buffer, 0, 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) {
was_error = 0;

View File

@ -13,7 +13,13 @@
#include "stream.h"
#include "ecma119.h"
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#endif
struct Iso_File_Src
{

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;
@ -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
{
@ -779,13 +783,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 +850,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 +867,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

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 - 2010 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
@ -72,7 +72,7 @@ struct iso_read_opts
unsigned int nojoliet : 1; /*< Do not read Joliet extensions */
unsigned int noiso1999 : 1; /*< Do not read ISO 9660:1999 enhanced tree */
unsigned int noaaip : 1; /* Do not read AAIP extension for xattr and ACL */
unsigned int nomd5 : 1; /* Do not read MD5 array */
unsigned int nomd5 : 2; /* Do not read MD5 array */
/**
* Hand out new inode numbers and overwrite eventually read PX inode
@ -267,7 +267,7 @@ typedef struct
int aaip_load;
/** Whether the MD5 array shall be read if available.
* 1 = yes , 0 = no
* 2 = yes, but do not check tags , 1 = yes , 0 = no
*/
int md5_load;
@ -317,6 +317,7 @@ typedef struct
typedef struct image_fs_data ImageFileSourceData;
/* IMPORTANT: Any change must be reflected by ifs_clone_src */
struct image_fs_data
{
IsoImageFilesystem *fs; /**< reference to the image it belongs to */
@ -1043,10 +1044,87 @@ int ifs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag)
return 1;
}
static
int ifs_clone_src(IsoFileSource *old_source,
IsoFileSource **new_source, int flag)
{
IsoFileSource *src = NULL;
ImageFileSourceData *old_data, *new_data = NULL;
char *new_name = NULL;
struct iso_file_section *new_sections = NULL;
void *new_aa_string = NULL;
int i, ret;
if (flag)
return ISO_STREAM_NO_CLONE; /* unknown option required */
old_data = (ImageFileSourceData *) 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(ImageFileSourceData));
if (new_data == NULL)
goto no_mem;
if (old_data->nsections > 0) {
new_sections = calloc(old_data->nsections,
sizeof(struct iso_file_section));
if (new_sections == NULL)
goto no_mem;
}
ret = aaip_xinfo_cloner(old_data->aa_string, &new_aa_string, 0);
if (ret < 0)
goto no_mem;
new_data->fs = old_data->fs;
new_data->parent = old_data->parent;
memcpy(&(new_data->info), &(old_data->info), sizeof(struct stat));
new_data->name = new_name;
new_data->sections = new_sections;
new_data->nsections = old_data->nsections;
for (i = 0; i < new_data->nsections; i++)
memcpy(new_data->sections + i, old_data->sections + i,
sizeof(struct iso_file_section));
new_data->opened = old_data->opened;
#ifdef Libisofs_with_zliB
new_data->header_size_div4 = old_data->header_size_div4;
new_data->block_size_log2 = old_data->block_size_log2;
new_data->uncompressed_size = old_data->uncompressed_size;
#endif
new_data->data.content = NULL;
new_data->aa_string = (unsigned char *) new_aa_string;
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(new_data->fs);
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);
if (new_sections != NULL)
free((char *) new_sections);
if (new_aa_string != NULL)
aaip_xinfo_func(new_aa_string, 1);
return ISO_OUT_OF_MEM;
}
IsoFileSourceIface ifs_class = {
1, /* version */
2, /* version */
ifs_get_path,
ifs_get_name,
ifs_lstat,
@ -1060,7 +1138,8 @@ IsoFileSourceIface ifs_class = {
ifs_get_filesystem,
ifs_free,
ifs_lseek,
ifs_get_aa_string
ifs_get_aa_string,
ifs_clone_src
};
@ -2339,6 +2418,10 @@ int iso_src_check_sb_tree(IsoDataSource *src, uint32_t start_lba, int flag)
ret = iso_util_eval_md5_tag(block, desired, start_lba + i,
ctx, start_lba, &tag_type, &next_tag, 0);
iso_md5_compute(ctx, block, 2048);
if (ret == ISO_MD5_TAG_COPIED) { /* growing without emulated TOC */
ret = 2;
goto ex;
}
if (ret == ISO_MD5_AREA_CORRUPTED || ret == ISO_MD5_TAG_MISMATCH)
ret = ISO_SB_TREE_CORRUPTED;
if (ret < 0)
@ -2425,7 +2508,12 @@ int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts,
data->dir_mode = opts->dir_mode & ~S_IFMT;
data->msgid = msgid;
data->aaip_load = !opts->noaaip;
data->md5_load = !opts->nomd5;
if (opts->nomd5 == 0)
data->md5_load = 1;
else if (opts->nomd5 == 2)
data->md5_load = 2;
else
data->md5_load = 0;
data->aaip_version = -1;
data->make_new_ino = opts->make_new_ino;
data->num_bootimgs = 0;
@ -2453,7 +2541,7 @@ int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts,
ifs->free = ifs_fs_free;
/* read Volume Descriptors and ensure it is a valid image */
if (data->md5_load) {
if (data->md5_load == 1) {
/* From opts->block on : check for superblock and tree tags */;
ret = iso_src_check_sb_tree(src, opts->block, 0);
if (ret < 0) {
@ -3155,6 +3243,8 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
size_t size;
void *ctx = NULL;
char md5[16];
struct el_torito_boot_catalog *catalog = NULL;
ElToritoBootImage *boot_image = NULL;
if (image == NULL || src == NULL || opts == NULL) {
return ISO_NULL_POINTER;
@ -3242,8 +3332,6 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
/* if old image has el-torito, add a new catalog */
if (data->eltorito) {
struct el_torito_boot_catalog *catalog;
ElToritoBootImage *boot_image= NULL;
catalog = calloc(1, sizeof(struct el_torito_boot_catalog));
if (catalog == NULL) {
@ -3269,11 +3357,13 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
memcpy(boot_image->selection_crit, data->selection_crits, 20);
catalog->bootimages[catalog->num_bootimages] = boot_image;
boot_image = NULL;
catalog->num_bootimages++;
}
for ( ; idx < Libisofs_max_boot_imageS; idx++)
catalog->bootimages[idx] = NULL;
image->bootcat = catalog;
catalog = NULL; /* So it does not get freed */
}
/* recursively add image */
@ -3452,6 +3542,10 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
image->fs = fsback;
image->builder = blback;
if (catalog != NULL)
el_torito_boot_catalog_free(catalog);
if (boot_image != NULL)
free((char *) boot_image);
iso_file_source_unref(newroot);
fs->close(fs);
iso_filesystem_unref(fs);
@ -3603,7 +3697,7 @@ int iso_read_opts_set_no_md5(IsoReadOpts *opts, int no_md5)
if (opts == NULL) {
return ISO_NULL_POINTER;
}
opts->nomd5 = no_md5 ? 1 : 0;
opts->nomd5 = no_md5 == 2 ? 2 : no_md5 == 1 ? 1 : 0;
return ISO_SUCCESS;
}

View File

@ -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) */
@ -534,10 +534,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 +597,8 @@ IsoFileSourceIface lfs_class = {
lfs_get_filesystem,
lfs_free,
lfs_lseek,
lfs_get_aa_string
lfs_get_aa_string,
lfs_clone_src
};

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_*/

View File

@ -1,6 +1,10 @@
#ifndef LIBISO_LIBISOFS_H_
#define LIBISO_LIBISOFS_H_
/*
* Copyright (c) 2007-2008 Vreixo Formoso, Mario Danic
* Copyright (c) 2009-2010 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
@ -24,11 +28,28 @@
*
*/
#ifndef LIBISO_LIBISOFS_H_
#define LIBISO_LIBISOFS_H_
/*
* Normally this API is operated via public functions and opaque object
* handles. But it also exposes several C structures which may be used to
* provide custom functionality for the objects of the API. The same
* structures are used for internal objects of libisofs, too.
* You are not supposed to manipulate the entrails of such objects if they
* are not your own custom extensions.
*
* See for an example IsoStream = struct iso_stream below.
*/
#include <sys/stat.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#endif
#include <stdlib.h>
struct burn_source;
@ -494,6 +515,8 @@ struct IsoFileSource_Iface
* @since 0.6.2
* Version 1 additionally provides function *(get_aa_string)().
* @since 0.6.14
* Version 2 additionally provides function *(clone_src)().
* @since 1.0.2
*/
int version;
@ -728,6 +751,24 @@ struct IsoFileSource_Iface
int (*get_aa_string)(IsoFileSource *src,
unsigned char **aa_string, int flag);
/**
* Produce a copy of a source. It must be possible to operate both source
* objects concurrently.
*
* @param old_src
* The existing source object to be copied
* @param new_stream
* Will return a pointer to the copy
* @param flag
* Bitfield for control purposes. Submit 0 for now.
* The function shall return ISO_STREAM_NO_CLONE on unknown flag bits.
*
* @since 1.0.2
* Present if .version is 2 or higher.
*/
int (*clone_src)(IsoFileSource *old_src, IsoFileSource **new_src,
int flag);
/*
* TODO #00004 Add a get_mime_type() function.
* This can be useful for GUI apps, to choose the icon of the file
@ -752,6 +793,31 @@ struct iso_file_source
#endif /* ! Libisofs_h_as_cpluspluS */
#endif /* ! __cplusplus */
/* A class of IsoStream is implemented by a class description
* IsoStreamIface = struct IsoStream_Iface
* and a structure of data storage for each instance of IsoStream.
* This structure shall be known to the functions of the IsoStreamIface.
* To create a custom IsoStream class:
* - Define the structure of the custom instance data.
* - Implement the methods which are described by the definition of
* struct IsoStream_Iface (see below),
* - Create a static instance of IsoStreamIface which lists the methods as
* C function pointers. (Example in libisofs/stream.c : fsrc_stream_class)
* To create an instance of that class:
* - Allocate sizeof(IsoStream) bytes of memory and initialize it as
* struct iso_stream :
* - Point to the custom IsoStreamIface by member .class .
* - Set member .refcount to 1.
* - Let member .data point to the custom instance data.
*
* Regrettably the choice of the structure member name "class" makes it
* impossible to implement this generic interface in C++ language directly.
* If C++ is absolutely necessary then you will have to make own copies
* of the public API structures. Use other names but take care to maintain
* the same memory layout.
*/
/**
* Representation of file contents. It is an stream of bytes, functionally
* like a pipe.
@ -787,6 +853,7 @@ extern ino_t serial_id;
*
* @since 0.6.4
*/
struct IsoStream_Iface
{
/*
@ -799,6 +866,8 @@ struct IsoStream_Iface
* get_input_stream() added. A filter stream must have version 2.
* Version 3 (since 0.6.20)
* compare() added. A filter stream should have version 3.
* Version 4 (since 1.0.2)
* clone_stream() added.
*/
int version;
@ -841,7 +910,7 @@ struct IsoStream_Iface
off_t (*get_size)(IsoStream *stream);
/**
* Attempts to read up to count bytes from the given stream into
* Attempt to read up to count bytes from the given stream into
* the buffer starting at buf. The implementation has to make sure that
* either the full desired count of bytes is delivered or that the
* next call to this function will return EOF or error.
@ -857,12 +926,9 @@ struct IsoStream_Iface
int (*read)(IsoStream *stream, void *buf, size_t count);
/**
* Whether this IsoStream can be read several times, with the same results.
* For example, a regular file is repeatable, you can read it as many
* times as you want. However, a pipe isn't.
*
* This function doesn't take into account if the file has been modified
* between the two reads.
* Tell whether this IsoStream can be read several times, with the same
* results. For example, a regular file is repeatable, you can read it
* as many times as you want. However, a pipe is not.
*
* @return
* 1 if stream is repeatable, 0 if not,
@ -883,13 +949,13 @@ struct IsoStream_Iface
void (*free)(IsoStream *stream);
/**
* Updates the size of the IsoStream with the current size of the
* underlying source. After calling this, get_size() will return
* the new size. This should never be called after
* iso_image_create_burn_source() was called and the image was not
* completely written. To update the size of all files before written the
* image, you may want to call iso_image_update_sizes() just before
* iso_image_create_burn_source().
* Update the size of the IsoStream with the current size of the underlying
* source, if the source is prone to size changes. After calling this,
* get_size() shall eventually return the new size.
* This will never be called after iso_image_create_burn_source() was
* called and before the image was completely written.
* (The API call to update the size of all files in the image is
* iso_image_update_sizes()).
*
* @return
* 1 if ok, < 0 on error (has to be a valid libisofs error code)
@ -900,15 +966,15 @@ struct IsoStream_Iface
int (*update_size)(IsoStream *stream);
/**
* Obtains the eventual input stream of a filter stream.
* Retrieve the eventual input stream of a filter stream.
*
* @param stream
* The eventual filter stream to be inquired.
* @param flag
* Bitfield for control purposes. Submit 0 for now.
* Bitfield for control purposes. 0 means normal behavior.
* @return
* The input stream, if one exists. Elsewise NULL.
* No extra reference to the stream is taken by this call.
* No extra reference to the stream shall be taken by this call.
*
* @since 0.6.18
* Present if .version is 2 or higher.
@ -920,33 +986,32 @@ struct IsoStream_Iface
* produce the same output. If in any doubt, then this comparison should
* indicate no match. A match might allow hardlinking of IsoFile objects.
*
* This function has to establish an equivalence and order relation:
* If this function cannot accept one of the given stream types, then
* the decision must be delegated to
* iso_stream_cmp_ino(s1, s2, 1);
* This is also appropriate if one has reason to implement stream.cmp_ino()
* without having an own special comparison algorithm.
*
* With filter streams the decision whether the underlying chains of
* streams match should be delegated to
* iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0),
* iso_stream_get_input_stream(s2, 0), 0);
*
* The stream.cmp_ino() function has to establish an equivalence and order
* relation:
* cmp_ino(A,A) == 0
* cmp_ino(A,B) == -cmp_ino(B,A)
* if cmp_ino(A,B) == 0 && cmp_ino(B,C) == 0 then cmp_ino(A,C) == 0
* if cmp_ino(A,B) < 0 && cmp_ino(B,C) < 0 then cmp_ino(A,C) < 0
*
* A big hazard to the last constraint are tests which do not apply to some
* types of streams. In this case for any A that is applicable and any B
* that is not applicable, cmp_ino(A,B) must have the same non-zero
* result. I.e. a pair of applicable and non-applicable streams must
* return that non-zero result before the test for a pair of applicable
* streams would happen.
* types of streams.Thus it is mandatory to let iso_stream_cmp_ino(s1,s2,1)
* decide in this case.
*
* A function s1.(*cmp_ino)() must only accept stream s2 if function
* s2.(*cmp_ino)() would accept s1. Best is to accept only the own stream
* type or to have the same function for a family of similar stream types.
*
* If the function cannot accept one of the given stream types, then
* the decision must be delegated to
* iso_stream_cmp_ino(s1, s2, 1);
* This is also appropriate if one has reason to implement stream.cmp_ino()
* without special comparison algorithm.
* With filter streams the decision whether the underlying chains of
* streams match should be delegated to
* iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0),
* iso_stream_get_input_stream(s2, 0), 0);
*
* @param s1
* The first stream to compare. Expect foreign stream types.
* @param s2
@ -959,6 +1024,26 @@ struct IsoStream_Iface
*/
int (*cmp_ino)(IsoStream *s1, IsoStream *s2);
/**
* Produce a copy of a stream. It must be possible to operate both stream
* objects concurrently.
*
* @param old_stream
* The existing stream object to be copied
* @param new_stream
* Will return a pointer to the copy
* @param flag
* Bitfield for control purposes. 0 means normal behavior.
* The function shall return ISO_STREAM_NO_CLONE on unknown flag bits.
* @return
* 1 in case of success, or an error code < 0
*
* @since 1.0.2
* Present if .version is 4 or higher.
*/
int (*clone_stream)(IsoStream *old_stream, IsoStream **new_stream,
int flag);
};
#ifndef __cplusplus
@ -1120,9 +1205,9 @@ int iso_lib_is_compatible(int major, int minor, int micro);
*
* @since 0.6.2
*/
#define iso_lib_header_version_major 0
#define iso_lib_header_version_minor 6
#define iso_lib_header_version_micro 40
#define iso_lib_header_version_major 1
#define iso_lib_header_version_minor 0
#define iso_lib_header_version_micro 4
/**
* Usage discussion:
@ -1344,6 +1429,70 @@ int iso_write_opts_set_hardlinks(IsoWriteOpts *opts, int enable);
*/
int iso_write_opts_set_aaip(IsoWriteOpts *opts, int enable);
/**
* Use this only if you need to reproduce a suboptimal behavior of older
* versions of libisofs. They used address 0 for links and device files,
* and the address of the Volume Descriptor Set Terminator for empty data
* files.
* New versions let symbolic links, device files, and empty data files point
* to a dedicated block of zero-bytes after the end of the directory trees.
* (Single-pass reader libarchive needs to see all directory info before
* processing any data files.)
*
* @param opts
* The option set to be manipulated.
* @param enable
* 1 = use the suboptimal block addresses in the range of 0 to 115.
* 0 = use the address of a block after the directory tree. (Default)
*
* @since 1.0.2
*/
int iso_write_opts_set_old_empty(IsoWriteOpts *opts, int enable);
/**
* Caution: This option breaks any assumptions about names that
* are supported by ECMA-119 specifications.
* Try to 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_full_ascii. Further it
* prevents the conversion from local character set to ASCII.
* The maximum name length is given by this call. If a filename exceeds
* this length or cannot be recorded untranslated for other reasons, then
* image production is aborted with ISO_NAME_NEEDS_TRANSL.
* Currently the length limit is 96 characters, because an ECMA-119 directory
* record may at most have 254 bytes and up to 158 other bytes must fit into
* the record. Probably 96 more bytes can be made free for the name in future.
* @param opts
* The option set to be manipulated.
* @param len
* 0 = disable this feature and perform name translation according to
* other settings.
* >0 = Omit any translation. Eventually abort image production
* if a name is longer than the given value.
* -1 = Like >0. Allow maximum possible length (currently 96)
* @return >=0 success, <0 failure
* In case of >=0 the return value tells the effectively set len.
* E.g. 96 after using len == -1.
* @since 1.0.0
*/
int iso_write_opts_set_untranslated_name_len(IsoWriteOpts *opts, int len);
/**
* Convert directory names for ECMA-119 similar to other file names, but do
* not force a dot or add a version number.
* This violates ECMA-119 by allowing one "." and especially ISO level 1
* by allowing DOS style 8.3 names rather than only 8 characters.
* (mkisofs and its clones seem to do this violation.)
* @param opts
* The option set to be manipulated.
* @param allow
* 1= allow dots , 0= disallow dots and convert them
* @return
* 1 success, < 0 error
* @since 1.0.0
*/
int iso_write_opts_set_allow_dir_id_ext(IsoWriteOpts *opts, int allow);
/**
* Omit the version number (";1") at the end of the ISO-9660 identifiers.
* This breaks ECMA-119 specification, but version numbers are usually not
@ -1810,7 +1959,13 @@ int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size);
* iso_write_opts_set_partition_img() for partition numbers 2
* to 8.
* This will overwrite the first 512 bytes of the submitted
* data.
* bit8-9= Only with System area type 0 = MBR
* @since 1.0.4
* 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
* @param flag
* bit0 = invalidate any attached system area data. Same as data == NULL
* (This re-activates eventually loaded image System Area data.
@ -2182,8 +2337,10 @@ int iso_read_opts_set_no_aaip(IsoReadOpts *opts, int noaaip);
* @param opts
* The option set to be manipulated
* @param no_md5
* 0 = Read MD5 array if available, refuse on non-matching MD5 tags
* 1 = Do not read MD5 checksum array
* 0 = Read Md% array if available
* 2 = Read MD5 array, but do not check MD5 tags
* @since 1.0.4
* All other values are reserved.
*
* @since 0.6.22
@ -2971,6 +3128,8 @@ int el_torito_seems_boot_info_table(ElToritoBootImage *bootimg, int flag);
* Specifies options for ISOLINUX or GRUB boot images. This should only be used
* if the type of boot image is known.
*
* @param bootimg
* The image to set options on
* @param options
* bitmask style flag. The following values are defined:
*
@ -2998,8 +3157,6 @@ int el_torito_seems_boot_info_table(ElToritoBootImage *bootimg, int flag);
* For that you need isolinux.bin from SYSLINUX 3.72 or later.
* IMPORTANT: The application has to take care that the image
* on media gets padded up to the next full MB.
* @param bootimg
* The image to set options on
* @param flag
* Reserved for future usage, set to 0.
* @return
@ -3132,9 +3289,9 @@ void iso_node_unref(IsoNode *node);
enum IsoNodeType iso_node_get_type(IsoNode *node);
/**
* Function to handle particular extended information. The function
* pointer acts as an identifier for the type of the information. Structs
* with same information type must use the same function.
* Class of functions to handle particular extended information. A function
* instance acts as an identifier for the type of the information. Structs
* with same information type must use a pointer to the same function.
*
* @param data
* Attached data
@ -3189,6 +3346,20 @@ int iso_node_add_xinfo(IsoNode *node, iso_node_xinfo_func proc, void *data);
*/
int iso_node_remove_xinfo(IsoNode *node, iso_node_xinfo_func proc);
/**
* Remove all extended information from the given node.
*
* @param node
* The node where to remove all extended info
* @param flag
* Bitfield for control purposes, unused yet, submit 0
* @return
* 1 on success, < 0 on error
*
* @since 1.0.2
*/
int iso_node_remove_all_xinfo(IsoNode *node, int flag);
/**
* Get the given extended info (defined by the proc function) from the
* given node.
@ -3208,6 +3379,102 @@ int iso_node_remove_xinfo(IsoNode *node, iso_node_xinfo_func proc);
*/
int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data);
/**
* Get the next pair of function pointer and data of an iteration of the
* list of extended informations. Like:
* iso_node_xinfo_func proc;
* void *handle = NULL, *data;
* while (iso_node_get_next_xinfo(node, &handle, &proc, &data) == 1) {
* ... make use of proc and data ...
* }
* The iteration allocates no memory. So you may end it without any disposal
* action.
* IMPORTANT: Do not continue iterations after manipulating the extended
* information of a node. Memory corruption hazard !
* @param node
* The node to inquire
* @param handle
* The opaque iteration handle. Initialize iteration by submitting
* a pointer to a void pointer with value NULL.
* Do not alter its content until iteration has ended.
* @param proc
* The function pointer which serves as key
* @param data
* Will be filled with the extended info corresponding to the given proc
* function
* @return
* 1 on success
* 0 if iteration has ended (proc and data are invalid then)
* < 0 on error
*
* @since 1.0.2
*/
int iso_node_get_next_xinfo(IsoNode *node, void **handle,
iso_node_xinfo_func *proc, void **data);
/**
* Class of functions to clone extended information. A function instance gets
* associated to a particular iso_node_xinfo_func instance by function
* iso_node_xinfo_make_clonable(). This is a precondition to have IsoNode
* objects clonable which carry data for a particular iso_node_xinfo_func.
*
* @param old_data
* Data item to be cloned
* @param new_data
* Shall return the cloned data item
* @param flag
* Unused yet, submit 0
* The function shall return ISO_XINFO_NO_CLONE on unknown flag bits.
* @return
* > 0 number of allocated bytes
* 0 no size info is available
* < 0 error
*
* @since 1.0.2
*/
typedef int (*iso_node_xinfo_cloner)(void *old_data, void **new_data,int flag);
/**
* Associate a iso_node_xinfo_cloner to a particular class of extended
* information in order to make it clonable.
*
* @param proc
* The key and disposal function which identifies the particular
* extended information class.
* @param cloner
* The cloner function which shall be associated with proc.
* @param flag
* Unused yet, submit 0
* @return
* 1 success, < 0 error
*
* @since 1.0.2
*/
int iso_node_xinfo_make_clonable(iso_node_xinfo_func proc,
iso_node_xinfo_cloner cloner, int flag);
/**
* Inquire the registered cloner function for a particular class of
* extended information.
*
* @param proc
* The key and disposal function which identifies the particular
* extended information class.
* @param cloner
* Will return the cloner function which is associated with proc, or NULL.
* @param flag
* Unused yet, submit 0
* @return
* 1 success, 0 no cloner registered for proc, < 0 error
*
* @since 1.0.2
*/
int iso_node_xinfo_get_cloner(iso_node_xinfo_func proc,
iso_node_xinfo_cloner *cloner, int flag);
/**
* Set the name of a node. Note that if the node is already added to a dir
* this can fail if dir already contains a node with the new name.
@ -3587,23 +3854,39 @@ int iso_dir_iter_take(IsoDirIter *iter);
/**
* Removes a child from a directory during an iteration and unref() it.
* It's like iso_node_remove(), but to be used during a directory iteration.
* The node removed will be the last returned by the iteration.
* Like iso_node_remove(), but to be used during a directory iteration.
* The node removed will be the one returned by the previous iteration.
*
* If you call this function twice without calling iso_dir_iter_next between
* them is not allowed and you will get an ISO_ERROR in second call.
* It is not allowed to call this function twice without calling
* iso_dir_iter_next inbetween.
*
* @return
* 1 on succes, < 0 error
* Possible errors:
* ISO_NULL_POINTER, if iter is NULL
* ISO_ERROR, on wrong iter usage, for example by call this before
* ISO_ERROR, on wrong iter usage, for example by calling this before
* iso_dir_iter_next.
*
* @since 0.6.2
*/
int iso_dir_iter_remove(IsoDirIter *iter);
/**
* Removes a node by iso_node_remove() or iso_dir_iter_remove(). If the node
* is a directory then the whole tree of nodes underneath is removed too.
*
* @param node
* The node to be removed.
* @param iter
* If not NULL, then the node will be removed by iso_dir_iter_remove(iter)
* else it will be removed by iso_node_remove(node).
* @return
* 1 is success, <0 indicates error
*
* @since 1.0.2
*/
int iso_node_remove_tree(IsoNode *node, IsoDirIter *boss_iter);
/**
* @since 0.6.4
@ -3982,6 +4265,24 @@ int iso_tree_add_new_dir(IsoDir *parent, const char *name, IsoDir **dir);
int iso_tree_add_new_file(IsoDir *parent, const char *name, IsoStream *stream,
IsoFile **file);
/**
* Create an IsoStream object from content which is stored in a dynamically
* allocated memory buffer. The new stream will become owner of the buffer
* and apply free() to it when the stream finally gets destroyed itself.
*
* @param buf
* The dynamically allocated memory buffer with the stream content.
* @parm size
* The number of bytes which may be read from buf.
* @param stream
* Will return a reference to the newly created stream.
* @return
* ISO_SUCCESS or <0 for error. E.g. ISO_NULL_POINTER, ISO_OUT_OF_MEM.
*
* @since 1.0.0
*/
int iso_memory_stream_new(unsigned char *buf, size_t size, IsoStream **stream);
/**
* Add a new symlink to the directory tree. Permissions are set to 0777,
* owner and hidden atts are taken from parent. You can modify any of them
@ -4322,6 +4623,57 @@ int iso_tree_add_new_cut_out_node(IsoImage *image, IsoDir *parent,
off_t offset, off_t size,
IsoNode **node);
/**
* Create a copy of the given node under a different path. If the node is
* actually a directory then clone its whole subtree.
* This call may fail because an IsoFile is encountered which gets fed by an
* IsoStream which cannot be cloned. See also IsoStream_Iface method
* clone_stream().
* Surely clonable node types are:
* IsoDir,
* IsoSymlink,
* IsoSpecial,
* IsoFile from a loaded ISO image,
* IsoFile referring to local filesystem files,
* IsoFile created by iso_tree_add_new_file
* from a stream created by iso_memory_stream_new(),
* IsoFile created by iso_tree_add_new_cut_out_node()
* Silently ignored are nodes of type IsoBoot.
* An IsoFile node with IsoStream filters can be cloned if all those filters
* are clonable and the node would be clonable without filter.
* Clonable IsoStream filters are created by:
* iso_file_add_zisofs_filter()
* iso_file_add_gzip_filter()
* iso_file_add_external_filter()
* An IsoNode with extended information as of iso_node_add_xinfo() can only be
* cloned if each of the iso_node_xinfo_func instances is associated to a
* clone function. See iso_node_xinfo_make_clonable().
* All internally used classes of extended information are clonable.
*
* @param node
* The node to be cloned.
* @param new_parent
* The existing directory node where to insert the cloned node.
* @param new_name
* The name for the cloned node. It must not yet exist in new_parent,
* unless it is a directory and node is a directory and flag bit0 is set.
* @param new_node
* Will return a pointer (without reference) to the newly created clone.
* @param flag
* Bitfield for control purposes. Submit any undefined bits as 0.
* bit0= Merge directories rather than returning ISO_NODE_NAME_NOT_UNIQUE.
* This will not allow to overwrite any existing node.
* Attributes of existing directories will not be overwritten.
* @return
* <0 means error, 1 = new node created,
* 2 = if flag bit0 is set: new_node is a directory which already existed.
*
* @since 1.0.2
*/
int iso_tree_clone(IsoNode *node,
IsoDir *new_parent, char *new_name, IsoNode **new_node,
int flag);
/**
* Add the contents of a dir to a given directory of the iso tree.
*
@ -5121,6 +5473,30 @@ char *iso_stream_get_source_path(IsoStream *stream, int flag);
*/
int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, int flag);
/**
* Produce a copy of a stream. It must be possible to operate both stream
* objects concurrently. The success of this function depends on the
* existence of a IsoStream_Iface.clone_stream() method with the stream
* and with its eventual subordinate streams.
* See iso_tree_clone() for a list of surely clonable built-in streams.
*
* @param old_stream
* The existing stream object to be copied
* @param new_stream
* Will return a pointer to the copy
* @param flag
* Bitfield for control purposes. Submit 0 for now.
* @return
* >0 means success
* ISO_STREAM_NO_CLONE is issued if no .clone_stream() exists
* other error return values < 0 may occur depending on kind of stream
*
* @since 1.0.2
*/
int iso_stream_clone(IsoStream *old_stream, IsoStream **new_stream, int flag);
/* --------------------------------- AAIP --------------------------------- */
/**
@ -5147,6 +5523,12 @@ int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, int flag);
*/
int aaip_xinfo_func(void *data, int flag);
/**
* The iso_node_xinfo_cloner function which gets associated to aaip_xinfo_func
* by iso_init() resp. iso_init_with_flag() via iso_node_xinfo_make_clonable().
* @since 1.0.2
*/
int aaip_xinfo_cloner(void *old_data, void **new_data, int flag);
/**
* Get the eventual ACLs which are associated with the node.
@ -6422,6 +6804,20 @@ int iso_md5_match(char first_md5[16], char second_md5[16]);
/** Displacement offset leads outside 32 bit range (FAILURE, HIGH, -372) */
#define ISO_DISPLACE_ROLLOVER 0xE830FE8C
/** File name cannot be written into ECMA-119 untranslated
(FAILURE, HIGH, -373) */
#define ISO_NAME_NEEDS_TRANSL 0xE830FE8B
/** Data file input stream object offers no cloning method
(FAILURE, HIGH, -374) */
#define ISO_STREAM_NO_CLONE 0xE830FE8A
/** Extended information class offers no cloning method
(FAILURE, HIGH, -375) */
#define ISO_XINFO_NO_CLONE 0xE830FE89
/** Found copied superblock checksum tag (WARNING, HIGH, -376) */
#define ISO_MD5_TAG_COPIED 0xD030FE88
/* Internal developer note:

View File

@ -1,5 +1,6 @@
LIBISOFS6 {
global:
aaip_xinfo_cloner;
aaip_xinfo_func;
el_torito_get_bootable;
el_torito_get_boot_media_type;
@ -133,6 +134,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 +157,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 +168,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 +184,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 +216,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 +242,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;
@ -255,6 +264,7 @@ iso_write_opts_new;
iso_write_opts_set_aaip;
iso_write_opts_set_aaip_susp_1_10;
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;
@ -276,6 +286,7 @@ 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;
@ -293,6 +304,7 @@ 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;

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>
@ -378,21 +386,19 @@ int make_isolinux_mbr(int32_t *img_blocks, uint32_t boot_lba,
int part_offset, int part_number, int fs_type,
uint8_t *buf, int flag)
{
uint32_t spc, id, part, nominal_part_size;
uint32_t id, part, nominal_part_size;
off_t hd_img_blocks, hd_boot_lba;
char *wpt;
/* For generating a weak random number */
struct timeval tv;
struct timezone tz;
/* 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);
}
/* 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;

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>
@ -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;
}
/* ----------------------------------------------------------------------- */

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,29 @@ 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;
return 1;
}
int iso_init()
{
return iso_init_with_flag(0);
@ -141,6 +226,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)
@ -361,6 +447,14 @@ const char *iso_error_to_msg(int errcode)
return "May not combine appended 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";
default:
return "Unknown error";
}

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
@ -226,6 +226,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.
*/
@ -651,6 +734,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 +772,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
@ -2153,6 +2277,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 +2415,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 +2520,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;

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,15 @@
#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
/**
* The extended information is a way to attach additional information to each
@ -113,6 +121,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;
@ -473,4 +482,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

@ -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
@ -897,7 +905,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 +914,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
@ -1097,6 +1122,44 @@ unannounced_ca:;
}
/* @param flag bit0= Do not add data but only count sua_free and ce_len
param info may be NULL in this case
*/
static
int add_aa_string(Ecma119Image *t, Ecma119Node *n, struct susp_info *info,
size_t *sua_free, size_t *ce_len, int flag)
{
int ret;
uint8_t *aapt;
void *xipt;
size_t num_aapt= 0;
if (!t->aaip)
return 1;
ret = iso_node_get_xinfo(n->node, aaip_xinfo_func, &xipt);
if (ret == 1) {
num_aapt = aaip_count_bytes((unsigned char *) xipt, 0);
if (num_aapt > 0) {
if (flag & 1) {
ret = aaip_add_AL(t, NULL,NULL, num_aapt, sua_free, ce_len, 1);
} else {
aapt = malloc(num_aapt);
if (aapt == NULL)
return ISO_OUT_OF_MEM;
memcpy(aapt, xipt, num_aapt);
ret = aaip_add_AL(t, info, &aapt, num_aapt, sua_free, ce_len,
0);
}
if (ret < 0)
return ret;
/* aapt is NULL now and the memory is owned by t */
}
}
return 1;
}
/**
* Compute the length needed for write all RR and SUSP entries for a given
* node.
@ -1104,27 +1167,31 @@ unannounced_ca:;
* @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 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 rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t used_up,
size_t *ce)
{
size_t su_size;
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;
}
/* 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 */;
@ -1190,9 +1257,15 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t space,
} else {
*ce = 182;
}
if (t->aaip) {
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;
}
}
@ -1224,43 +1297,6 @@ void susp_info_free(struct susp_info* susp)
}
/* @param flag bit0= Do not add data but only count sua_free and ce_len
*/
static
int add_aa_string(Ecma119Image *t, Ecma119Node *n, struct susp_info *info,
size_t *sua_free, size_t *ce_len, int flag)
{
int ret;
uint8_t *aapt;
void *xipt;
size_t num_aapt= 0;
if (!t->aaip)
return 1;
ret = iso_node_get_xinfo(n->node, aaip_xinfo_func, &xipt);
if (ret == 1) {
num_aapt = aaip_count_bytes((unsigned char *) xipt, 0);
if (num_aapt > 0) {
if (flag & 1) {
ret = aaip_add_AL(t, NULL,NULL, num_aapt, sua_free, ce_len, 1);
} else {
aapt = malloc(num_aapt);
if (aapt == NULL)
return ISO_OUT_OF_MEM;
memcpy(aapt, xipt, num_aapt);
ret = aaip_add_AL(t, info, &aapt, num_aapt, sua_free, ce_len,
0);
}
if (ret < 0)
return ret;
/* aapt is NULL now and the memory is owned by t */
}
}
return 1;
}
/**
* Fill a struct susp_info with the RR/SUSP entries needed for a given
* node.
@ -1268,8 +1304,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 +1315,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 +1327,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;
size_t 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, (int) space, ISO_ROCKRIDGE_IN_DIR_REC);
return ISO_ASSERT_FAILURE;
}
if (type == 2 && n->parent != NULL) {
@ -1306,13 +1349,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)
@ -1384,6 +1420,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, (int) 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 */
@ -1670,7 +1713,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;

View File

@ -443,7 +443,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 +514,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
@ -157,8 +157,64 @@ 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;
}
IsoStreamIface fsrc_stream_class = {
1, /* update_size is defined for this stream */
4, /* version */
"fsrc",
fsrc_open,
fsrc_close,
@ -167,7 +223,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)
@ -375,11 +434,76 @@ 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.
*/
IsoStreamIface cut_out_stream_class = {
0,
4, /* version */
"cout",
cut_out_open,
cut_out_close,
@ -387,7 +511,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,
@ -549,12 +678,77 @@ 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;
}
IsoStreamIface mem_stream_class = {
0,
4, /* version */
"mem ",
mem_open,
mem_close,
@ -562,7 +756,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
};
/**
@ -924,3 +1123,42 @@ ex:;
iso_md5_end(&ctx, md5);
return res;
}
/* 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;
@ -55,15 +56,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 +95,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_*/

View File

@ -809,3 +809,118 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
return ISO_SUCCESS;
}
/* Choose *heads_per_cyl so that
- *heads_per_cyl * secs_per_head * 1024 >= imgsize / 512
- *heads_per_cyl * secs_per_head is divisible by 4
- it is as small as possible (to reduce aligment overhead)
- it is <= 255
@return 1= success , 0= cannot achieve goals
*/
static
int try_sph(off_t imgsize, int secs_per_head, int *heads_per_cyl, int flag)
{
off_t hd_blocks, hpc;
hd_blocks= imgsize / 512;
hpc = hd_blocks / secs_per_head / 1024;
if (hpc * secs_per_head * 1024 < hd_blocks)
hpc++;
if ((secs_per_head % 4) == 0) {
;
} else if ((secs_per_head % 2) == 0) {
hpc += (hpc % 2);
} else if(hpc % 4) {
hpc += 4 - (hpc % 4);
}
if (hpc > 255)
return 0;
*heads_per_cyl = hpc;
return 1;
}
int iso_align_isohybrid(Ecma119Image *t, int flag)
{
int sa_type, ret, always_align;
uint32_t img_blocks;
off_t imgsize, cylsize = 0, frac;
char msg[160];
sa_type = (t->system_area_options >> 2) & 0x3f;
if (sa_type != 0)
return ISO_SUCCESS;
always_align = (t->system_area_options >> 8) & 3;
img_blocks = t->curblock;
imgsize = ((off_t) img_blocks) * (off_t) 2048;
if (((t->system_area_options & 3) || always_align)
&& (off_t) (t->partition_heads_per_cyl * t->partition_secs_per_head
* 1024) * (off_t) 512 < imgsize) {
/* Choose small values which can represent the image size */
/* First try 32 sectors per head */
ret = try_sph(imgsize, 32, &(t->partition_heads_per_cyl), 0);
if (ret == 1) {
t->partition_secs_per_head = 32;
} else {
/* Did not work with 32. Try 63 */
t->partition_secs_per_head = 63;
ret = try_sph(imgsize, 63, &(t->partition_heads_per_cyl), 0);
if (ret != 1)
t->partition_heads_per_cyl = 255;
}
cylsize = t->partition_heads_per_cyl * t->partition_secs_per_head *512;
frac = imgsize % cylsize;
sprintf(msg, "Automatically adjusted MBR geometry to %d/%d/%d",
(int) (imgsize / cylsize + !!frac),
t->partition_heads_per_cyl, t->partition_secs_per_head);
iso_msgs_submit(0, msg, 0, "NOTE", 0);
}
if (always_align >= 2)
return ISO_SUCCESS;
cylsize = 0;
if (t->catalog != NULL &&
(t->catalog->bootimages[0]->isolinux_options & 0x0a) == 0x02) {
/* Check for isolinux image with magic number of 3.72 and produce
an MBR from our built-in template. (Deprecated since 31 Mar 2010)
*/
if (img_blocks >= 0x40000000)
return ISO_SUCCESS;
cylsize = 64 * 32 * 512;
} else if ((t->system_area_options & 2) || always_align) {
/* Patch externally provided system area as isohybrid MBR */
if (t->catalog == NULL || t->system_area_data == NULL) {
/* isohybrid makes only sense together with ISOLINUX boot image
and externally provided System Area.
*/
return ISO_ISOLINUX_CANT_PATCH;
}
cylsize = t->partition_heads_per_cyl * t->partition_secs_per_head
* 512;
}
if (cylsize == 0)
return ISO_SUCCESS;
if (((double) imgsize) / (double) cylsize > 1024.0) {
iso_msgs_submit(0,
"Image size exceeds 1024 cylinders. Cannot align partition.",
0, "WARNING", 0);
return ISO_SUCCESS;
}
frac = imgsize % cylsize;
imgsize += (frac > 0 ? cylsize - frac : 0);
frac = imgsize - ((off_t) img_blocks) * (off_t) 2048;
if (frac == 0)
return ISO_SUCCESS;
if (frac % 2048) {
sprintf(msg,
"Cylinder size %d not divisible by 2048. Cannot align partition.",
(int) cylsize);
iso_msgs_submit(0, msg, 0, "WARNING", 0);
} else {
t->tail_blocks += frac / 2048;
}
return ISO_SUCCESS;
}

View File

@ -46,6 +46,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.

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
@ -993,3 +994,194 @@ char *iso_tree_get_node_path(IsoNode *node)
return strdup(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;
}

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2007 Mario Danic
* 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
@ -773,6 +773,8 @@ char *iso_r_dirid(const char *src, int size, int relaxed)
len = size;
}
dest = malloc(len + 1);
if (dest == NULL)
return NULL;
for (i = 0; i < len; i++) {
char c= src[i];
if (relaxed == 2) {
@ -1036,6 +1038,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));
}
@ -1294,12 +1298,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 +1342,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 +1439,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;
}
@ -1460,6 +1577,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);
@ -1721,10 +1840,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);

View File

@ -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
@ -505,12 +512,26 @@ 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);
/* ------------------------------------------------------------------------- */