Compare commits

...

33 Commits

Author SHA1 Message Date
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
31 changed files with 2066 additions and 224 deletions

View File

@ -1,7 +1,33 @@
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.2.tar.gz)
=============================================================================== ===============================================================================
- no novelties yet - no novelties yet
libisofs-1.0.2.tar.gz Tue Wed 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 libisofs-0.6.40.tar.gz Fri Dec 10 2010
=============================================================================== ===============================================================================
* New API call iso_write_opts_set_disc_label(), new system area type * 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.2], [http://libburnia-project.org])
AC_PREREQ([2.50]) AC_PREREQ([2.50])
dnl AC_CONFIG_HEADER([config.h]) dnl AC_CONFIG_HEADER([config.h])
@ -38,9 +38,9 @@ dnl It rather feeds the API function iso_lib_version().
dnl dnl
dnl If LIBISOFS_*_VERSION changes, be sure to change AC_INIT above to match. dnl If LIBISOFS_*_VERSION changes, be sure to change AC_INIT above to match.
dnl dnl
LIBISOFS_MAJOR_VERSION=0 LIBISOFS_MAJOR_VERSION=1
LIBISOFS_MINOR_VERSION=6 LIBISOFS_MINOR_VERSION=0
LIBISOFS_MICRO_VERSION=40 LIBISOFS_MICRO_VERSION=2
LIBISOFS_VERSION=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION.$LIBISOFS_MICRO_VERSION LIBISOFS_VERSION=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION.$LIBISOFS_MICRO_VERSION
AC_SUBST(LIBISOFS_MAJOR_VERSION) AC_SUBST(LIBISOFS_MAJOR_VERSION)
@ -50,10 +50,10 @@ AC_SUBST(LIBISOFS_VERSION)
dnl Libtool versioning dnl Libtool versioning
LT_RELEASE=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION LT_RELEASE=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION
# 2010.12.10 development jump has not yet happened # 2011.02.23 development jump has not yet happened
# SONAME = 42 - 36 = 6 . Library name = libisofs.6.36.0 # SONAME = 46 - 40 = 6 . Library name = libisofs.6.40.0
LT_CURRENT=42 LT_CURRENT=46
LT_AGE=36 LT_AGE=40
LT_REVISION=0 LT_REVISION=0
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE` LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
@ -133,15 +133,15 @@ AC_ARG_ENABLE(debug,
, enable_debug=yes) , enable_debug=yes)
if test x$enable_debug != xyes; then if test x$enable_debug != xyes; then
if test x$GCC = xyes; then if test x$GCC = xyes; then
CFLAGS="$CFLAGS -O3" CFLAGS="-O3 $CFLAGS"
CFLAGS="$CFLAGS -fexpensive-optimizations" CFLAGS="-fexpensive-optimizations $CFLAGS"
fi fi
CFLAGS="$CFLAGS -DNDEBUG" CFLAGS="-DNDEBUG $CFLAGS"
else else
if test x$GCC = xyes; then if test x$GCC = xyes; then
CFLAGS="$CFLAGS -g -pedantic -Wall" CFLAGS="-g -pedantic -Wall $CFLAGS"
fi fi
CFLAGS="$CFLAGS -DDEBUG" CFLAGS="-DDEBUG $CFLAGS"
fi fi
dnl Verbose debug to make libisofs issue more debug messages 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 | | "the number of virtual/emulated sectors the system
| | will store at Load Segment during the initial boot | | will store at Load Segment during the initial boot
| | procedure." | | procedure."
| | libisofs stores 1 for emulated boot_media and | | libisofs stores 1 for emulated boot_media and a
| | 0 for boot_media == 0. | | user defined value for boot_media == 0. Often: 4.
| | | |
8 - 11 | load_rba | Load RBA. The 2 kB block address where the boot 8 - 11 | load_rba | Load RBA. The 2 kB block address where the boot
| | image file content is located in the ISO 9660 image. | | image file content is located in the ISO 9660 image.
@ -210,8 +210,8 @@ Byte Range | Value | Meaning
| | | |
6 - 7 | sec_count | Sector Count. 6 - 7 | sec_count | Sector Count.
| | See above Initial/Default Entry | | See above Initial/Default Entry
| | libisofs stores 1 for emulated boot_media and | | libisofs stores 1 for emulated boot_media and a
| | 0 for boot_media == 0. | | user defined value for boot_media == 0. Often: 4.
| | | |
8 - 11 | load_rba | Load RBA. The 2 kB block address where the boot 8 - 11 | load_rba | Load RBA. The 2 kB block address where the boot
| | image file content is located in the ISO 9660 image. | | 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 END is also the block address of the start of the checksum recording
area in the image. area in the image.
See also isofs.cx . See also isofs.cx .
This attribute shall eventually be attached to the root directory entry
and be global for the whole image.
Format of Value: Format of Value:
START_LEN | START_BYTES | END_LEN | END_BYTES | START_LEN | START_BYTES | END_LEN | END_BYTES |
@ -150,7 +152,7 @@ Registered:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
This text is under This text is under
Copyright (c) 2009 - 2010 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2009 - 2011 Thomas Schmitt <scdbackup@gmx.net>
It shall only be modified in sync with libisofs and other software which It shall only be modified in sync with libisofs and other software which
makes use of AAIP. Please mail change requests to mailing list makes use of AAIP. Please mail change requests to mailing list
<libburn-hackers@pykix.org> or to the copyright holder in private. <libburn-hackers@pykix.org> or to the copyright holder in private.

View File

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

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2007 Mario Danic * Copyright (c) 2007 Mario Danic
* Copyright (c) 2009 - 2010 Thomas Schmitt * Copyright (c) 2009 - 2011 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -141,7 +141,7 @@ static int show_chunk_to_jte(Ecma119Image *target, char *buf, int count)
static static
int need_version_number(Ecma119Image *t, Ecma119Node *n) 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; return 0;
} }
if (n->type == ECMA119_DIR || n->type == ECMA119_PLACEHOLDER) { 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 */ /* size of "." and ".." entries */
len = 34 + 34; len = 34 + 34;
if (t->rockridge) { 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; *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; *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) { for (section = 0; section < nsections; ++section) {
size_t dirent_len = calc_dirent_len(t, child); size_t dirent_len = calc_dirent_len(t, child);
if (t->rockridge) { 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; *ce += ce_len;
} }
remaining = BLOCK_SIZE - (len % BLOCK_SIZE); 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 */; image start and not for the partition */;
} }
target->tree_end_block = target->curblock;
return ISO_SUCCESS; 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; multi_extend = (node->info.file->nsections - 1 == extent) ? 0 : 1;
} else { } else {
/* /*
* for nodes other than files and dirs, we set both * for nodes other than files and dirs, we set len to 0, and
* len and block to 0 * the content block address to a dummy value.
*/ */
len = 0; 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 */ /* write the "." and ".." entries first */
if (t->rockridge) { 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) { if (ret < 0) {
return ret; return ret;
} }
@ -604,7 +610,7 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *parent)
buf += len; buf += len;
if (t->rockridge) { 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) { if (ret < 0) {
return ret; return ret;
} }
@ -630,7 +636,7 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *parent)
/* get the SUSP fields if rockridge is enabled */ /* get the SUSP fields if rockridge is enabled */
if (t->rockridge) { 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) { if (ret < 0) {
return ret; return ret;
} }
@ -871,6 +877,7 @@ int ecma119_writer_write_data(IsoImageWriter *writer)
{ {
int ret; int ret;
Ecma119Image *t; Ecma119Image *t;
uint32_t curblock;
if (writer == NULL) { if (writer == NULL) {
return ISO_ASSERT_FAILURE; return ISO_ASSERT_FAILURE;
@ -888,6 +895,20 @@ int ecma119_writer_write_data(IsoImageWriter *writer)
if (ret < 0) if (ret < 0)
return ret; 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; return ISO_SUCCESS;
} }
@ -1135,6 +1156,8 @@ int write_vol_desc_terminator(Ecma119Image *target)
uint8_t buf[BLOCK_SIZE]; uint8_t buf[BLOCK_SIZE];
struct ecma119_vol_desc_terminator *vol; struct ecma119_vol_desc_terminator *vol;
memset(buf, 0, BLOCK_SIZE);
vol = (struct ecma119_vol_desc_terminator *) buf; vol = (struct ecma119_vol_desc_terminator *) buf;
vol->vol_desc_type[0] = 255; vol->vol_desc_type[0] = 255;
@ -1209,7 +1232,7 @@ int write_head_part2(Ecma119Image *target, int *write_count, int flag)
return ISO_SUCCESS; return ISO_SUCCESS;
/* Write multi-session padding up to target->partition_offset + 16 */ /* 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)++) { for(; *write_count < target->partition_offset + 16; (*write_count)++) {
res = iso_write(target, buf, BLOCK_SIZE); res = iso_write(target, buf, BLOCK_SIZE);
if (res < 0) if (res < 0)
@ -1400,6 +1423,12 @@ void *write_function(void *arg)
Eventually free target */ Eventually free target */
ecma119_image_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, "WARNING", 0);
}
#ifdef Libisofs_with_pthread_exiT #ifdef Libisofs_with_pthread_exiT
pthread_exit(NULL); pthread_exit(NULL);
#else #else
@ -1575,6 +1604,9 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
target->hardlinks = opts->hardlinks; target->hardlinks = opts->hardlinks;
target->aaip = opts->aaip; target->aaip = opts->aaip;
target->always_gmt = opts->always_gmt; 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 target->omit_version_numbers = opts->omit_version_numbers
| opts->max_37_char_filenames; | opts->max_37_char_filenames;
target->allow_deep_paths = opts->allow_deep_paths; target->allow_deep_paths = opts->allow_deep_paths;
@ -1731,6 +1763,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
target->mipsel_p_filesz = 0; target->mipsel_p_filesz = 0;
target->empty_file_block = 0; target->empty_file_block = 0;
target->tree_end_block = 0;
target->wthread_is_running = 0; target->wthread_is_running = 0;
@ -1918,8 +1951,15 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
if (i == el_torito_writer_index) if (i == el_torito_writer_index)
continue; continue;
/* Exposing address of data start to IsoWriteOpts */ /* Exposing address of data start to IsoWriteOpts iand memorizing
this address for 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 (i == file_src_writer_index) {
if (! target->old_empty)
target->empty_file_block = target->curblock;
opts->data_start_lba = target->curblock; opts->data_start_lba = target->curblock;
} }
@ -2266,6 +2306,8 @@ int iso_write(Ecma119Image *target, void *buf, size_t count)
/* reader cancelled */ /* reader cancelled */
return ISO_CANCELED; return ISO_CANCELED;
} }
if (ret < 0)
return ret;
if (target->checksum_ctx != NULL) { if (target->checksum_ctx != NULL) {
/* Add to image checksum */ /* Add to image checksum */
target->checksum_counter += count; target->checksum_counter += count;
@ -2277,7 +2319,7 @@ int iso_write(Ecma119Image *target, void *buf, size_t count)
return ret; return ret;
/* total size is 0 when writing the overwrite buffer */ /* 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; unsigned int kbw, kbt;
int percent; int percent;
@ -2294,7 +2336,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) int iso_write_opts_new(IsoWriteOpts **opts, int profile)
@ -2363,6 +2405,9 @@ int iso_write_opts_new(IsoWriteOpts **opts, int profile)
wopts->appended_partitions[i] = NULL; wopts->appended_partitions[i] = NULL;
wopts->ascii_disc_label[0] = 0; wopts->ascii_disc_label[0] = 0;
wopts->will_cancel = 0; wopts->will_cancel = 0;
wopts->allow_dir_id_ext = 0;
wopts->old_empty = 0;
wopts->untranslated_name_len = 0;
*opts = wopts; *opts = wopts;
return ISO_SUCCESS; return ISO_SUCCESS;
@ -2451,6 +2496,40 @@ int iso_write_opts_set_aaip(IsoWriteOpts *opts, int enable)
return ISO_SUCCESS; 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) int iso_write_opts_set_omit_version_numbers(IsoWriteOpts *opts, int omit)
{ {
if (opts == NULL) { if (opts == NULL) {

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt * Copyright (c) 2009 - 2011 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -15,7 +15,14 @@
#include "util.h" #include "util.h"
#include "buffer.h" #include "buffer.h"
#ifdef HAVE_STDINT_H
#include <stdint.h> #include <stdint.h>
#else
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#endif
#include <pthread.h> #include <pthread.h>
#define BLOCK_SIZE 2048 #define BLOCK_SIZE 2048
@ -52,6 +59,17 @@
#define ISO_DISC_LABEL_SIZE 129 #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. * 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. * 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. * Omit the version number (";1") at the end of the ISO-9660 identifiers.
* Version numbers are usually not used. * Version numbers are usually not used.
@ -218,6 +244,26 @@ struct iso_write_opts {
uid_t uid; /** uid to use when replace_uid == 2. */ uid_t uid; /** uid to use when replace_uid == 2. */
gid_t gid; /** gid to use when replace_gid == 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 * 0 to use IsoNode timestamps, 1 to use recording time, 2 to use
* values from timestamp field. This has only meaning if RR extensions * values from timestamp field. This has only meaning if RR extensions
@ -399,6 +445,7 @@ struct ecma119_image
unsigned int always_gmt :1; unsigned int always_gmt :1;
/* relaxed constraints */ /* relaxed constraints */
unsigned int allow_dir_id_ext :1;
unsigned int omit_version_numbers :2; unsigned int omit_version_numbers :2;
unsigned int allow_deep_paths :1; unsigned int allow_deep_paths :1;
unsigned int allow_longer_paths :1; unsigned int allow_longer_paths :1;
@ -443,6 +490,9 @@ struct ecma119_image
mode_t dir_mode; mode_t dir_mode;
time_t timestamp; time_t timestamp;
unsigned int old_empty :1;
unsigned int untranslated_name_len;
/** /**
* if sort files or not. Sorting is based of the weight of each file * if sort files or not. Sorting is based of the weight of each file
*/ */
@ -475,6 +525,12 @@ struct ecma119_image
*/ */
uint32_t empty_file_block; uint32_t empty_file_block;
/*
* The calculated block address after ECMA-119 tree and eventual
* tree checksum tag.
*/
uint32_t tree_end_block;
/* /*
* number of dirs in ECMA-119 tree, computed together with dir position, * number of dirs in ECMA-119 tree, computed together with dir position,
* and needed for path table computation in a efficient way * and needed for path table computation in a efficient way

View File

@ -12,6 +12,9 @@
#include "../config.h" #include "../config.h"
#endif #endif
/* Must be before ecma119.h because of eventual Libisofs_with_rrip_rR */
#include "libisofs.h"
#include "ecma119_tree.h" #include "ecma119_tree.h"
#include "ecma119.h" #include "ecma119.h"
#include "node.h" #include "node.h"
@ -29,7 +32,7 @@
static static
int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name) int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name)
{ {
int ret, relaxed; int ret, relaxed, free_ascii_name= 0, force_dots = 0, max_len;
char *ascii_name; char *ascii_name;
char *isoname= NULL; char *isoname= NULL;
@ -38,9 +41,16 @@ int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name)
return ISO_SUCCESS; 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) { 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; return ret;
} }
@ -49,8 +59,18 @@ int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name)
} else { } else {
relaxed = (int)img->allow_lowercase; relaxed = (int)img->allow_lowercase;
} }
if (iso->type == LIBISO_DIR) { if (iso->type == LIBISO_DIR && !(img->allow_dir_id_ext)) {
if (img->max_37_char_filenames) { 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); isoname = iso_r_dirid(ascii_name, 37, relaxed);
} else if (img->iso_level == 1) { } else if (img->iso_level == 1) {
if (relaxed) { if (relaxed) {
@ -60,32 +80,40 @@ int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name)
} }
} else { } else {
if (relaxed) { if (relaxed) {
isoname = iso_r_dirid(ascii_name, 8, relaxed); isoname = iso_r_dirid(ascii_name, 31, relaxed);
} else { } else {
isoname = iso_2_dirid(ascii_name); isoname = iso_2_dirid(ascii_name);
} }
} }
} else { } else {
if (img->max_37_char_filenames) { force_dots = !((img->no_force_dots & 1) || iso->type == LIBISO_DIR);
isoname = iso_r_fileid(ascii_name, 36, relaxed, if (img->untranslated_name_len > 0) {
(img->no_force_dots & 1) ? 0 : 1); 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) { } else if (img->iso_level == 1) {
if (relaxed) { if (relaxed || !force_dots) {
isoname = iso_r_fileid(ascii_name, 11, relaxed, if (strchr(ascii_name, '.') == NULL)
(img->no_force_dots & 1) ? 0 : 1); max_len = 8;
else
max_len = 11;
isoname = iso_r_fileid(ascii_name, max_len, relaxed,
force_dots);
} else { } else {
isoname = iso_1_fileid(ascii_name); isoname = iso_1_fileid(ascii_name);
} }
} else { } else {
if (relaxed) { if (relaxed || !force_dots) {
isoname = iso_r_fileid(ascii_name, 30, relaxed, isoname = iso_r_fileid(ascii_name, 30, relaxed, force_dots);
(img->no_force_dots & 1) ? 0 : 1);
} else { } else {
isoname = iso_2_fileid(ascii_name); isoname = iso_2_fileid(ascii_name);
} }
} }
} }
free(ascii_name); if (free_ascii_name)
free(ascii_name);
if (isoname != NULL) { if (isoname != NULL) {
*name = isoname; *name = isoname;
return ISO_SUCCESS; return ISO_SUCCESS;
@ -416,8 +444,6 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree,
!!hidden); !!hidden);
if (cret < 0) { if (cret < 0) {
/* error */ /* error */
if (!hidden)
ecma119_node_free(node);
ret = cret; ret = cret;
break; break;
} else if (cret == ISO_SUCCESS && !hidden) { } else if (cret == ISO_SUCCESS && !hidden) {
@ -537,6 +563,18 @@ int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
continue; 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 * 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 * 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 */ /* compute name and extension */
dot = strrchr(full_name, '.'); 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 * Note that we don't need to check for placeholders, as
* tree reparent happens later, so no placeholders can be * tree reparent happens later, so no placeholders can be
* here at this time. * here at this time.
@ -596,10 +635,10 @@ int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
name[max] = '\0'; name[max] = '\0';
} }
} else { } else {
/* Directory, or file without extension */ /* Directory (normally), or file without extension */
if (children[i]->type == ECMA119_DIR) { if (children[i]->type == ECMA119_DIR) {
max = max_dir_len - digits; max = max_dir_len - digits;
dot = NULL; /* dots have no meaning in dirs */ dot = NULL; /* dots (normally) have no meaning in dirs */
} else { } else {
max = max_file_len - digits; max = max_file_len - digits;
} }
@ -716,7 +755,9 @@ int mangle_tree(Ecma119Image *img, int recurse)
int max_file, max_dir; int max_file, max_dir;
Ecma119Node *root; 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; max_file = max_dir = 37;
} else if (img->iso_level == 1) { } else if (img->iso_level == 1) {
max_file = 12; /* 8 + 3 + 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); iso_node_get_id(nodes[0]->node, &fs_id, &dev_id, &img_ino, 1);
family_start = 0; family_start = 0;
for (i = 1; i < node_count; i++) { for (i = 1; i < node_count; i++) {
if (ecma119_node_cmp_hard(nodes + (i - 1), nodes + i) == 0) { if (nodes[i]->type != ECMA119_DIR &&
ecma119_node_cmp_hard(nodes + (i - 1), nodes + i) == 0) {
/* Still in same ino family */ /* Still in same ino family */
if (img_ino == 0) { /* Just in case any member knows its img_ino */ if (img_ino == 0) { /* Just in case any member knows its img_ino */
iso_node_get_id(nodes[0]->node, &fs_id, &dev_id, &img_ino, 1); iso_node_get_id(nodes[0]->node, &fs_id, &dev_id, &img_ino, 1);
} }
continue; continue;
} }
family_set_ino(img, nodes, family_start, i, img_ino, prev_ino, 0); family_set_ino(img, nodes, family_start, i, img_ino, prev_ino, 0);

View File

@ -12,8 +12,8 @@
#include "../config.h" #include "../config.h"
#endif #endif
#include "libisofs.h"
#include "eltorito.h" #include "eltorito.h"
#include "stream.h"
#include "fsource.h" #include "fsource.h"
#include "filesrc.h" #include "filesrc.h"
#include "image.h" #include "image.h"

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * 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 * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -232,6 +232,12 @@ int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
t = writer->target; 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 */ /* on appendable images, ms files shouldn't be included */
if (t->appendable) { if (t->appendable) {
inc_item = is_ms_file; inc_item = is_ms_file;
@ -347,11 +353,22 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
return ISO_ASSERT_FAILURE; return ISO_ASSERT_FAILURE;
} }
memset(buffer, 0, BLOCK_SIZE);
t = writer->target; t = writer->target;
filelist = writer->data; filelist = writer->data;
iso_msg_debug(t->image->id, "Writing Files..."); 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; i = 0;
while ((file = filelist[i++]) != NULL) { while ((file = filelist[i++]) != NULL) {
was_error = 0; was_error = 0;

View File

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

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 * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -25,6 +25,7 @@
#include "../filter.h" #include "../filter.h"
#include "../fsource.h" #include "../fsource.h"
#include "../util.h" #include "../util.h"
#include "../stream.h"
#include <sys/types.h> #include <sys/types.h>
#include <sys/time.h> #include <sys/time.h>
@ -153,6 +154,7 @@ static int gzip_compression_level = 6;
/* /*
* The data payload of an individual Gzip Filter IsoStream * The data payload of an individual Gzip Filter IsoStream
*/ */
/* IMPORTANT: Any change must be reflected by gzip_clone_stream() */
typedef struct typedef struct
{ {
IsoStream *orig; IsoStream *orig;
@ -529,12 +531,41 @@ IsoStream *gzip_get_input_stream(IsoStream *stream, int flag)
} }
static
int gzip_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag)
{
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;
}
static static
int gzip_cmp_ino(IsoStream *s1, IsoStream *s2); int gzip_cmp_ino(IsoStream *s1, IsoStream *s2);
IsoStreamIface gzip_stream_compress_class = { IsoStreamIface gzip_stream_compress_class = {
3, 4,
"gzip", "gzip",
gzip_stream_open, gzip_stream_open,
gzip_stream_close, gzip_stream_close,
@ -545,12 +576,13 @@ IsoStreamIface gzip_stream_compress_class = {
gzip_stream_free, gzip_stream_free,
gzip_update_size, gzip_update_size,
gzip_get_input_stream, gzip_get_input_stream,
gzip_cmp_ino gzip_cmp_ino,
gzip_clone_stream
}; };
IsoStreamIface gzip_stream_uncompress_class = { IsoStreamIface gzip_stream_uncompress_class = {
3, 4,
"pizg", "pizg",
gzip_stream_open, gzip_stream_open,
gzip_stream_close, gzip_stream_close,
@ -561,7 +593,8 @@ IsoStreamIface gzip_stream_uncompress_class = {
gzip_stream_free, gzip_stream_free,
gzip_update_size, gzip_update_size,
gzip_get_input_stream, gzip_get_input_stream,
gzip_cmp_ino gzip_cmp_ino,
gzip_clone_stream
}; };

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 * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -22,6 +22,7 @@
#include "../filter.h" #include "../filter.h"
#include "../fsource.h" #include "../fsource.h"
#include "../util.h" #include "../util.h"
#include "../stream.h"
#include <sys/types.h> #include <sys/types.h>
#include <sys/time.h> #include <sys/time.h>
@ -167,6 +168,7 @@ static int ziso_compression_level = 6;
/* /*
* The common data payload of an individual Zisofs Filter IsoStream * The common data payload of an individual Zisofs Filter IsoStream
* IMPORTANT: Any change must be reflected by ziso_clone_stream().
*/ */
typedef struct typedef struct
{ {
@ -183,6 +185,7 @@ typedef struct
/* /*
* The data payload of an individual Zisofs Filter Compressor IsoStream * The data payload of an individual Zisofs Filter Compressor IsoStream
* IMPORTANT: Any change must be reflected by ziso_clone_stream().
*/ */
typedef struct typedef struct
{ {
@ -198,6 +201,7 @@ typedef struct
/* /*
* The data payload of an individual Zisofs Filter Uncompressor IsoStream * The data payload of an individual Zisofs Filter Uncompressor IsoStream
* IMPORTANT: Any change must be reflected by ziso_clone_stream().
*/ */
typedef struct typedef struct
{ {
@ -779,13 +783,63 @@ IsoStream *ziso_get_input_stream(IsoStream *stream, int flag)
return data->orig; return data->orig;
} }
static
int ziso_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag)
{
int ret;
IsoStream *new_input_stream = NULL, *stream = NULL;
ZisofsFilterStreamData *stream_data, *old_stream_data;
ZisofsUncomprStreamData *uncompr, *old_uncompr;
ZisofsComprStreamData *compr, *old_compr;
if (flag)
return ISO_STREAM_NO_CLONE; /* unknown option required */
ret = iso_stream_clone_filter_common(old_stream, &stream,
&new_input_stream, 0);
if (ret < 0)
return ret;
if (old_stream->class->read == &ziso_stream_uncompress) {
uncompr = calloc(1, sizeof(ZisofsUncomprStreamData));
if (uncompr == NULL)
goto no_mem;
stream_data = (ZisofsFilterStreamData *) uncompr;
old_uncompr = (ZisofsUncomprStreamData *) old_stream->data;
uncompr->header_size_div4 = old_uncompr->header_size_div4;
uncompr->block_size_log2 = old_uncompr->block_size_log2;
} else {
compr = calloc(1, sizeof(ZisofsComprStreamData));
if (compr == NULL)
goto no_mem;
stream_data = (ZisofsFilterStreamData *) compr;
old_compr = (ZisofsComprStreamData *) old_stream->data;
compr->orig_size = old_compr->orig_size;
compr->block_pointers = NULL;
}
old_stream_data = (ZisofsFilterStreamData *) old_stream->data;
stream_data->orig = new_input_stream;
stream_data->size = old_stream_data->size;
stream_data->running = NULL;
stream_data->id = ++ziso_ino_id;
stream->data = stream_data;
*new_stream = stream;
return ISO_SUCCESS;
no_mem:
if (new_input_stream != NULL)
iso_stream_unref(new_input_stream);
if (stream != NULL)
iso_stream_unref(stream);
return ISO_OUT_OF_MEM;
}
static static
int ziso_cmp_ino(IsoStream *s1, IsoStream *s2); int ziso_cmp_ino(IsoStream *s1, IsoStream *s2);
IsoStreamIface ziso_stream_compress_class = { IsoStreamIface ziso_stream_compress_class = {
3, 4,
"ziso", "ziso",
ziso_stream_open, ziso_stream_open,
ziso_stream_close, ziso_stream_close,
@ -796,12 +850,13 @@ IsoStreamIface ziso_stream_compress_class = {
ziso_stream_free, ziso_stream_free,
ziso_update_size, ziso_update_size,
ziso_get_input_stream, ziso_get_input_stream,
ziso_cmp_ino ziso_cmp_ino,
ziso_clone_stream
}; };
IsoStreamIface ziso_stream_uncompress_class = { IsoStreamIface ziso_stream_uncompress_class = {
3, 4,
"osiz", "osiz",
ziso_stream_open, ziso_stream_open,
ziso_stream_close, ziso_stream_close,
@ -812,7 +867,8 @@ IsoStreamIface ziso_stream_uncompress_class = {
ziso_stream_free, ziso_stream_free,
ziso_update_size, ziso_update_size,
ziso_get_input_stream, ziso_get_input_stream,
ziso_cmp_ino ziso_cmp_ino,
ziso_clone_stream
}; };

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * 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 * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -317,6 +317,7 @@ typedef struct
typedef struct image_fs_data ImageFileSourceData; typedef struct image_fs_data ImageFileSourceData;
/* IMPORTANT: Any change must be reflected by ifs_clone_src */
struct image_fs_data struct image_fs_data
{ {
IsoImageFilesystem *fs; /**< reference to the image it belongs to */ 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; 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 = { IsoFileSourceIface ifs_class = {
1, /* version */ 2, /* version */
ifs_get_path, ifs_get_path,
ifs_get_name, ifs_get_name,
ifs_lstat, ifs_lstat,
@ -1060,7 +1138,8 @@ IsoFileSourceIface ifs_class = {
ifs_get_filesystem, ifs_get_filesystem,
ifs_free, ifs_free,
ifs_lseek, ifs_lseek,
ifs_get_aa_string ifs_get_aa_string,
ifs_clone_src
}; };

View File

@ -39,7 +39,7 @@ int iso_file_source_new_lfs(IsoFileSource *parent, const char *name,
*/ */
IsoFilesystem *lfs= NULL; IsoFilesystem *lfs= NULL;
/* IMPORTANT: Any change must be reflected by lfs_clone_src() */
typedef struct typedef struct
{ {
/** reference to the parent (if root it points to itself) */ /** reference to the parent (if root it points to itself) */
@ -534,10 +534,56 @@ ex:;
return ret; return ret;
} }
static
int lfs_clone_src(IsoFileSource *old_source,
IsoFileSource **new_source, int flag)
{
IsoFileSource *src = NULL;
char *new_name = NULL;
_LocalFsFileSource *old_data, *new_data = NULL;
if (flag)
return ISO_STREAM_NO_CLONE; /* unknown option required */
old_data = (_LocalFsFileSource *) old_source->data;
*new_source = NULL;
src = calloc(1, sizeof(IsoFileSource));
if (src == NULL)
goto no_mem;
new_name = strdup(old_data->name);
if (new_name == NULL)
goto no_mem;
new_data = calloc(1, sizeof(_LocalFsFileSource));
if (new_data == NULL)
goto no_mem;
new_data->openned = 0;
new_data->info.fd = -1; /* the value does not matter with (openned == 0) */
new_data->name = new_name;
new_data->parent = old_data->parent;
src->class = old_source->class;
src->refcount = 1;
src->data = new_data;
*new_source = src;
iso_file_source_ref(new_data->parent);
iso_filesystem_ref(lfs);
return ISO_SUCCESS;
no_mem:;
if (src != NULL)
free((char *) src);
if (new_data != NULL)
free((char *) new_data);
if (new_name != NULL)
free(new_name);
return ISO_OUT_OF_MEM;
}
IsoFileSourceIface lfs_class = { IsoFileSourceIface lfs_class = {
1, /* version */ 2, /* version */
lfs_get_path, lfs_get_path,
lfs_get_name, lfs_get_name,
lfs_lstat, lfs_lstat,
@ -551,7 +597,8 @@ IsoFileSourceIface lfs_class = {
lfs_get_filesystem, lfs_get_filesystem,
lfs_free, lfs_free,
lfs_lseek, lfs_lseek,
lfs_get_aa_string lfs_get_aa_string,
lfs_clone_src
}; };

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt * Copyright (c) 2009 - 2011 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -33,9 +33,16 @@
int iso_local_filesystem_new(IsoFilesystem **fs); int iso_local_filesystem_new(IsoFilesystem **fs);
/* Rank two IsoFileSource by their eventual old image LBAs. /* Rank two IsoFileSource of ifs_class by their eventual old image LBAs.
Other IsoFileSource classes will be ranked only roughly. Other IsoFileSource classes will be ranked only roughly.
*/ */
int iso_ifs_sections_cmp(IsoFileSource *s1, IsoFileSource *s2, int flag); int iso_ifs_sections_cmp(IsoFileSource *s1, IsoFileSource *s2, int flag);
/* Create an independent copy of an ifs_class IsoFileSource.
*/
int iso_ifs_source_clone(IsoFileSource *old_source, IsoFileSource **new_source,
int flag);
#endif /*LIBISO_FSOURCE_H_*/ #endif /*LIBISO_FSOURCE_H_*/

View File

@ -1,6 +1,10 @@
#ifndef LIBISO_LIBISOFS_H_
#define LIBISO_LIBISOFS_H_
/* /*
* Copyright (c) 2007-2008 Vreixo Formoso, Mario Danic * 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 * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -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> #include <sys/stat.h>
#ifdef HAVE_STDINT_H
#include <stdint.h> #include <stdint.h>
#else
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#endif
#include <stdlib.h> #include <stdlib.h>
struct burn_source; struct burn_source;
@ -494,6 +515,8 @@ struct IsoFileSource_Iface
* @since 0.6.2 * @since 0.6.2
* Version 1 additionally provides function *(get_aa_string)(). * Version 1 additionally provides function *(get_aa_string)().
* @since 0.6.14 * @since 0.6.14
* Version 2 additionally provides function *(clone_src)().
* @since 1.0.2
*/ */
int version; int version;
@ -728,6 +751,24 @@ struct IsoFileSource_Iface
int (*get_aa_string)(IsoFileSource *src, int (*get_aa_string)(IsoFileSource *src,
unsigned char **aa_string, int flag); 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. * TODO #00004 Add a get_mime_type() function.
* This can be useful for GUI apps, to choose the icon of the file * 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 /* ! Libisofs_h_as_cpluspluS */
#endif /* ! __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 * Representation of file contents. It is an stream of bytes, functionally
* like a pipe. * like a pipe.
@ -787,6 +853,7 @@ extern ino_t serial_id;
* *
* @since 0.6.4 * @since 0.6.4
*/ */
struct IsoStream_Iface struct IsoStream_Iface
{ {
/* /*
@ -799,6 +866,8 @@ struct IsoStream_Iface
* get_input_stream() added. A filter stream must have version 2. * get_input_stream() added. A filter stream must have version 2.
* Version 3 (since 0.6.20) * Version 3 (since 0.6.20)
* compare() added. A filter stream should have version 3. * compare() added. A filter stream should have version 3.
* Version 4 (since 1.0.2)
* clone_stream() added.
*/ */
int version; int version;
@ -841,7 +910,7 @@ struct IsoStream_Iface
off_t (*get_size)(IsoStream *stream); 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 * the buffer starting at buf. The implementation has to make sure that
* either the full desired count of bytes is delivered or that the * either the full desired count of bytes is delivered or that the
* next call to this function will return EOF or error. * 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); int (*read)(IsoStream *stream, void *buf, size_t count);
/** /**
* Whether this IsoStream can be read several times, with the same results. * Tell whether this IsoStream can be read several times, with the same
* For example, a regular file is repeatable, you can read it as many * results. For example, a regular file is repeatable, you can read it
* times as you want. However, a pipe isn't. * as many times as you want. However, a pipe is not.
*
* This function doesn't take into account if the file has been modified
* between the two reads.
* *
* @return * @return
* 1 if stream is repeatable, 0 if not, * 1 if stream is repeatable, 0 if not,
@ -883,13 +949,13 @@ struct IsoStream_Iface
void (*free)(IsoStream *stream); void (*free)(IsoStream *stream);
/** /**
* Updates the size of the IsoStream with the current size of the * Update the size of the IsoStream with the current size of the underlying
* underlying source. After calling this, get_size() will return * source, if the source is prone to size changes. After calling this,
* the new size. This should never be called after * get_size() shall eventually return the new size.
* iso_image_create_burn_source() was called and the image was not * This will never be called after iso_image_create_burn_source() was
* completely written. To update the size of all files before written the * called and before the image was completely written.
* image, you may want to call iso_image_update_sizes() just before * (The API call to update the size of all files in the image is
* iso_image_create_burn_source(). * iso_image_update_sizes()).
* *
* @return * @return
* 1 if ok, < 0 on error (has to be a valid libisofs error code) * 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); 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 * @param stream
* The eventual filter stream to be inquired. * The eventual filter stream to be inquired.
* @param flag * @param flag
* Bitfield for control purposes. Submit 0 for now. * Bitfield for control purposes. 0 means normal behavior.
* @return * @return
* The input stream, if one exists. Elsewise NULL. * 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 * @since 0.6.18
* Present if .version is 2 or higher. * 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 * produce the same output. If in any doubt, then this comparison should
* indicate no match. A match might allow hardlinking of IsoFile objects. * 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,A) == 0
* cmp_ino(A,B) == -cmp_ino(B,A) * 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
* 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 * 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 * types of streams.Thus it is mandatory to let iso_stream_cmp_ino(s1,s2,1)
* that is not applicable, cmp_ino(A,B) must have the same non-zero * decide in this case.
* 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.
* *
* A function s1.(*cmp_ino)() must only accept stream s2 if function * 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 * 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. * 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 * @param s1
* The first stream to compare. Expect foreign stream types. * The first stream to compare. Expect foreign stream types.
* @param s2 * @param s2
@ -959,6 +1024,26 @@ struct IsoStream_Iface
*/ */
int (*cmp_ino)(IsoStream *s1, IsoStream *s2); 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 #ifndef __cplusplus
@ -1120,9 +1205,9 @@ int iso_lib_is_compatible(int major, int minor, int micro);
* *
* @since 0.6.2 * @since 0.6.2
*/ */
#define iso_lib_header_version_major 0 #define iso_lib_header_version_major 1
#define iso_lib_header_version_minor 6 #define iso_lib_header_version_minor 0
#define iso_lib_header_version_micro 40 #define iso_lib_header_version_micro 2
/** /**
* Usage discussion: * 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); 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. * Omit the version number (";1") at the end of the ISO-9660 identifiers.
* This breaks ECMA-119 specification, but version numbers are usually not * This breaks ECMA-119 specification, but version numbers are usually not
@ -3132,9 +3281,9 @@ void iso_node_unref(IsoNode *node);
enum IsoNodeType iso_node_get_type(IsoNode *node); enum IsoNodeType iso_node_get_type(IsoNode *node);
/** /**
* Function to handle particular extended information. The function * Class of functions to handle particular extended information. A function
* pointer acts as an identifier for the type of the information. Structs * instance acts as an identifier for the type of the information. Structs
* with same information type must use the same function. * with same information type must use a pointer to the same function.
* *
* @param data * @param data
* Attached data * Attached data
@ -3189,6 +3338,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); 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 * Get the given extended info (defined by the proc function) from the
* given node. * given node.
@ -3208,6 +3371,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); 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 * 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. * this can fail if dir already contains a node with the new name.
@ -3587,23 +3846,39 @@ int iso_dir_iter_take(IsoDirIter *iter);
/** /**
* Removes a child from a directory during an iteration and unref() it. * 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. * Like iso_node_remove(), but to be used during a directory iteration.
* The node removed will be the last returned by the 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 * It is not allowed to call this function twice without calling
* them is not allowed and you will get an ISO_ERROR in second call. * iso_dir_iter_next inbetween.
* *
* @return * @return
* 1 on succes, < 0 error * 1 on succes, < 0 error
* Possible errors: * Possible errors:
* ISO_NULL_POINTER, if iter is NULL * 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. * iso_dir_iter_next.
* *
* @since 0.6.2 * @since 0.6.2
*/ */
int iso_dir_iter_remove(IsoDirIter *iter); 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 * @since 0.6.4
@ -3982,6 +4257,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, int iso_tree_add_new_file(IsoDir *parent, const char *name, IsoStream *stream,
IsoFile **file); 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, * 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 * owner and hidden atts are taken from parent. You can modify any of them
@ -4322,6 +4615,57 @@ int iso_tree_add_new_cut_out_node(IsoImage *image, IsoDir *parent,
off_t offset, off_t size, off_t offset, off_t size,
IsoNode **node); 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. * Add the contents of a dir to a given directory of the iso tree.
* *
@ -5121,6 +5465,30 @@ char *iso_stream_get_source_path(IsoStream *stream, int flag);
*/ */
int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, 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 --------------------------------- */ /* --------------------------------- AAIP --------------------------------- */
/** /**
@ -5147,6 +5515,12 @@ int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, int flag);
*/ */
int aaip_xinfo_func(void *data, 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. * Get the eventual ACLs which are associated with the node.
@ -6422,6 +6796,17 @@ int iso_md5_match(char first_md5[16], char second_md5[16]);
/** Displacement offset leads outside 32 bit range (FAILURE, HIGH, -372) */ /** Displacement offset leads outside 32 bit range (FAILURE, HIGH, -372) */
#define ISO_DISPLACE_ROLLOVER 0xE830FE8C #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
/* Internal developer note: /* Internal developer note:

View File

@ -1,5 +1,6 @@
LIBISOFS6 { LIBISOFS6 {
global: global:
aaip_xinfo_cloner;
aaip_xinfo_func; aaip_xinfo_func;
el_torito_get_bootable; el_torito_get_bootable;
el_torito_get_boot_media_type; el_torito_get_boot_media_type;
@ -133,6 +134,7 @@ iso_md5_compute;
iso_md5_end; iso_md5_end;
iso_md5_match; iso_md5_match;
iso_md5_start; iso_md5_start;
iso_memory_stream_new;
iso_msgs_submit; iso_msgs_submit;
iso_new_find_conditions_and; iso_new_find_conditions_and;
iso_new_find_conditions_atime; iso_new_find_conditions_atime;
@ -155,6 +157,7 @@ iso_node_get_hidden;
iso_node_get_mode; iso_node_get_mode;
iso_node_get_mtime; iso_node_get_mtime;
iso_node_get_name; iso_node_get_name;
iso_node_get_next_xinfo;
iso_node_get_old_image_lba; iso_node_get_old_image_lba;
iso_node_get_parent; iso_node_get_parent;
iso_node_get_permissions; iso_node_get_permissions;
@ -165,6 +168,8 @@ iso_node_get_xinfo;
iso_node_lookup_attr; iso_node_lookup_attr;
iso_node_ref; iso_node_ref;
iso_node_remove; iso_node_remove;
iso_node_remove_all_xinfo;
iso_node_remove_tree;
iso_node_remove_xinfo; iso_node_remove_xinfo;
iso_node_set_acl_text; iso_node_set_acl_text;
iso_node_set_atime; iso_node_set_atime;
@ -179,6 +184,8 @@ iso_node_set_sort_weight;
iso_node_set_uid; iso_node_set_uid;
iso_node_take; iso_node_take;
iso_node_unref; iso_node_unref;
iso_node_xinfo_get_cloner;
iso_node_xinfo_make_clonable;
iso_node_zf_by_magic; iso_node_zf_by_magic;
iso_obtain_msgs; iso_obtain_msgs;
iso_read_image_features_destroy; iso_read_image_features_destroy;
@ -209,6 +216,7 @@ iso_set_local_charset;
iso_set_msgs_severities; iso_set_msgs_severities;
iso_sev_to_text; iso_sev_to_text;
iso_special_get_dev; iso_special_get_dev;
iso_stream_clone;
iso_stream_close; iso_stream_close;
iso_stream_cmp_ino; iso_stream_cmp_ino;
iso_stream_get_external_filter; iso_stream_get_external_filter;
@ -234,6 +242,7 @@ iso_tree_add_new_node;
iso_tree_add_new_special; iso_tree_add_new_special;
iso_tree_add_new_symlink; iso_tree_add_new_symlink;
iso_tree_add_node; iso_tree_add_node;
iso_tree_clone;
iso_tree_get_follow_symlinks; iso_tree_get_follow_symlinks;
iso_tree_get_ignore_hidden; iso_tree_get_ignore_hidden;
iso_tree_get_ignore_special; iso_tree_get_ignore_special;
@ -255,6 +264,7 @@ iso_write_opts_new;
iso_write_opts_set_aaip; iso_write_opts_set_aaip;
iso_write_opts_set_aaip_susp_1_10; iso_write_opts_set_aaip_susp_1_10;
iso_write_opts_set_allow_deep_paths; 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_full_ascii;
iso_write_opts_set_allow_longer_paths; iso_write_opts_set_allow_longer_paths;
iso_write_opts_set_allow_lowercase; 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_max_37_char_filenames;
iso_write_opts_set_ms_block; iso_write_opts_set_ms_block;
iso_write_opts_set_no_force_dots; iso_write_opts_set_no_force_dots;
iso_write_opts_set_old_empty;
iso_write_opts_set_omit_version_numbers; iso_write_opts_set_omit_version_numbers;
iso_write_opts_set_output_charset; iso_write_opts_set_output_charset;
iso_write_opts_set_overwrite_buf; iso_write_opts_set_overwrite_buf;
@ -293,6 +304,7 @@ iso_write_opts_set_scdbackup_tag;
iso_write_opts_set_sort_files; iso_write_opts_set_sort_files;
iso_write_opts_set_system_area; iso_write_opts_set_system_area;
iso_write_opts_set_tail_blocks; iso_write_opts_set_tail_blocks;
iso_write_opts_set_untranslated_name_len;
iso_write_opts_set_will_cancel; iso_write_opts_set_will_cancel;
iso_zisofs_get_params; iso_zisofs_get_params;
iso_zisofs_get_refcounts; iso_zisofs_get_refcounts;

View File

@ -4,7 +4,15 @@
#endif #endif
#include <ctype.h> #include <ctype.h>
#ifdef HAVE_STDINT_H
#include <stdint.h> #include <stdint.h>
#else
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#endif
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>

View File

@ -12,7 +12,14 @@
#include "../config.h" #include "../config.h"
#endif #endif
#ifdef HAVE_STDINT_H
#include <stdint.h> #include <stdint.h>
#else
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#endif
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
@ -417,6 +424,22 @@ int checksum_cx_xinfo_func(void *data, int flag)
return 1; return 1;
} }
/* The iso_node_xinfo_cloner function which gets associated to
* checksum_cx_xinfo_func by iso_init() resp. iso_init_with_flag() via
* iso_node_xinfo_make_clonable()
*/
int checksum_cx_xinfo_cloner(void *old_data, void **new_data, int flag)
{
*new_data = NULL;
if (flag)
return ISO_XINFO_NO_CLONE;
if (old_data == NULL)
return 0;
/* data is an int disguised as pointer. It does not point to memory. */
*new_data = old_data;
return 0;
}
/* Function to identify and manage md5 sums of unspecified providence stored /* Function to identify and manage md5 sums of unspecified providence stored
* directly in this xinfo. * directly in this xinfo.
@ -429,6 +452,24 @@ int checksum_md5_xinfo_func(void *data, int flag)
return 1; return 1;
} }
/* The iso_node_xinfo_cloner function which gets associated to
* checksum_md5_xinfo_func by iso_init() resp. iso_init_with_flag() via
* iso_node_xinfo_make_clonable()
*/
int checksum_md5_xinfo_cloner(void *old_data, void **new_data, int flag)
{
*new_data = NULL;
if (flag)
return ISO_XINFO_NO_CLONE;
if (old_data == NULL)
return 0;
*new_data = calloc(1, 16);
if (*new_data == NULL)
return ISO_OUT_OF_MEM;
memcpy(*new_data, old_data, 16);
return 16;
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */

View File

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 - 2011 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -36,6 +37,7 @@
#include "messages.h" #include "messages.h"
#include "util.h" #include "util.h"
#include "node.h"
/* /*
@ -79,11 +81,76 @@ int abort_threshold = LIBISO_MSGS_SEV_FAILURE;
struct libiso_msgs *libiso_msgr = NULL; struct libiso_msgs *libiso_msgr = NULL;
/* ------------- List of xinfo clone functions ----------- */
struct iso_xinfo_cloner_assoc {
iso_node_xinfo_func proc;
iso_node_xinfo_cloner cloner;
struct iso_xinfo_cloner_assoc *next;
};
struct iso_xinfo_cloner_assoc *iso_xinfo_cloner_list = NULL;
/* API */
int iso_node_xinfo_make_clonable(iso_node_xinfo_func proc,
iso_node_xinfo_cloner cloner, int flag)
{
struct iso_xinfo_cloner_assoc *assoc;
/* Look for existing assoc of proc */
for (assoc = iso_xinfo_cloner_list; assoc != NULL; assoc = assoc->next)
if (assoc->proc == proc)
break;
if (assoc == NULL) {
assoc = calloc(1, sizeof(struct iso_xinfo_cloner_assoc));
if (assoc == NULL)
return ISO_OUT_OF_MEM;
assoc->proc = proc;
assoc->next = iso_xinfo_cloner_list;
iso_xinfo_cloner_list = assoc;
}
assoc->cloner = cloner;
return ISO_SUCCESS;
}
/* API */
int iso_node_xinfo_get_cloner(iso_node_xinfo_func proc,
iso_node_xinfo_cloner *cloner, int flag)
{
struct iso_xinfo_cloner_assoc *assoc;
*cloner = NULL;
for (assoc = iso_xinfo_cloner_list; assoc != NULL; assoc = assoc->next) {
if (assoc->proc != proc)
continue;
*cloner = assoc->cloner;
return 1;
}
return 0;
}
static
int iso_node_xinfo_dispose_cloners(int flag)
{
struct iso_xinfo_cloner_assoc *assoc, *next;
for (assoc = iso_xinfo_cloner_list; assoc != NULL; assoc = next) {
next = assoc->next;
free((char *) assoc);
}
return(1);
}
/* ------------- End of xinfo clone functions list ----------- */
/* /*
@param flag bit0= do not set up locale by LC_* environment variables @param flag bit0= do not set up locale by LC_* environment variables
*/ */
int iso_init_with_flag(int flag) int iso_init_with_flag(int flag)
{ {
int ret;
#ifdef Libisofs_with_libjtE #ifdef Libisofs_with_libjtE
@ -119,7 +186,6 @@ LIBJTE_MISCONFIGURATION_ = 0;
#endif /* Libisofs_with_libjtE */ #endif /* Libisofs_with_libjtE */
if (! (flag & 1)) { if (! (flag & 1)) {
iso_init_locale(0); iso_init_locale(0);
} }
@ -129,10 +195,29 @@ LIBJTE_MISCONFIGURATION_ = 0;
} }
libiso_msgs_set_severities(libiso_msgr, LIBISO_MSGS_SEV_NEVER, libiso_msgs_set_severities(libiso_msgr, LIBISO_MSGS_SEV_NEVER,
LIBISO_MSGS_SEV_FATAL, "libisofs: ", 0); LIBISO_MSGS_SEV_FATAL, "libisofs: ", 0);
ret = iso_node_xinfo_make_clonable(aaip_xinfo_func, aaip_xinfo_cloner, 0);
if (ret < 0)
return ret;
ret = iso_node_xinfo_make_clonable(checksum_cx_xinfo_func,
checksum_cx_xinfo_cloner, 0);
if (ret < 0)
return ret;
ret = iso_node_xinfo_make_clonable(checksum_md5_xinfo_func,
checksum_md5_xinfo_cloner, 0);
if (ret < 0)
return ret;
ret = iso_node_xinfo_make_clonable(zisofs_zf_xinfo_func,
zisofs_zf_xinfo_cloner, 0);
if (ret < 0)
return ret;
ret = iso_node_xinfo_make_clonable(iso_px_ino_xinfo_func,
iso_px_ino_xinfo_cloner, 0);
if (ret < 0)
return ret;
return 1; return 1;
} }
int iso_init() int iso_init()
{ {
return iso_init_with_flag(0); return iso_init_with_flag(0);
@ -141,6 +226,7 @@ int iso_init()
void iso_finish() void iso_finish()
{ {
libiso_msgs_destroy(&libiso_msgr, 0); libiso_msgs_destroy(&libiso_msgr, 0);
iso_node_xinfo_dispose_cloners(0);
} }
int iso_set_abort_severity(char *severity) int iso_set_abort_severity(char *severity)
@ -361,6 +447,12 @@ const char *iso_error_to_msg(int errcode)
return "May not combine appended partition with non-MBR system area"; return "May not combine appended partition with non-MBR system area";
case ISO_DISPLACE_ROLLOVER: case ISO_DISPLACE_ROLLOVER:
return "Displacement offset leads outside 32 bit range"; return "Displacement offset leads outside 32 bit range";
case ISO_NAME_NEEDS_TRANSL:
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";
default: default:
return "Unknown error"; return "Unknown error";
} }

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt * Copyright (c) 2009 - 2011 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -226,6 +226,89 @@ int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data)
return 0; return 0;
} }
/* API */
int iso_node_get_next_xinfo(IsoNode *node, void **handle,
iso_node_xinfo_func *proc, void **data)
{
IsoExtendedInfo *xinfo;
if (node == NULL || handle == NULL || proc == NULL || data == NULL)
return ISO_NULL_POINTER;
*proc = NULL;
*data = NULL;
xinfo = (IsoExtendedInfo *) *handle;
if (xinfo == NULL)
xinfo = node->xinfo;
else
xinfo = xinfo->next;
*handle = xinfo;
if (xinfo == NULL)
return 0;
*proc = xinfo->process;
*data = xinfo->data;
return ISO_SUCCESS;
}
int iso_node_remove_all_xinfo(IsoNode *node, int flag)
{
IsoExtendedInfo *pos, *next;
for (pos = node->xinfo; pos != NULL; pos = next) {
next = pos->next;
pos->process(pos->data, 1);
free((char *) pos);
}
node->xinfo = NULL;
return ISO_SUCCESS;
}
static
int iso_node_revert_xinfo_list(IsoNode *node, int flag)
{
IsoExtendedInfo *pos, *next, *prev = NULL;
for (pos = node->xinfo; pos != NULL; pos = next) {
next = pos->next;
pos->next = prev;
prev = pos;
}
node->xinfo = prev;
return ISO_SUCCESS;
}
int iso_node_clone_xinfo(IsoNode *from_node, IsoNode *to_node, int flag)
{
void *handle = NULL, *data, *new_data;
iso_node_xinfo_func proc;
iso_node_xinfo_cloner cloner;
int ret;
iso_node_remove_all_xinfo(to_node, 0);
while (1) {
ret = iso_node_get_next_xinfo(from_node, &handle, &proc, &data);
if (ret <= 0)
break;
ret = iso_node_xinfo_get_cloner(proc, &cloner, 0);
if (ret == 0)
return ISO_XINFO_NO_CLONE;
if (ret < 0)
return ret;
ret = (*cloner)(data, &new_data, 0);
if (ret < 0)
break;
ret = iso_node_add_xinfo(to_node, proc, new_data);
if (ret < 0)
break;
}
if (ret < 0) {
iso_node_remove_all_xinfo(to_node, 0);
} else {
ret = iso_node_revert_xinfo_list(to_node, 0);
}
return ret;
}
/** /**
* Get the type of an IsoNode. * Get the type of an IsoNode.
*/ */
@ -651,6 +734,9 @@ int iso_node_take(IsoNode *node)
if (dir == NULL) { if (dir == NULL) {
return ISO_NODE_NOT_ADDED_TO_DIR; return ISO_NODE_NOT_ADDED_TO_DIR;
} }
/* >>> Do not take root directory ! (dir == node) ? */;
pos = iso_dir_find_node(dir, node); pos = iso_dir_find_node(dir, node);
if (pos == NULL) { if (pos == NULL) {
/* should never occur */ /* should never occur */
@ -686,6 +772,44 @@ int iso_node_remove(IsoNode *node)
return ret; return ret;
} }
/* API */
int iso_node_remove_tree(IsoNode *node, IsoDirIter *boss_iter)
{
IsoDirIter *iter = NULL;
IsoNode *sub_node;
int ret;
if (node->type != LIBISO_DIR) {
/* >>> Do not remove root directory ! (node->parent == node) ? */;
ret = iso_dir_get_children((IsoDir *) node, &iter);
if (ret < 0)
goto ex;
while(1) {
ret = iso_dir_iter_next(iter, &sub_node);
if (ret == 0)
break;
ret = iso_node_remove_tree(sub_node, iter);
if (ret < 0)
goto ex;
}
if (node->parent == NULL) {
/* node is not grafted into a boss directory */
iso_node_unref(node);
goto ex;
}
}
if (boss_iter != NULL)
ret = iso_dir_iter_remove(boss_iter);
else
ret = iso_node_remove(node);
ex:;
if (iter != NULL)
iso_dir_iter_free(iter);
return ret;
}
/* /*
* Get the parent of the given iso tree node. No extra ref is added to the * Get the parent of the given iso tree node. No extra ref is added to the
* returned directory, you must take your ref. with iso_node_ref() if you * returned directory, you must take your ref. with iso_node_ref() if you
@ -2153,6 +2277,23 @@ int zisofs_zf_xinfo_func(void *data, int flag)
return 1; return 1;
} }
/* The iso_node_xinfo_cloner function which gets associated to
* zisofs_zf_xinfo_func by iso_init() resp. iso_init_with_flag() via
* iso_node_xinfo_make_clonable()
*/
int zisofs_zf_xinfo_cloner(void *old_data, void **new_data, int flag)
{
*new_data = NULL;
if (flag)
return ISO_XINFO_NO_CLONE;
if (old_data == NULL)
return 0;
*new_data = calloc(1, sizeof(struct zisofs_zf_info));
if (*new_data == NULL)
return ISO_OUT_OF_MEM;
memcpy(*new_data, old_data, sizeof(struct zisofs_zf_info));
return (int) sizeof(struct zisofs_zf_info);
}
/* Checks whether a file effectively bears a zisofs file header and eventually /* Checks whether a file effectively bears a zisofs file header and eventually
* marks this by a struct zisofs_zf_info as xinfo of the file node. * marks this by a struct zisofs_zf_info as xinfo of the file node.
@ -2274,6 +2415,21 @@ int iso_px_ino_xinfo_func(void *data, int flag)
return 1; return 1;
} }
/* The iso_node_xinfo_cloner function which gets associated to
* iso_px_ino_xinfo_func by iso_init() resp. iso_init_with_flag() via
* iso_node_xinfo_make_clonable()
*/
int iso_px_ino_xinfo_cloner(void *old_data, void **new_data, int flag)
{
*new_data = NULL;
if (flag)
return ISO_XINFO_NO_CLONE;
*new_data = calloc(1, sizeof(ino_t));
if (*new_data == NULL)
return ISO_OUT_OF_MEM;
memcpy(*new_data, old_data, sizeof(ino_t));
return (int) sizeof(ino_t);
}
/* /*
* @param flag * @param flag
@ -2364,7 +2520,6 @@ int iso_node_set_ino_xinfo(IsoNode *node, ino_t ino, int flag)
return ret; return ret;
} }
int iso_node_set_ino(IsoNode *node, ino_t ino, int flag) int iso_node_set_ino(IsoNode *node, ino_t ino, int flag)
{ {
int ret; int ret;

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt * Copyright (c) 2009 - 2011 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -20,7 +20,15 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#ifdef HAVE_STDINT_H
#include <stdint.h> #include <stdint.h>
#else
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#endif
/** /**
* The extended information is a way to attach additional information to each * The extended information is a way to attach additional information to each
@ -113,6 +121,7 @@ struct Iso_Dir
IsoNode *children; /**< list of children. ptr to first child */ IsoNode *children; /**< list of children. ptr to first child */
}; };
/* IMPORTANT: Any change must be reflected by iso_tree_clone_file. */
struct Iso_File struct Iso_File
{ {
IsoNode node; IsoNode node;
@ -473,4 +482,35 @@ int iso_root_get_isofsca(IsoNode *node, uint32_t *start_lba, uint32_t *end_lba,
int flag); int flag);
/**
* Copy the xinfo list from one node to the another.
*/
int iso_node_clone_xinfo(IsoNode *from_node, IsoNode *to_node, int flag);
/**
* The iso_node_xinfo_func instance which governs the storing of the inode
* number from Rock Ridge field PX.
*/
int iso_px_ino_xinfo_func(void *data, int flag);
/* The iso_node_xinfo_cloner function which gets associated to
* iso_px_ino_xinfo_func by iso_init() resp. iso_init_with_flag() via
* iso_node_xinfo_make_clonable()
*/
int iso_px_ino_xinfo_cloner(void *old_data, void **new_data, int flag);
/* Function to identify and manage ZF parameters of zisofs compression.
* data is supposed to be a pointer to struct zisofs_zf_info
*/
int zisofs_zf_xinfo_func(void *data, int flag);
/* The iso_node_xinfo_cloner function which gets associated to
* zisofs_zf_xinfo_func by iso_init() resp. iso_init_with_flag() via
* iso_node_xinfo_make_clonable()
*/
int zisofs_zf_xinfo_cloner(void *old_data, void **new_data, int flag);
#endif /*LIBISO_NODE_H_*/ #endif /*LIBISO_NODE_H_*/

View File

@ -13,6 +13,9 @@
#include "../config.h" #include "../config.h"
#endif #endif
#include <string.h>
#include <stdio.h>
#include "rockridge.h" #include "rockridge.h"
#include "node.h" #include "node.h"
#include "ecma119_tree.h" #include "ecma119_tree.h"
@ -22,7 +25,12 @@
#include "aaip_0_2.h" #include "aaip_0_2.h"
#include "libisofs.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 static
@ -897,7 +905,7 @@ int add_zf_field(Ecma119Image *t, Ecma119Node *n, struct susp_info *info,
return 1; return 1;
} }
/* API */
int aaip_xinfo_func(void *data, int flag) int aaip_xinfo_func(void *data, int flag)
{ {
if (flag & 1) { if (flag & 1) {
@ -906,6 +914,23 @@ int aaip_xinfo_func(void *data, int flag)
return 1; return 1;
} }
/* API */
int aaip_xinfo_cloner(void *old_data, void **new_data, int flag)
{
size_t aa_size;
*new_data = NULL;
if (old_data == NULL)
return 0;
aa_size = aaip_count_bytes((unsigned char *) old_data, 0);
if (aa_size <= 0)
return ISO_AAIP_BAD_AASTRING;
*new_data = calloc(1, aa_size);
if (*new_data == NULL)
return ISO_OUT_OF_MEM;
memcpy(*new_data, old_data, aa_size);
return (int) aa_size;
}
/** /**
* Compute SUA length and eventual Continuation Area length of field NM and * Compute SUA length and eventual Continuation Area length of field NM and
@ -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 * Compute the length needed for write all RR and SUSP entries for a given
* node. * node.
@ -1104,27 +1167,31 @@ unannounced_ca:;
* @param type * @param type
* 0 normal entry, 1 "." entry for that node (it is a dir), 2 ".." * 0 normal entry, 1 "." entry for that node (it is a dir), 2 ".."
* for that node (i.e., it will refer to the parent) * for that node (i.e., it will refer to the parent)
* @param space * @param used_up
* Available space in the System Use Area for the directory record. * Already occupied space in the directory record.
* @param ce * @param ce
* Will be filled with the space needed in a CE * Will be filled with the space needed in a CE
* @return * @return
* The size needed for the RR entries in the System Use Area * 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 *ce)
{ {
size_t su_size; size_t su_size, space;
int ret; int ret;
size_t aaip_sua_free= 0, aaip_len= 0;
/* Directory record length must be even (ECMA-119, 9.1.13). Maximum is 254.
*/
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; *ce = 0;
su_size = 0; su_size = 0;
/* If AAIP enabled and announced by ER : account for 5 bytes of ES */; /* 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 { } else {
*ce = 182; *ce = 182;
} }
if (t->aaip) { if (t->aaip && !t->aaip_susp_1_10) {
*ce += 160; /* ER of AAIP */ *ce += 160; /* ER of AAIP */
} }
/* Compute length of AAIP string of root node */
aaip_sua_free= 0;
ret = add_aa_string(t, n, NULL, &aaip_sua_free, &aaip_len, 1);
if (ret < 0)
return ret;
*ce += aaip_len;
} }
} }
@ -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 * Fill a struct susp_info with the RR/SUSP entries needed for a given
* node. * node.
@ -1268,8 +1304,8 @@ int add_aa_string(Ecma119Image *t, Ecma119Node *n, struct susp_info *info,
* @param type * @param type
* 0 normal entry, 1 "." entry for that node (it is a dir), 2 ".." * 0 normal entry, 1 "." entry for that node (it is a dir), 2 ".."
* for that node (i.e., it will refer to the parent) * for that node (i.e., it will refer to the parent)
* @param space * @param used_up
* Available space in the System Use Area for the directory record. * Already occupied space in the directory record.
* @param info * @param info
* Pointer to the struct susp_info where the entries will be stored. * 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 * 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 * 1 success, < 0 error
*/ */
int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type, 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; int ret;
size_t i; 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 */ size_t su_size_pd, ce_len_pd; /* predicted sizes of SUA and CA */
int ce_is_predicted = 0; int ce_is_predicted = 0;
size_t aaip_sua_free= 0, aaip_len= 0; size_t aaip_sua_free= 0, aaip_len= 0;
size_t space;
if (t == NULL || n == NULL || info == NULL) { if (t == NULL || n == NULL || info == NULL) {
return ISO_NULL_POINTER; return ISO_NULL_POINTER;
} }
if (type < 0 || type > 2 || space < 185) {
/* space min is 255 - 33 - 37 = 185 */ /* Directory record length must be even (ECMA-119, 9.1.13). Maximum is 254.
return ISO_WRONG_ARG_VALUE; */
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) { if (type == 2 && n->parent != NULL) {
@ -1306,13 +1349,6 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
node = n; 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 * SP must be the first entry for the "." record of the root directory
* (SUSP, 5.3) * (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) { if (type == 0) {
size_t sua_free; /* free space in the SUA */ size_t sua_free; /* free space in the SUA */
int nm_type = 0; /* 0 whole entry in SUA, 1 part in CE */ 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 */ /* Compute length of AAIP string of root node */
aaip_sua_free= 0; aaip_sua_free= 0;
ret = add_aa_string(t, n, info, &aaip_sua_free, &aaip_len, 1); ret = add_aa_string(t, n, NULL, &aaip_sua_free, &aaip_len, 1);
if (ret < 0) if (ret < 0)
goto add_susp_cleanup; goto add_susp_cleanup;

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, int read_aaip_AA(struct susp_sys_user_entry *sue,
unsigned char **aa_string, size_t *aa_size, size_t *aa_len, unsigned char **aa_string, size_t *aa_size, size_t *aa_len,
@ -514,7 +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, int read_aaip_AL(struct susp_sys_user_entry *sue,
unsigned char **aa_string, size_t *aa_size, size_t *aa_len, unsigned char **aa_string, size_t *aa_size, size_t *aa_len,

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt * Copyright (c) 2009 - 2011 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -157,8 +157,64 @@ int fsrc_update_size(IsoStream *stream)
return ISO_SUCCESS; return ISO_SUCCESS;
} }
static
IsoStream *fsrc_get_input_stream(IsoStream *stream, int flag)
{
return NULL;
}
static
int fsrc_cmp_ino(IsoStream *s1, IsoStream *s2)
{
int ret;
ret = iso_stream_cmp_ino(s1, s2, 1);
return ret;
}
int fsrc_clone_stream(IsoStream *old_stream, IsoStream **new_stream,
int flag)
{
FSrcStreamData *data, *new_data;
IsoStream *stream;
int ret;
if (flag)
return ISO_STREAM_NO_CLONE; /* unknown option required */
data = (FSrcStreamData*) old_stream->data;
if (data->src->class->version < 2)
return ISO_STREAM_NO_CLONE; /* No clone_src() method available */
*new_stream = NULL;
stream = calloc(1, sizeof(IsoStream));
if (stream == NULL)
return ISO_OUT_OF_MEM;
new_data = calloc(1, sizeof(FSrcStreamData));
if (new_data == NULL) {
free((char *) stream);
return ISO_OUT_OF_MEM;
}
*new_stream = stream;
stream->class = old_stream->class;
stream->refcount = 1;
stream->data = new_data;
ret = data->src->class->clone_src(data->src, &(new_data->src), 0);
if (ret < 0) {
free((char *) stream);
free((char *) new_data);
return ret;
}
new_data->dev_id = data->dev_id;
new_data->ino_id = data->ino_id;
new_data->size = data->size;
return ISO_SUCCESS;
}
IsoStreamIface fsrc_stream_class = { IsoStreamIface fsrc_stream_class = {
1, /* update_size is defined for this stream */ 4, /* version */
"fsrc", "fsrc",
fsrc_open, fsrc_open,
fsrc_close, fsrc_close,
@ -167,7 +223,10 @@ IsoStreamIface fsrc_stream_class = {
fsrc_is_repeatable, fsrc_is_repeatable,
fsrc_get_id, fsrc_get_id,
fsrc_free, fsrc_free,
fsrc_update_size fsrc_update_size,
fsrc_get_input_stream,
fsrc_cmp_ino,
fsrc_clone_stream
}; };
int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream) int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream)
@ -375,11 +434,76 @@ void cut_out_free(IsoStream *stream)
free(data); free(data);
} }
static
int cut_out_update_size(IsoStream *stream)
{
return ISO_SUCCESS;
}
static
IsoStream* cut_out_get_input_stream(IsoStream *stream, int flag)
{
return NULL;
}
static
int cut_out_cmp_ino(IsoStream *s1, IsoStream *s2)
{
int ret;
ret = iso_stream_cmp_ino(s1, s2, 1);
return ret;
}
static
int cut_out_clone_stream(IsoStream *old_stream, IsoStream **new_stream,
int flag)
{
struct cut_out_stream *data, *new_data;
IsoStream *stream;
int ret;
if (flag)
return ISO_STREAM_NO_CLONE; /* unknown option required */
data = (struct cut_out_stream *) old_stream->data;
if (data->src->class->version < 2)
return ISO_STREAM_NO_CLONE; /* No clone_src() method available */
*new_stream = NULL;
stream = calloc(1, sizeof(IsoStream));
if (stream == NULL)
return ISO_OUT_OF_MEM;
stream->refcount = 1;
stream->class = old_stream->class;
new_data = calloc(1, sizeof(struct cut_out_stream));
if (new_data == NULL) {
free((char *) stream);
return ISO_OUT_OF_MEM;
}
ret = data->src->class->clone_src(data->src, &(new_data->src), 0);
if (ret < 0) {
free((char *) stream);
free((char *) new_data);
return ret;
}
new_data->dev_id = (dev_t) 0;
new_data->ino_id = cut_out_serial_id++;
new_data->offset = data->offset;
new_data->size = data->size;
new_data->pos = 0;
stream->data = new_data;
*new_stream = stream;
return ISO_SUCCESS;
}
/* /*
* TODO update cut out streams to deal with update_size(). Seems hard. * TODO update cut out streams to deal with update_size(). Seems hard.
*/ */
IsoStreamIface cut_out_stream_class = { IsoStreamIface cut_out_stream_class = {
0, 4, /* version */
"cout", "cout",
cut_out_open, cut_out_open,
cut_out_close, cut_out_close,
@ -387,7 +511,12 @@ IsoStreamIface cut_out_stream_class = {
cut_out_read, cut_out_read,
cut_out_is_repeatable, cut_out_is_repeatable,
cut_out_get_id, cut_out_get_id,
cut_out_free cut_out_free,
cut_out_update_size,
cut_out_get_input_stream,
cut_out_cmp_ino,
cut_out_clone_stream
}; };
int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size, int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
@ -549,12 +678,77 @@ void mem_free(IsoStream *stream)
{ {
MemStreamData *data; MemStreamData *data;
data = (MemStreamData*)stream->data; data = (MemStreamData*)stream->data;
free(data->buf); if (data->buf != NULL)
free(data->buf);
free(data); free(data);
} }
static
int mem_update_size(IsoStream *stream)
{
return ISO_SUCCESS;
}
static
IsoStream* mem_get_input_stream(IsoStream *stream, int flag)
{
return NULL;
}
static
int mem_cmp_ino(IsoStream *s1, IsoStream *s2)
{
int ret;
ret = iso_stream_cmp_ino(s1, s2, 1);
return ret;
}
static
int mem_clone_stream(IsoStream *old_stream, IsoStream **new_stream,
int flag)
{
MemStreamData *data, *new_data;
IsoStream *stream;
uint8_t *new_buf = NULL;
if (flag)
return ISO_STREAM_NO_CLONE; /* unknown option required */
*new_stream = NULL;
stream = calloc(1, sizeof(IsoStream));
if (stream == NULL)
return ISO_OUT_OF_MEM;
stream->refcount = 1;
stream->class = old_stream->class;
new_data = calloc(1, sizeof(MemStreamData));
if (new_data == NULL) {
free((char *) stream);
return ISO_OUT_OF_MEM;
}
data = (MemStreamData *) old_stream->data;
if (data->size > 0) {
new_buf = calloc(1, data->size);
if (new_buf == NULL) {
free((char *) stream);
free((char *) new_data);
return ISO_OUT_OF_MEM;
}
memcpy(new_buf, data->buf, data->size);
}
new_data->buf = new_buf;
new_data->offset = -1;
new_data->ino_id = mem_serial_id++;
new_data->size = data->size;
stream->data = new_data;
*new_stream = stream;
return ISO_SUCCESS;
}
IsoStreamIface mem_stream_class = { IsoStreamIface mem_stream_class = {
0, 4, /* version */
"mem ", "mem ",
mem_open, mem_open,
mem_close, mem_close,
@ -562,7 +756,12 @@ IsoStreamIface mem_stream_class = {
mem_read, mem_read,
mem_is_repeatable, mem_is_repeatable,
mem_get_id, mem_get_id,
mem_free mem_free,
mem_update_size,
mem_get_input_stream,
mem_cmp_ino,
mem_clone_stream
}; };
/** /**
@ -924,3 +1123,42 @@ ex:;
iso_md5_end(&ctx, md5); iso_md5_end(&ctx, md5);
return res; 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) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt * Copyright (c) 2009 - 2011 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -15,6 +15,7 @@
*/ */
#include "fsource.h" #include "fsource.h"
/* IMPORTANT: Any change must be reflected by fsrc_clone_stream */
typedef struct typedef struct
{ {
IsoFileSource *src; IsoFileSource *src;
@ -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, int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
IsoStream **stream); 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 * Obtain eventual zisofs ZF field entry parameters from a file source out
* of a loaded ISO image. * 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); int iso_stream_make_md5(IsoStream *stream, char md5[16], int flag);
/**
* Create a clone of the input stream of old_stream and a roughly initialized
* clone of old_stream which has the same class and refcount 1. Its data
* pointer will be NULL and needs to be filled by an expert which knows how
* to clone the data of old_stream.
* @param old_stream The existing stream which is in process of cloning
* @param new_stream Will return the uninitialized memory object which shall
* later become the clone of old_stream.
* @param new_input The clone of the input stream of old stream.
* @param flag Submit 0 for now.
* @return ISO_SUCCESS or an error code <0
*/
int iso_stream_clone_filter_common(IsoStream *old_stream,
IsoStream **new_stream,
IsoStream **new_input, int flag);
#endif /*STREAM_H_*/ #endif /*STREAM_H_*/

View File

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2011 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -993,3 +994,194 @@ char *iso_tree_get_node_path(IsoNode *node)
return strdup(path); 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 Vreixo Formoso
* Copyright (c) 2007 Mario Danic * 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 * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -773,6 +773,8 @@ char *iso_r_dirid(const char *src, int size, int relaxed)
len = size; len = size;
} }
dest = malloc(len + 1); dest = malloc(len + 1);
if (dest == NULL)
return NULL;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
char c= src[i]; char c= src[i];
if (relaxed == 2) { if (relaxed == 2) {
@ -1036,6 +1038,8 @@ uint16_t *ucsdup(const uint16_t *str)
size_t len = ucslen(str); size_t len = ucslen(str);
ret = malloc(2 * (len + 1)); ret = malloc(2 * (len + 1));
if (ret == NULL)
return NULL;
if (ret != NULL) { if (ret != NULL) {
memcpy(ret, str, 2 * (len + 1)); 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 #ifndef HAVE_TIMEGM
/* putenv is SVr4, POSIX.1-2001, 4.3BSD , setenv is 4.3BSD, POSIX.1-2001.
So putenv is more widely available.
Also, setenv spoils eventual putenv expectation of applications because
putenv installs the original string which then may be altered from
its owner. setenv installs a copy that may not be altered.
Both are slow.
Thus first try with a naive implementation that assumes no leap seconds.
If it fails a test with gmtime() then use the slow function with mktime().
*/
#define Libisofs_use_putenV yes
static static
time_t timegm(struct tm *tm) time_t env_timegm(struct tm *tm)
{ {
time_t ret; time_t ret;
char *tz; char *tz;
#ifdef Libisofs_use_putenV
static char unset_name[] = {"TZ"};
tz = getenv("TZ");
putenv("TZ=");
tzset();
ret = mktime(tm);
if (tz != NULL) {
/* tz is a pointer to the value part in a string of form "TZ="value */
putenv(tz - 3);
} else
putenv(unset_name); /* not daring to submit constant */
tzset();
#else /* Libisofs_use_putenV */
tz = getenv("TZ"); tz = getenv("TZ");
setenv("TZ", "", 1); setenv("TZ", "", 1);
tzset(); tzset();
@ -1309,9 +1342,92 @@ time_t timegm(struct tm *tm)
else else
unsetenv("TZ"); unsetenv("TZ");
tzset(); tzset();
#endif /* ! Libisofs_use_putenV */
return ret; return ret;
} }
#endif
static
int ts_is_leapyear(int tm_year) /* years since 1900 */
{
return ((tm_year % 4) == 0 && ((tm_year % 100) != 0 ||
(tm_year % 400) == 100));
}
/* Fast implementation without leap seconds.
Inspired by but not copied from code by Kungliga Tekniska Hgskolan
(Royal Institute of Technology, Stockholm, Sweden),
which was modified by Andrew Tridgell for Samba4.
I claim own copyright 2011 Thomas Schmitt <scdbackup@gmx.net>.
*/
static
time_t ts_timegm(struct tm *tm)
{
time_t ret;
static int month_length_normal[12] =
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static int month_length_leap[12] =
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int *month_length_pt;
int years, i;
ret = 0;
years = tm->tm_year - 70; /* Years since 1970 */
if (years < 0)
return ret;
for (i = 0; i < years; i++) {
ret += 365 * 86400;
if (ts_is_leapyear(70 + i))
ret += 86400;
}
if (ts_is_leapyear(tm->tm_year))
month_length_pt = month_length_leap;
else
month_length_pt = month_length_normal;
for (i = 0; i < tm->tm_mon; i++)
ret += month_length_pt[i] * 86400;
ret += (tm->tm_mday - 1) * 86400;
ret += tm->tm_hour * 3600;
ret += tm->tm_min * 60;
ret += tm->tm_sec;
return ret;
}
static
time_t timegm(struct tm *tm)
{
time_t raw_t, ret;
struct tm *test_tm, input_tm_copy;
/* Beware of ill effects if tm is result of gmtime() or alike */
memcpy(&input_tm_copy, tm, sizeof(struct tm));
/* Try without leapseconds (which are rarely implemented, as it seems) */
raw_t = ts_timegm(tm);
if (raw_t == 0)
return raw_t;
/* Check whether this translates back to the input values */
test_tm = gmtime(&raw_t);
if (input_tm_copy.tm_sec == test_tm->tm_sec &&
input_tm_copy.tm_min == test_tm->tm_min &&
input_tm_copy.tm_hour == test_tm->tm_hour &&
input_tm_copy.tm_mday == test_tm->tm_mday &&
input_tm_copy.tm_mon == test_tm->tm_mon &&
input_tm_copy.tm_year == test_tm->tm_year) {
ret = raw_t;
} else {
/* Mismatch. Use slow method around mktime() */
ret = env_timegm(&input_tm_copy);
}
return ret;
}
#endif /* ! HAVE_TIMEGM */
time_t iso_datetime_read_7(const uint8_t *buf) time_t iso_datetime_read_7(const uint8_t *buf)
{ {
@ -1323,6 +1439,7 @@ time_t iso_datetime_read_7(const uint8_t *buf)
tm.tm_hour = buf[3]; tm.tm_hour = buf[3];
tm.tm_min = buf[4]; tm.tm_min = buf[4];
tm.tm_sec = buf[5]; tm.tm_sec = buf[5];
return timegm(&tm) - ((int8_t)buf[6]) * 60 * 15; return timegm(&tm) - ((int8_t)buf[6]) * 60 * 15;
} }
@ -1460,6 +1577,8 @@ char *ucs2str(const char *buf, size_t len)
/* ensure enought space */ /* ensure enought space */
out = calloc(outbytes, 1); out = calloc(outbytes, 1);
if (out == NULL)
return NULL;
/* convert to local charset */ /* convert to local charset */
conv_ret = iso_iconv_open(&conv, iso_get_local_charset(0), "UCS-2BE", 0); conv_ret = iso_iconv_open(&conv, iso_get_local_charset(0), "UCS-2BE", 0);

View File

@ -11,7 +11,14 @@
#ifndef LIBISO_UTIL_H_ #ifndef LIBISO_UTIL_H_
#define LIBISO_UTIL_H_ #define LIBISO_UTIL_H_
#ifdef HAVE_STDINT_H
#include <stdint.h> #include <stdint.h>
#else
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#endif
#include <time.h> #include <time.h>
#ifndef MAX #ifndef MAX
@ -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); int checksum_cx_xinfo_func(void *data, int flag);
/* The iso_node_xinfo_cloner function which gets associated to
* checksum_cx_xinfo_func by iso_init() resp. iso_init_with_flag() via
* iso_node_xinfo_make_clonable()
*/
int checksum_cx_xinfo_cloner(void *old_data, void **new_data, int flag);
/* Function to identify and manage md5 sums of unspecified providence stored /* Function to identify and manage md5 sums of unspecified providence stored
* directly in this xinfo. This is supposed to override any other recorded * directly in this xinfo. This is supposed to override any other recorded
* MD5 of the node unless data get copied and checksummed during that copying. * MD5 of the node unless data get copied and checksummed during that copying.
*/ */
int checksum_md5_xinfo_func(void *data, int flag); int checksum_md5_xinfo_func(void *data, int flag);
/* The iso_node_xinfo_cloner function which gets associated to
* checksum_md5_xinfo_func by iso_init() resp. iso_init_with_flag() via
* iso_node_xinfo_make_clonable()
*/
int checksum_md5_xinfo_cloner(void *old_data, void **new_data, int flag);
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */