Compare commits
29 Commits
release-0.
...
release-0.
Author | SHA1 | Date | |
---|---|---|---|
1d44d931d0 | |||
5d5a0cbfd4 | |||
4353a35c59 | |||
2f48297d25 | |||
dfcb815480 | |||
f370829717 | |||
ef96f3588c | |||
e8fc149423 | |||
e12d409b80 | |||
b34fd35e62 | |||
714ee67472 | |||
8c4682ae92 | |||
5b073a2f29 | |||
c6f1101e9d | |||
f8d3bca20a | |||
46a947b602 | |||
56796ff55f | |||
1cbae01f12 | |||
da4634a593 | |||
f18d5157dc | |||
1195614881 | |||
1218e6e32d | |||
95381ce258 | |||
19fd87ef7b | |||
d20da80767 | |||
5009d1038d | |||
1ae2a39d1d | |||
70af4872c9 | |||
71d491ed37 |
44
Makefile.am
44
Makefile.am
@ -156,27 +156,31 @@ demo_isoms_SOURCES = demo/iso_ms.c
|
||||
# demo_isogrow_SOURCES = demo/iso_grow.c
|
||||
|
||||
|
||||
## Build unit test
|
||||
## ts A90428 , ticket 147, The test code does not use the API and is totally
|
||||
## outdated in its creation of mocked objects.
|
||||
## A volunteer is needed to rewrite it using the API.
|
||||
|
||||
# ## Build unit test
|
||||
|
||||
check_PROGRAMS = \
|
||||
test/test
|
||||
|
||||
test_test_CPPFLAGS = -Ilibisofs
|
||||
test_test_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
$(libisofs_libisofs_la_LIBADD) -lcunit
|
||||
test_test_LDFLAGS = -L.. -lm
|
||||
|
||||
test_test_SOURCES = \
|
||||
test/test.h \
|
||||
test/test.c \
|
||||
test/test_node.c \
|
||||
test/test_image.c \
|
||||
test/test_tree.c \
|
||||
test/test_util.c \
|
||||
test/test_rockridge.c \
|
||||
test/test_stream.c \
|
||||
test/mocked_fsrc.h \
|
||||
test/mocked_fsrc.c
|
||||
# check_PROGRAMS = \
|
||||
# test/test
|
||||
#
|
||||
# test_test_CPPFLAGS = -Ilibisofs
|
||||
# test_test_LDADD = $(libisofs_libisofs_la_OBJECTS) \
|
||||
# $(libisofs_libisofs_la_LIBADD) -lcunit
|
||||
# test_test_LDFLAGS = -L.. -lm
|
||||
#
|
||||
# test_test_SOURCES = \
|
||||
# test/test.h \
|
||||
# test/test.c \
|
||||
# test/test_node.c \
|
||||
# test/test_image.c \
|
||||
# test/test_tree.c \
|
||||
# test/test_util.c \
|
||||
# test/test_rockridge.c \
|
||||
# test/test_stream.c \
|
||||
# test/mocked_fsrc.h \
|
||||
# test/mocked_fsrc.c
|
||||
|
||||
## ========================================================================= ##
|
||||
|
||||
|
12
configure.ac
12
configure.ac
@ -1,4 +1,4 @@
|
||||
AC_INIT([libisofs], [0.6.18], [http://libburnia-project.org])
|
||||
AC_INIT([libisofs], [0.6.20], [http://libburnia-project.org])
|
||||
AC_PREREQ([2.50])
|
||||
dnl AC_CONFIG_HEADER([config.h])
|
||||
|
||||
@ -44,7 +44,7 @@ dnl If LIBISOFS_*_VERSION changes, be sure to change AC_INIT above to match.
|
||||
dnl
|
||||
LIBISOFS_MAJOR_VERSION=0
|
||||
LIBISOFS_MINOR_VERSION=6
|
||||
LIBISOFS_MICRO_VERSION=18
|
||||
LIBISOFS_MICRO_VERSION=20
|
||||
LIBISOFS_VERSION=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION.$LIBISOFS_MICRO_VERSION
|
||||
|
||||
AC_SUBST(LIBISOFS_MAJOR_VERSION)
|
||||
@ -54,11 +54,11 @@ AC_SUBST(LIBISOFS_VERSION)
|
||||
|
||||
dnl Libtool versioning
|
||||
LT_RELEASE=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION
|
||||
# 2009.04.15: development jump has not yet happened
|
||||
# SONAME = 20 - 14 = 6 . Library name = libisofs.6.14.0
|
||||
LT_CURRENT=20
|
||||
# 2009.05.30 development jump has not yet happened
|
||||
# SONAME = 22 - 16 = 6 . Library name = libisofs.6.16.0
|
||||
LT_CURRENT=22
|
||||
LT_REVISION=0
|
||||
LT_AGE=14
|
||||
LT_AGE=16
|
||||
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
|
||||
|
||||
AC_SUBST(LT_RELEASE)
|
||||
|
@ -128,13 +128,7 @@ size_t aaip_encode(size_t num_attrs, char **names,
|
||||
/* write the field headers */
|
||||
for(i= 0; i < number_of_fields; i++) {
|
||||
(*result)[i * 255 + 0]= 'A';
|
||||
|
||||
#ifdef Libisofs_aaip_2_0
|
||||
(*result)[i * 255 + 1]= 'L';
|
||||
#else /* Libisofs_aaip_2_0 */
|
||||
(*result)[i * 255 + 1]= 'A';
|
||||
#endif /* ! Libisofs_aaip_2_0 */
|
||||
|
||||
if(i < number_of_fields - 1 || (mem_size % 255) == 0)
|
||||
(*result)[i * 255 + 2]= 255;
|
||||
else
|
||||
@ -1186,16 +1180,9 @@ static int aaip_consume_aa_head(struct aaip_state *aaip,
|
||||
aaip->aa_head_missing-= todo;
|
||||
if(aaip->aa_head_missing == 0) {
|
||||
aaip_read_from_recs(aaip, aaip->recs_fill - 5, aa_head, 5, 0);
|
||||
|
||||
#ifdef Libisofs_aaip_2_0
|
||||
if(aa_head[0] != 'A' || (aa_head[1] != 'L' && aa_head[1] != 'A') ||
|
||||
aa_head[3] != 1)
|
||||
return(-1);
|
||||
#else /* Libisofs_aaip_2_0 */
|
||||
if(aa_head[0] != 'A' || aa_head[1] != 'A' || aa_head[3] != 1)
|
||||
return(-1);
|
||||
#endif /* ! Libisofs_aaip_2_0 */
|
||||
|
||||
aaip->aa_missing= aa_head[2];
|
||||
aaip->aa_ends= !(aa_head[4] & 1);
|
||||
aaip->recs_fill-= 5; /* AAIP field heads do not get delivered */
|
||||
|
@ -92,6 +92,7 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
int ret;
|
||||
struct stat info;
|
||||
IsoNode *new;
|
||||
IsoFilesystem *fs;
|
||||
char *name;
|
||||
unsigned char *aa_string;
|
||||
char *a_text = NULL, *d_text = NULL;
|
||||
@ -111,6 +112,7 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
}
|
||||
|
||||
name = iso_file_source_get_name(src);
|
||||
fs = iso_file_source_get_filesystem(src);
|
||||
new = NULL;
|
||||
|
||||
switch (info.st_mode & S_IFMT) {
|
||||
@ -154,6 +156,13 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
}
|
||||
ret = iso_node_new_symlink(name, strdup(dest), &link);
|
||||
new = (IsoNode*) link;
|
||||
if (fs != NULL) {
|
||||
link->fs_id = fs->get_id(fs);
|
||||
if (link->fs_id != 0) {
|
||||
link->st_ino = info.st_ino;
|
||||
link->st_dev = info.st_dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case S_IFSOCK:
|
||||
@ -166,6 +175,13 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
ret = iso_node_new_special(name, info.st_mode, info.st_rdev,
|
||||
&special);
|
||||
new = (IsoNode*) special;
|
||||
if (fs != NULL) {
|
||||
special->fs_id = fs->get_id(fs);
|
||||
if (special->fs_id != 0) {
|
||||
special->st_ino = info.st_ino;
|
||||
special->st_dev = info.st_dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -887,9 +887,14 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
||||
target->rockridge = opts->rockridge;
|
||||
target->joliet = opts->joliet;
|
||||
target->iso1999 = opts->iso1999;
|
||||
target->hardlinks = opts->hardlinks;
|
||||
target->aaip = opts->aaip;
|
||||
target->always_gmt = opts->always_gmt;
|
||||
|
||||
#ifndef Libisofs_hardlink_matcheR
|
||||
target->ino = 0;
|
||||
#endif
|
||||
|
||||
target->omit_version_numbers = opts->omit_version_numbers
|
||||
| opts->max_37_char_filenames;
|
||||
target->allow_deep_paths = opts->allow_deep_paths;
|
||||
@ -901,6 +906,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
||||
target->relaxed_vol_atts = opts->relaxed_vol_atts;
|
||||
target->joliet_longer_paths = opts->joliet_longer_paths;
|
||||
target->rrip_version_1_10 = opts->rrip_version_1_10;
|
||||
target->rrip_1_10_px_ino = opts->rrip_1_10_px_ino;
|
||||
target->aaip_susp_1_10 = opts->aaip_susp_1_10;
|
||||
target->dir_rec_mtime = opts->dir_rec_mtime;
|
||||
target->sort_files = opts->sort_files;
|
||||
@ -927,16 +933,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
||||
target->eltorito = (src->bootcat == NULL ? 0 : 1);
|
||||
target->catalog = src->bootcat;
|
||||
|
||||
#ifndef Libisofs_setlocale_in_iniT
|
||||
/* default to locale charset */
|
||||
/* ??? ts Nov 25 2008 :
|
||||
Shouldn't this go to library initialization or even to app ?
|
||||
*/
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
|
||||
target->input_charset = strdup(iso_get_local_charset(0));
|
||||
|
||||
if (target->input_charset == NULL) {
|
||||
iso_image_unref(src);
|
||||
free(target);
|
||||
@ -1427,6 +1424,15 @@ int iso_write_opts_set_iso1999(IsoWriteOpts *opts, int enable)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_write_opts_set_hardlinks(IsoWriteOpts *opts, int enable)
|
||||
{
|
||||
if (opts == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
opts->hardlinks = enable ? 1 : 0;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_write_opts_set_aaip(IsoWriteOpts *opts, int enable)
|
||||
{
|
||||
if (opts == NULL) {
|
||||
@ -1526,6 +1532,15 @@ int iso_write_opts_set_rrip_version_1_10(IsoWriteOpts *opts, int oldvers)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_write_opts_set_rrip_1_10_px_ino(IsoWriteOpts *opts, int enable)
|
||||
{
|
||||
if (opts == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
opts->rrip_1_10_px_ino = enable ? 1 : 0;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_write_opts_set_aaip_susp_1_10(IsoWriteOpts *opts, int oldvers)
|
||||
{
|
||||
if (opts == NULL) {
|
||||
|
@ -115,6 +115,16 @@ struct iso_write_opts {
|
||||
*/
|
||||
unsigned int rrip_version_1_10 :1;
|
||||
|
||||
/**
|
||||
* Write field PX with file serial number even with RRIP-1.10
|
||||
*/
|
||||
unsigned int rrip_1_10_px_ino :1;
|
||||
|
||||
/**
|
||||
* See iso_write_opts_set_hardlinks()
|
||||
*/
|
||||
unsigned int hardlinks:1;
|
||||
|
||||
/**
|
||||
* Write AAIP as extension according to SUSP 1.10 rather than SUSP 1.12.
|
||||
* I.e. without announcing it by an ER field and thus without the need
|
||||
@ -269,7 +279,9 @@ struct ecma119_image
|
||||
unsigned int eltorito :1;
|
||||
unsigned int iso1999 :1;
|
||||
|
||||
unsigned int aaip :1; /* whether to write eventual ACLs and EAs */
|
||||
unsigned int hardlinks:1; /* see iso_write_opts_set_hardlinks() */
|
||||
|
||||
unsigned int aaip :1; /* see iso_write_opts_set_aaip() */
|
||||
|
||||
/* allways write timestamps in GMT */
|
||||
unsigned int always_gmt :1;
|
||||
@ -291,6 +303,9 @@ struct ecma119_image
|
||||
/** Write old fashioned RRIP-1.10 rather than RRIP-1.12 */
|
||||
unsigned int rrip_version_1_10 :1;
|
||||
|
||||
/** Write field PX with file serial number even with RRIP-1.10 */
|
||||
unsigned int rrip_1_10_px_ino :1;
|
||||
|
||||
/* Write AAIP as extension according to SUSP 1.10 rather than SUSP 1.12. */
|
||||
unsigned int aaip_susp_1_10 :1;
|
||||
|
||||
@ -318,12 +333,18 @@ struct ecma119_image
|
||||
*/
|
||||
int sort_files;
|
||||
|
||||
|
||||
#ifndef Libisofs_hardlink_matcheR
|
||||
|
||||
/* ts A90508 : <<< this is on its way out */
|
||||
/**
|
||||
* In the CD, each file must have an unique inode number. So each
|
||||
* time we add a new file, this is incremented.
|
||||
*/
|
||||
ino_t ino;
|
||||
|
||||
#endif /* ! Libisofs_hardlink_matcheR */
|
||||
|
||||
char *input_charset;
|
||||
char *output_charset;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
@ -106,10 +107,38 @@ int create_ecma119_node(Ecma119Image *img, IsoNode *iso, Ecma119Node **node)
|
||||
ecma->node = iso;
|
||||
iso_node_ref(iso);
|
||||
|
||||
/* TODO #00009 : add true support for harlinks and inode numbers */
|
||||
ecma->nlink = 1;
|
||||
|
||||
#ifndef Libisofs_hardlink_matcheR
|
||||
|
||||
/* ts A90503 : This is obsolete with Libisofs_hardlink_matcheR
|
||||
which will later hand out image inode numbers for all. */
|
||||
|
||||
#ifdef Libisofs_hardlink_prooF
|
||||
|
||||
/* Looking only for valid ISO image inode numbers. */
|
||||
{
|
||||
unsigned int fs_id;
|
||||
dev_t dev_id;
|
||||
int ret;
|
||||
|
||||
ret = iso_node_get_id(iso, &fs_id, &dev_id, &(ecma->ino), 1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
} else if (ret == 0) {
|
||||
/* What has not got a valid ISO image inode yet, gets it now. */
|
||||
ecma->ino = img_give_ino_number(img->image, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* Libisofs_hardlink_prooF */
|
||||
|
||||
/* TODO #00009 : add true support for harlinks and inode numbers */
|
||||
ecma->ino = ++img->ino;
|
||||
|
||||
#endif /* ! Libisofs_hardlink_prooF */
|
||||
#endif /* ! Libisofs_hardlink_matcheR */
|
||||
|
||||
*node = ecma;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
@ -811,6 +840,174 @@ int reorder_tree(Ecma119Image *img, Ecma119Node *dir, int level, int pathlen)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* @param flag
|
||||
* bit0= recursion
|
||||
* bit1= count nodes rather than fill them into *nodes
|
||||
* @return
|
||||
* <0 error
|
||||
* bit0= saw ino == 0
|
||||
* bit1= saw ino != 0
|
||||
*/
|
||||
static
|
||||
int make_node_array(Ecma119Image *img, Ecma119Node *dir,
|
||||
Ecma119Node **nodes, size_t nodes_size, size_t *node_count,
|
||||
int flag)
|
||||
{
|
||||
int ret, result = 0;
|
||||
size_t i;
|
||||
Ecma119Node *child;
|
||||
|
||||
if (!(flag & 1)) {
|
||||
*node_count = 0;
|
||||
if (!(flag & 2)) {
|
||||
/* Register the tree root node */
|
||||
if (*node_count >= nodes_size) {
|
||||
iso_msg_submit(img->image->id, ISO_ASSERT_FAILURE, 0,
|
||||
"Programming error: Overflow of hardlink sort array");
|
||||
return ISO_ASSERT_FAILURE;
|
||||
}
|
||||
nodes[*node_count] = dir;
|
||||
}
|
||||
result|= (dir->ino == 0 ? 1 : 2);
|
||||
(*node_count)++;
|
||||
}
|
||||
|
||||
for (i = 0; i < dir->info.dir->nchildren; i++) {
|
||||
child = dir->info.dir->children[i];
|
||||
if (!(flag & 2)) {
|
||||
if (*node_count >= nodes_size) {
|
||||
iso_msg_submit(img->image->id, ISO_ASSERT_FAILURE, 0,
|
||||
"Programming error: Overflow of hardlink sort array");
|
||||
return ISO_ASSERT_FAILURE;
|
||||
}
|
||||
nodes[*node_count] = child;
|
||||
}
|
||||
result|= (child->ino == 0 ? 1 : 2);
|
||||
(*node_count)++;
|
||||
|
||||
if (child->type == ECMA119_DIR) {
|
||||
ret = make_node_array(img, child,
|
||||
nodes, nodes_size, node_count, flag | 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @param flag
|
||||
* bit0= compare stat properties and attributes
|
||||
* bit1= treat all nodes with image ino == 0 as unique
|
||||
*/
|
||||
static
|
||||
int ecma119_node_cmp_flag(const void *v1, const void *v2, int flag)
|
||||
{
|
||||
int ret;
|
||||
Ecma119Node *n1, *n2;
|
||||
|
||||
n1 = *((Ecma119Node **) v1);
|
||||
n2 = *((Ecma119Node **) v2);
|
||||
if (n1 == n2)
|
||||
return 0;
|
||||
|
||||
ret = iso_node_cmp_flag(n1->node, n2->node, flag & (1 | 2));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int ecma119_node_cmp_hard(const void *v1, const void *v2)
|
||||
{
|
||||
return ecma119_node_cmp_flag(v1, v2, 1);
|
||||
}
|
||||
|
||||
static
|
||||
int ecma119_node_cmp_nohard(const void *v1, const void *v2)
|
||||
{
|
||||
return ecma119_node_cmp_flag(v1, v2, 1 | 2);
|
||||
}
|
||||
|
||||
static
|
||||
int family_set_ino(Ecma119Image *img, Ecma119Node **nodes, size_t family_start,
|
||||
size_t next_family, ino_t img_ino, ino_t prev_ino, int flag)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (img_ino != 0) {
|
||||
/* Check whether this is the same img_ino as in the previous
|
||||
family (e.g. by property divergence of imported hardlink).
|
||||
*/
|
||||
if (img_ino == prev_ino)
|
||||
img_ino = 0;
|
||||
}
|
||||
if (img_ino == 0) {
|
||||
img_ino = img_give_ino_number(img->image, 0);
|
||||
}
|
||||
for (i = family_start; i < next_family; i++) {
|
||||
nodes[i]->ino = img_ino;
|
||||
nodes[i]->nlink = next_family - family_start;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int match_hardlinks(Ecma119Image *img, Ecma119Node *dir, int flag)
|
||||
{
|
||||
int ret;
|
||||
size_t nodes_size = 0, node_count = 0, i, family_start;
|
||||
Ecma119Node **nodes = NULL;
|
||||
unsigned int fs_id;
|
||||
dev_t dev_id;
|
||||
ino_t img_ino = 0, prev_ino = 0;
|
||||
|
||||
ret = make_node_array(img, dir, nodes, nodes_size, &node_count, 2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
nodes_size = node_count;
|
||||
nodes = (Ecma119Node **) calloc(sizeof(Ecma119Node *), nodes_size);
|
||||
if (nodes == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
ret = make_node_array(img, dir, nodes, nodes_size, &node_count, 0);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
|
||||
/* Sort according to id tuples, IsoFileSrc identity, properties, xattr. */
|
||||
if (img->hardlinks)
|
||||
qsort(nodes, node_count, sizeof(Ecma119Node *), ecma119_node_cmp_hard);
|
||||
else
|
||||
qsort(nodes, node_count, sizeof(Ecma119Node *),
|
||||
ecma119_node_cmp_nohard);
|
||||
|
||||
/* Hand out image inode numbers to all Ecma119Node.ino == 0 .
|
||||
Same sorting rank gets same inode number.
|
||||
Split those image inode number families where the sort criterion
|
||||
differs.
|
||||
*/
|
||||
iso_node_get_id(nodes[0]->node, &fs_id, &dev_id, &img_ino, 1);
|
||||
family_start = 0;
|
||||
for (i = 1; i < node_count; i++) {
|
||||
if (ecma119_node_cmp_hard(nodes + (i - 1), nodes + i) == 0) {
|
||||
/* Still in same ino family */
|
||||
if (img_ino == 0) { /* Just in case any member knows its img_ino */
|
||||
iso_node_get_id(nodes[0]->node, &fs_id, &dev_id, &img_ino, 1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
family_set_ino(img, nodes, family_start, i, img_ino, prev_ino, 0);
|
||||
prev_ino = img_ino;
|
||||
iso_node_get_id(nodes[i]->node, &fs_id, &dev_id, &img_ino, 1);
|
||||
family_start = i;
|
||||
}
|
||||
family_set_ino(img, nodes, family_start, i, img_ino, prev_ino, 0);
|
||||
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
if (nodes != NULL)
|
||||
free((char *) nodes);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ecma119_tree_create(Ecma119Image *img)
|
||||
{
|
||||
int ret;
|
||||
@ -826,6 +1023,16 @@ int ecma119_tree_create(Ecma119Image *img)
|
||||
}
|
||||
img->root = root;
|
||||
|
||||
#ifdef Libisofs_hardlink_matcheR
|
||||
|
||||
iso_msg_debug(img->image->id, "Matching hardlinks...");
|
||||
ret = match_hardlinks(img, img->root, 0);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* ! Libisofs_hardlink_matcheR */
|
||||
|
||||
iso_msg_debug(img->image->id, "Sorting the low level tree...");
|
||||
sort_tree(root);
|
||||
|
||||
|
@ -62,8 +62,10 @@ struct ecma119_node
|
||||
|
||||
IsoNode *node; /*< reference to the iso node */
|
||||
|
||||
/* TODO #00009 : add true support for harlinks and inode numbers */
|
||||
/* >>> ts A90501 : Shouldn't this be uint32_t
|
||||
as this is what PX will take ? */
|
||||
ino_t ino;
|
||||
|
||||
nlink_t nlink;
|
||||
|
||||
/**< file, symlink, special, directory or placeholder */
|
||||
|
@ -12,49 +12,28 @@
|
||||
#include "writer.h"
|
||||
#include "messages.h"
|
||||
#include "image.h"
|
||||
#include "stream.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
int iso_file_src_cmp(const void *n1, const void *n2)
|
||||
{
|
||||
int ret;
|
||||
const IsoFileSrc *f1, *f2;
|
||||
unsigned int fs_id1, fs_id2;
|
||||
dev_t dev_id1, dev_id2;
|
||||
ino_t ino_id1, ino_id2;
|
||||
off_t size1, size2;
|
||||
|
||||
if (n1 == n2) {
|
||||
return 0; /* Normally just a shortcut.
|
||||
But important if Libisofs_file_src_cmp_non_zerO */
|
||||
}
|
||||
|
||||
f1 = (const IsoFileSrc *)n1;
|
||||
f2 = (const IsoFileSrc *)n2;
|
||||
|
||||
iso_stream_get_id(f1->stream, &fs_id1, &dev_id1, &ino_id1);
|
||||
iso_stream_get_id(f2->stream, &fs_id2, &dev_id2, &ino_id2);
|
||||
|
||||
if (fs_id1 < fs_id2) {
|
||||
return -1;
|
||||
} else if (fs_id1 > fs_id2) {
|
||||
return 1;
|
||||
} else {
|
||||
/* files belong to the same fs */
|
||||
if (dev_id1 > dev_id2) {
|
||||
return -1;
|
||||
} else if (dev_id1 < dev_id2) {
|
||||
return 1;
|
||||
} else if (ino_id1 < ino_id2) {
|
||||
return -1;
|
||||
} else if (ino_id1 > ino_id2) {
|
||||
return 1;
|
||||
} else {
|
||||
size1 = iso_stream_get_size(f1->stream);
|
||||
size2 = iso_stream_get_size(f2->stream);
|
||||
if (size1 < size2) {
|
||||
return -1;
|
||||
} else if (size1 > size2) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ret = iso_stream_cmp_ino(f1->stream, f2->stream, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
|
||||
|
@ -594,8 +594,13 @@ IsoStream *extf_get_input_stream(IsoStream *stream, int flag)
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int extf_cmp_ino(IsoStream *s1, IsoStream *s2);
|
||||
/* Function is defined after definition of extf_stream_class */
|
||||
|
||||
|
||||
IsoStreamIface extf_stream_class = {
|
||||
2,
|
||||
3,
|
||||
"extf",
|
||||
extf_stream_open,
|
||||
extf_stream_close,
|
||||
@ -605,10 +610,28 @@ IsoStreamIface extf_stream_class = {
|
||||
extf_stream_get_id,
|
||||
extf_stream_free,
|
||||
extf_update_size,
|
||||
extf_get_input_stream
|
||||
extf_get_input_stream,
|
||||
extf_cmp_ino
|
||||
};
|
||||
|
||||
|
||||
static
|
||||
int extf_cmp_ino(IsoStream *s1, IsoStream *s2)
|
||||
{
|
||||
ExternalFilterStreamData *data1, *data2;
|
||||
|
||||
if (s1->class != &extf_stream_class || s2->class != &extf_stream_class)
|
||||
return iso_stream_cmp_ino(s1, s2, 1);
|
||||
data1 = (ExternalFilterStreamData*) s1->data;
|
||||
data2 = (ExternalFilterStreamData*) s2->data;
|
||||
if (data1->cmd != data2->cmd)
|
||||
return (data1->cmd < data2->cmd ? -1 : 1);
|
||||
return iso_stream_cmp_ino(data1->orig, data2->orig, 0);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static
|
||||
void extf_filter_free(FilterContext *filter)
|
||||
{
|
||||
|
@ -521,8 +521,12 @@ IsoStream *gzip_get_input_stream(IsoStream *stream, int flag)
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int gzip_cmp_ino(IsoStream *s1, IsoStream *s2);
|
||||
|
||||
|
||||
IsoStreamIface gzip_stream_compress_class = {
|
||||
2,
|
||||
3,
|
||||
"gzip",
|
||||
gzip_stream_open,
|
||||
gzip_stream_close,
|
||||
@ -532,12 +536,13 @@ IsoStreamIface gzip_stream_compress_class = {
|
||||
gzip_stream_get_id,
|
||||
gzip_stream_free,
|
||||
gzip_update_size,
|
||||
gzip_get_input_stream
|
||||
gzip_get_input_stream,
|
||||
gzip_cmp_ino
|
||||
};
|
||||
|
||||
|
||||
IsoStreamIface gzip_stream_uncompress_class = {
|
||||
2,
|
||||
3,
|
||||
"pizg",
|
||||
gzip_stream_open,
|
||||
gzip_stream_close,
|
||||
@ -547,9 +552,24 @@ IsoStreamIface gzip_stream_uncompress_class = {
|
||||
gzip_stream_get_id,
|
||||
gzip_stream_free,
|
||||
gzip_update_size,
|
||||
gzip_get_input_stream
|
||||
gzip_get_input_stream,
|
||||
gzip_cmp_ino
|
||||
};
|
||||
|
||||
|
||||
static
|
||||
int gzip_cmp_ino(IsoStream *s1, IsoStream *s2)
|
||||
{
|
||||
if (s1->class != s2->class || (s1->class != &gzip_stream_compress_class &&
|
||||
s2->class != &gzip_stream_compress_class))
|
||||
return iso_stream_cmp_ino(s1, s2, 1);
|
||||
return iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0),
|
||||
iso_stream_get_input_stream(s2, 0), 0);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
static
|
||||
void gzip_filter_free(FilterContext *filter)
|
||||
|
@ -775,8 +775,12 @@ IsoStream *ziso_get_input_stream(IsoStream *stream, int flag)
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int ziso_cmp_ino(IsoStream *s1, IsoStream *s2);
|
||||
|
||||
|
||||
IsoStreamIface ziso_stream_compress_class = {
|
||||
2,
|
||||
3,
|
||||
"ziso",
|
||||
ziso_stream_open,
|
||||
ziso_stream_close,
|
||||
@ -786,12 +790,13 @@ IsoStreamIface ziso_stream_compress_class = {
|
||||
ziso_stream_get_id,
|
||||
ziso_stream_free,
|
||||
ziso_update_size,
|
||||
ziso_get_input_stream
|
||||
ziso_get_input_stream,
|
||||
ziso_cmp_ino
|
||||
};
|
||||
|
||||
|
||||
IsoStreamIface ziso_stream_uncompress_class = {
|
||||
2,
|
||||
3,
|
||||
"osiz",
|
||||
ziso_stream_open,
|
||||
ziso_stream_close,
|
||||
@ -801,10 +806,25 @@ IsoStreamIface ziso_stream_uncompress_class = {
|
||||
ziso_stream_get_id,
|
||||
ziso_stream_free,
|
||||
ziso_update_size,
|
||||
ziso_get_input_stream
|
||||
ziso_get_input_stream,
|
||||
ziso_cmp_ino
|
||||
};
|
||||
|
||||
|
||||
static
|
||||
int ziso_cmp_ino(IsoStream *s1, IsoStream *s2)
|
||||
{
|
||||
if (s1->class != s2->class || (s1->class != &ziso_stream_compress_class &&
|
||||
s2->class != &ziso_stream_uncompress_class))
|
||||
iso_stream_cmp_ino(s1, s2, 1);
|
||||
return iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0),
|
||||
iso_stream_get_input_stream(s2, 0), 0);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
static
|
||||
void ziso_filter_free(FilterContext *filter)
|
||||
{
|
||||
|
@ -63,6 +63,12 @@ struct iso_read_opts
|
||||
unsigned int noiso1999 : 1; /*< Do not read ISO 9660:1999 enhanced tree */
|
||||
unsigned int noaaip : 1; /* Do not read AAIP extension for xattr and ACL */
|
||||
|
||||
/**
|
||||
* Hand out new inode numbers and overwrite eventually read PX inode
|
||||
* numbers. This will split apart any hardlinks.
|
||||
*/
|
||||
unsigned int make_new_ino : 1 ;
|
||||
|
||||
/**
|
||||
* When both Joliet and RR extensions are present, the RR tree is used.
|
||||
* If you prefer using Joliet, set this to 1.
|
||||
@ -88,6 +94,7 @@ struct iso_read_opts
|
||||
* attribute "isofs.cs" of root directory
|
||||
*/
|
||||
int auto_input_charset;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@ -137,6 +144,7 @@ enum read_rr_ext {
|
||||
RR_EXT_112 = 2 /*< RR extensions conforming version 1.12 */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Private data for the image IsoFilesystem
|
||||
*/
|
||||
@ -261,9 +269,20 @@ typedef struct
|
||||
uint32_t imgblock; /**< Block for El-Torito boot image */
|
||||
uint32_t catblock; /**< Block for El-Torito catalog */
|
||||
|
||||
/* Whether inode numbers from PX entries shall be discarded */
|
||||
unsigned int make_new_ino : 1 ;
|
||||
|
||||
/* Inode number generator counter */
|
||||
ino_t inode_counter;
|
||||
|
||||
/* PX inode number status
|
||||
bit0= there were nodes with PX inode numbers
|
||||
bit1= there were nodes with PX but without inode numbers
|
||||
bit2= there were nodes without PX
|
||||
bit3= there were nodes with faulty PX
|
||||
*/
|
||||
int px_ino_status;
|
||||
|
||||
} _ImageFsData;
|
||||
|
||||
typedef struct image_fs_data ImageFileSourceData;
|
||||
@ -1070,6 +1089,8 @@ char *get_name(_ImageFsData *fsdata, const char *str, size_t len)
|
||||
}
|
||||
|
||||
|
||||
#ifndef Libisofs_hardlink_prooF
|
||||
|
||||
/**
|
||||
* A global counter for default inode numbers for the ISO image filesystem.
|
||||
* @param fs The filesystem where the number shall be used
|
||||
@ -1087,11 +1108,13 @@ ino_t fs_give_ino_number(IsoImageFilesystem *fs, int flag)
|
||||
if (fsdata->inode_counter == 0) {
|
||||
|
||||
/* >>> raise alert because of inode rollover */;
|
||||
|
||||
|
||||
}
|
||||
return fsdata->inode_counter;
|
||||
}
|
||||
|
||||
#endif /* ! Libisofs_hardlink_prooF */
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
@ -1135,6 +1158,8 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
||||
size_t cs_value_length = 0;
|
||||
char msg[160];
|
||||
|
||||
int has_px = 0;
|
||||
|
||||
#ifdef Libisofs_with_zliB
|
||||
uint8_t zisofs_alg[2], zisofs_hs4 = 0, zisofs_bsl2 = 0;
|
||||
uint32_t zisofs_usize = 0;
|
||||
@ -1147,6 +1172,7 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
||||
fsdata = (_ImageFsData*)fs->data;
|
||||
|
||||
memset(&atts, 0, sizeof(struct stat));
|
||||
atts.st_nlink = 1;
|
||||
|
||||
/*
|
||||
* First of all, check for unsupported ECMA-119 features
|
||||
@ -1275,12 +1301,22 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
||||
continue;
|
||||
|
||||
if (SUSP_SIG(sue, 'P', 'X')) {
|
||||
has_px = 1;
|
||||
ret = read_rr_PX(sue, &atts);
|
||||
if (ret < 0) {
|
||||
/* notify and continue */
|
||||
ret = iso_msg_submit(fsdata->msgid, ISO_WRONG_RR_WARN, ret,
|
||||
"Invalid PX entry");
|
||||
fsdata->px_ino_status |= 8;
|
||||
} if (ret == 2) {
|
||||
if (fsdata->inode_counter < atts.st_ino)
|
||||
fsdata->inode_counter = atts.st_ino;
|
||||
fsdata->px_ino_status |= 1;
|
||||
|
||||
} else {
|
||||
fsdata->px_ino_status |= 2;
|
||||
}
|
||||
|
||||
} else if (SUSP_SIG(sue, 'T', 'F')) {
|
||||
ret = read_rr_TF(sue, &atts);
|
||||
if (ret < 0) {
|
||||
@ -1536,6 +1572,10 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_px) {
|
||||
fsdata->px_ino_status |= 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* if we haven't RR extensions, or no NM entry is present,
|
||||
* we use the name in directory record
|
||||
@ -1596,9 +1636,18 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
||||
/* but the real name is the name of the placeholder */
|
||||
ifsdata = (ImageFileSourceData*) (*src)->data;
|
||||
ifsdata->name = name;
|
||||
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_hardlink_prooF
|
||||
|
||||
/* Production of missing inode numbers is delayed until the image is
|
||||
complete. Then all nodes which shall get a new inode number will
|
||||
be served.
|
||||
*/
|
||||
|
||||
#else /* Libisofs_hardlink_prooF */
|
||||
|
||||
#ifdef Libisofs_new_fs_image_inO
|
||||
|
||||
@ -1611,6 +1660,7 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
||||
|
||||
#else /* Libisofs_new_fs_image_inO */
|
||||
|
||||
|
||||
/* ts Nov 25 2008: TODO
|
||||
This seems not fully consistent with read_rr_PX() which decides
|
||||
by (px->len_sue[0] == 44) whether an inode number is present or not.
|
||||
@ -1630,19 +1680,7 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
||||
* to generate those serial numbers, and we use extend block instead.
|
||||
* It BREAKS POSIX SEMANTICS, but its suitable for our needs
|
||||
*/
|
||||
|
||||
#ifndef Libisofs_ino_from_lbA
|
||||
#define Libisofs_patch_ticket_144 yes
|
||||
#endif
|
||||
#ifdef Libisofs_patch_ticket_144
|
||||
|
||||
atts.st_ino = fs_give_ino_number(fs, 0);
|
||||
|
||||
#else
|
||||
/* Ticket 144: This produces duplicate numbers with empty files.
|
||||
*/
|
||||
atts.st_ino = (ino_t) iso_read_bb(record->block, 4, NULL);
|
||||
#endif
|
||||
if (fsdata->rr == 0) {
|
||||
atts.st_nlink = 1;
|
||||
}
|
||||
@ -1650,6 +1688,8 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
||||
|
||||
#endif /* ! Libisofs_new_fs_image_inO */
|
||||
|
||||
#endif /* ! Libisofs_hardlink_prooF */
|
||||
|
||||
/*
|
||||
* if we haven't RR extensions, or a needed TF time stamp is not present,
|
||||
* we use plain iso recording time
|
||||
@ -1974,7 +2014,6 @@ void ifs_fs_free(IsoFilesystem *fs)
|
||||
free(data->copyright_file_id);
|
||||
free(data->abstract_file_id);
|
||||
free(data->biblio_file_id);
|
||||
|
||||
free(data->input_charset);
|
||||
free(data->local_charset);
|
||||
free(data);
|
||||
@ -2273,13 +2312,9 @@ int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts,
|
||||
data->msgid = msgid;
|
||||
data->aaip_load = !opts->noaaip;
|
||||
data->aaip_version = -1;
|
||||
|
||||
#ifndef Libisofs_setlocale_in_iniT
|
||||
/* ??? ts Nov 25 2008 :
|
||||
Shouldn't this go to library initialization or even to app ?
|
||||
*/
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
data->make_new_ino = opts->make_new_ino;
|
||||
data->inode_counter = 0;
|
||||
data->px_ino_status = 0;
|
||||
|
||||
data->local_charset = strdup(iso_get_local_charset(0));
|
||||
if (data->local_charset == NULL) {
|
||||
@ -2522,6 +2557,7 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
IsoNode *new;
|
||||
char *name;
|
||||
ImageFileSourceData *data;
|
||||
_ImageFsData *fsdata;
|
||||
|
||||
#ifdef Libisofs_with_zliB
|
||||
/* Intimate friendship with this function in filters/zisofs.c */
|
||||
@ -2536,6 +2572,7 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
}
|
||||
|
||||
data = (ImageFileSourceData*)src->data;
|
||||
fsdata = data->fs->data;
|
||||
|
||||
name = iso_file_source_get_name(src);
|
||||
|
||||
@ -2550,7 +2587,6 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
case S_IFREG:
|
||||
{
|
||||
/* source is a regular file */
|
||||
_ImageFsData *fsdata = data->fs->data;
|
||||
|
||||
/* El-Torito images have only one section */
|
||||
if (fsdata->eltorito && data->sections[0].block == fsdata->catblock) {
|
||||
@ -2677,6 +2713,13 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
}
|
||||
link->dest = strdup(dest);
|
||||
link->node.type = LIBISO_SYMLINK;
|
||||
|
||||
#ifdef Libisofs_hardlink_matcheR
|
||||
link->fs_id = ISO_IMAGE_FS_ID;
|
||||
link->st_dev = info.st_dev;
|
||||
link->st_ino = info.st_ino;
|
||||
#endif
|
||||
|
||||
new = (IsoNode*) link;
|
||||
new->refcount = 0;
|
||||
}
|
||||
@ -2695,6 +2738,13 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
}
|
||||
special->dev = info.st_rdev;
|
||||
special->node.type = LIBISO_SPECIAL;
|
||||
|
||||
#ifdef Libisofs_hardlink_matcheR
|
||||
special->fs_id = ISO_IMAGE_FS_ID;
|
||||
special->st_dev = info.st_dev;
|
||||
special->st_ino = info.st_ino;
|
||||
#endif
|
||||
|
||||
new = (IsoNode*) special;
|
||||
new->refcount = 0;
|
||||
}
|
||||
@ -2718,15 +2768,30 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
||||
|
||||
ret = src_aa_to_node(src, new, 0);
|
||||
if (ret < 0) {
|
||||
/* todo: stuff any possible memory leak here */
|
||||
if (name != NULL)
|
||||
free(name);
|
||||
free(new);
|
||||
return ret;
|
||||
goto failure;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_hardlink_prooF
|
||||
|
||||
/* Attach ino as xinfo if valid and no IsoStream is involved */
|
||||
if (info.st_ino != 0 && (info.st_mode & S_IFMT) != S_IFREG &&
|
||||
!fsdata->make_new_ino) {
|
||||
ret = iso_node_set_ino(new, info.st_ino, 0);
|
||||
if (ret < 0)
|
||||
goto failure;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_hardlink_prooF */
|
||||
|
||||
*node = new;
|
||||
return ISO_SUCCESS;
|
||||
|
||||
failure:;
|
||||
/* todo: stuff any possible memory leak here */
|
||||
if (name != NULL)
|
||||
free(name);
|
||||
free(new);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2763,7 +2828,8 @@ int iso_image_builder_new(IsoNodeBuilder *old, IsoNodeBuilder **builder)
|
||||
* accessible from the ISO filesystem.
|
||||
*/
|
||||
static
|
||||
int create_boot_img_filesrc(IsoImageFilesystem *fs, IsoFileSource **src)
|
||||
int create_boot_img_filesrc(IsoImageFilesystem *fs, IsoImage *image,
|
||||
IsoFileSource **src)
|
||||
{
|
||||
int ret;
|
||||
struct stat atts;
|
||||
@ -2780,6 +2846,12 @@ int create_boot_img_filesrc(IsoImageFilesystem *fs, IsoFileSource **src)
|
||||
memset(&atts, 0, sizeof(struct stat));
|
||||
atts.st_mode = S_IFREG;
|
||||
|
||||
#ifdef Libisofs_hardlink_prooF
|
||||
|
||||
atts.st_ino = img_give_ino_number(image, 0);
|
||||
|
||||
#else /* Libisofs_hardlink_prooF */
|
||||
|
||||
#ifdef Libisofs_new_fs_image_inO
|
||||
|
||||
atts.st_ino = fs_give_ino_number(fs, 0);
|
||||
@ -2790,6 +2862,8 @@ int create_boot_img_filesrc(IsoImageFilesystem *fs, IsoFileSource **src)
|
||||
|
||||
#endif /* ! Libisofs_new_fs_image_inO */
|
||||
|
||||
#endif /* ! Libisofs_hardlink_prooF */
|
||||
|
||||
atts.st_nlink = 1;
|
||||
|
||||
/*
|
||||
@ -2852,7 +2926,7 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
struct iso_read_opts *opts,
|
||||
IsoReadImageFeatures **features)
|
||||
{
|
||||
int ret;
|
||||
int ret, hflag;
|
||||
IsoImageFilesystem *fs;
|
||||
IsoFilesystem *fsback;
|
||||
IsoNodeBuilder *blback;
|
||||
@ -2915,6 +2989,17 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
if (ret < 0)
|
||||
goto import_revert;
|
||||
|
||||
#ifdef Libisofs_hardlink_prooF
|
||||
|
||||
/* Attach ino as xinfo if valid */
|
||||
if (info.st_ino != 0 && !data->make_new_ino) {
|
||||
ret = iso_node_set_ino(&(image->root->node), info.st_ino, 0);
|
||||
if (ret < 0)
|
||||
goto import_revert;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_hardlink_prooF */
|
||||
|
||||
}
|
||||
|
||||
/* if old image has el-torito, add a new catalog */
|
||||
@ -2951,12 +3036,36 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
goto import_revert;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_hardlink_prooF
|
||||
|
||||
/* Take over inode management from IsoImageFilesystem.
|
||||
data->inode_counter is supposed to hold the maximum PX inode number.
|
||||
*/
|
||||
image->inode_counter = data->inode_counter;
|
||||
|
||||
if ((data->px_ino_status & (2 | 4 | 8)) || opts->make_new_ino) {
|
||||
/* Attach new inode numbers to any node which does not have one,
|
||||
resp. to all nodes in case of opts->make_new_ino
|
||||
*/
|
||||
if (opts->make_new_ino)
|
||||
hflag = 1; /* Equip all data files with new unique inos */
|
||||
else
|
||||
hflag = 2 | 4 | 8; /* Equip any file type if it has ino == 0 */
|
||||
ret = img_make_inos(image, image->root, hflag);
|
||||
if (ret < 0) {
|
||||
iso_node_builder_unref(image->builder);
|
||||
goto import_revert;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ! Libisofs_hardlink_prooF */
|
||||
|
||||
if (data->eltorito) {
|
||||
/* if catalog and image nodes were not filled, we create them here */
|
||||
if (image->bootcat->image->image == NULL) {
|
||||
IsoFileSource *src;
|
||||
IsoNode *node;
|
||||
ret = create_boot_img_filesrc(fs, &src);
|
||||
ret = create_boot_img_filesrc(fs, image, &src);
|
||||
if (ret < 0) {
|
||||
iso_node_builder_unref(image->builder);
|
||||
goto import_revert;
|
||||
@ -3177,6 +3286,16 @@ int iso_read_opts_set_no_aaip(IsoReadOpts *opts, int noaaip)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int iso_read_opts_set_new_inos(IsoReadOpts *opts, int new_inos)
|
||||
{
|
||||
if (opts == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
opts->make_new_ino = new_inos ? 1 : 0;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int iso_read_opts_set_preferjoliet(IsoReadOpts *opts, int preferjoliet)
|
||||
{
|
||||
if (opts == NULL) {
|
||||
@ -3355,3 +3474,29 @@ int iso_file_get_old_image_sections(IsoFile *file, int *section_count,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Rank two IsoFileSource by their eventual old image LBAs.
|
||||
Other IsoFileSource classes will be ranked only roughly.
|
||||
*/
|
||||
int iso_ifs_sections_cmp(IsoFileSource *s1, IsoFileSource *s2, int flag)
|
||||
{
|
||||
int i;
|
||||
ImageFileSourceData *d1, *d2;
|
||||
|
||||
if (s1->class != s2->class)
|
||||
return (s1->class < s2->class ? -1 : 1);
|
||||
if (s1->class != &ifs_class)
|
||||
return(0);
|
||||
|
||||
d1= s1->data;
|
||||
d2= s2->data;
|
||||
for (i = 0; i < d1->nsections; i++) {
|
||||
if (i >= d2->nsections)
|
||||
return 1;
|
||||
if (d1->sections[i].block != d2->sections[i].block)
|
||||
return (d1->sections[i].block < d2->sections[i].block ? -1 : 1);
|
||||
if (d1->sections[i].size != d2->sections[i].size)
|
||||
return (d1->sections[i].size < d2->sections[i].size ? -1 : 1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
@ -30,4 +31,10 @@
|
||||
*/
|
||||
int iso_local_filesystem_new(IsoFilesystem **fs);
|
||||
|
||||
|
||||
/* Rank two IsoFileSource by their eventual old image LBAs.
|
||||
Other IsoFileSource classes will be ranked only roughly.
|
||||
*/
|
||||
int iso_ifs_sections_cmp(IsoFileSource *s1, IsoFileSource *s2, int flag);
|
||||
|
||||
#endif /*LIBISO_FSOURCE_H_*/
|
||||
|
211
libisofs/image.c
211
libisofs/image.c
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
@ -14,6 +15,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* Create a new image, empty.
|
||||
@ -73,6 +75,9 @@ int iso_image_new(const char *name, IsoImage **image)
|
||||
}
|
||||
img->builder_ignore_acl = 1;
|
||||
img->builder_ignore_ea = 1;
|
||||
img->inode_counter = 0;
|
||||
img->used_inodes = NULL;
|
||||
img->used_inodes_start = 0;
|
||||
*image = img;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
@ -119,6 +124,8 @@ void iso_image_unref(IsoImage *image)
|
||||
free(image->copyright_file_id);
|
||||
free(image->abstract_file_id);
|
||||
free(image->biblio_file_id);
|
||||
if (image->used_inodes != NULL)
|
||||
free(image->used_inodes);
|
||||
free(image);
|
||||
}
|
||||
}
|
||||
@ -318,3 +325,207 @@ void iso_image_set_ignore_aclea(IsoImage *image, int what)
|
||||
image->builder_ignore_ea = !!(what & 2);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int img_register_ino(IsoImage *image, IsoNode *node, int flag)
|
||||
{
|
||||
int ret;
|
||||
ino_t ino;
|
||||
unsigned int fs_id;
|
||||
dev_t dev_id;
|
||||
|
||||
ret = iso_node_get_id(node, &fs_id, &dev_id, &ino, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret > 0 && ino >= image->used_inodes_start &&
|
||||
ino <= image->used_inodes_start + (ISO_USED_INODE_RANGE - 1)) {
|
||||
/* without -1 : rollover hazard on 32 bit */
|
||||
image->used_inodes[(ino - image->used_inodes_start) / 8]
|
||||
|= (1 << (ino % 8));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Collect the bitmap of used inode numbers in the range of
|
||||
_ImageFsData.used_inodes_start + ISO_USED_INODE_RANGE
|
||||
@param flag bit0= recursion is active
|
||||
*/
|
||||
int img_collect_inos(IsoImage *image, IsoDir *dir, int flag)
|
||||
{
|
||||
int ret, register_dir = 1;
|
||||
IsoDirIter *iter = NULL;
|
||||
IsoNode *node;
|
||||
IsoDir *subdir;
|
||||
|
||||
if (dir == NULL)
|
||||
dir = image->root;
|
||||
if (image->used_inodes == NULL) {
|
||||
image->used_inodes = calloc(ISO_USED_INODE_RANGE / 8, 1);
|
||||
if (image->used_inodes == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
} else if(!(flag & 1)) {
|
||||
memset(image->used_inodes, 0, ISO_USED_INODE_RANGE / 8);
|
||||
} else {
|
||||
register_dir = 0;
|
||||
}
|
||||
if (register_dir) {
|
||||
node = (IsoNode *) dir;
|
||||
ret = img_register_ino(image, node, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = iso_dir_get_children(dir, &iter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
while (iso_dir_iter_next(iter, &node) == 1 ) {
|
||||
ret = img_register_ino(image, node, 0);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
if (iso_node_get_type(node) == LIBISO_DIR) {
|
||||
subdir = (IsoDir *) node;
|
||||
ret = img_collect_inos(image, subdir, flag | 1);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
ex:;
|
||||
if (iter != NULL)
|
||||
iso_dir_iter_free(iter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A global counter for inode numbers for the ISO image filesystem.
|
||||
* On image import it gets maxed by the eventual inode numbers from PX
|
||||
* entries. Up to the first 32 bit rollover it simply increments the counter.
|
||||
* After the first rollover it uses a look ahead bitmap which gets filled
|
||||
* by a full tree traversal. It covers the next inode numbers to come
|
||||
* (somewhere between 1 and ISO_USED_INODE_RANGE which is quite many)
|
||||
* and advances when being exhausted.
|
||||
* @param image The image where the number shall be used
|
||||
* @param flag bit0= reset count (Caution: image must get new inos then)
|
||||
* @return
|
||||
* Since ino_t 0 is used as default and considered self-unique,
|
||||
* the value 0 should only be returned in case of error.
|
||||
*/
|
||||
ino_t img_give_ino_number(IsoImage *image, int flag)
|
||||
{
|
||||
int ret;
|
||||
ino_t new_ino, ino_idx;
|
||||
static uint64_t limit = 0xffffffff;
|
||||
|
||||
if (flag & 1) {
|
||||
image->inode_counter = 0;
|
||||
if (image->used_inodes != NULL)
|
||||
free(image->used_inodes);
|
||||
image->used_inodes = NULL;
|
||||
image->used_inodes_start = 0;
|
||||
}
|
||||
new_ino = image->inode_counter + 1;
|
||||
if (image->used_inodes == NULL) {
|
||||
if (new_ino > 0 && new_ino <= limit) {
|
||||
image->inode_counter = new_ino;
|
||||
return image->inode_counter;
|
||||
}
|
||||
}
|
||||
/* Look for free number in used territory */
|
||||
while (1) {
|
||||
if (new_ino <= 0 || new_ino > limit ||
|
||||
new_ino >= image->used_inodes_start + ISO_USED_INODE_RANGE ) {
|
||||
|
||||
/* Collect a bitmap of used inode numbers ahead */
|
||||
|
||||
image->used_inodes_start += ISO_USED_INODE_RANGE;
|
||||
if (image->used_inodes_start > 0xffffffff ||
|
||||
image->used_inodes_start <= 0)
|
||||
image->used_inodes_start = 0;
|
||||
ret = img_collect_inos(image, NULL, 0);
|
||||
if (ret < 0)
|
||||
goto return_result; /* >>> need error return value */
|
||||
|
||||
new_ino = image->used_inodes_start + !image->used_inodes_start;
|
||||
}
|
||||
ino_idx = (new_ino - image->used_inodes_start) / 8;
|
||||
if (!(image->used_inodes[ino_idx] & (1 << (new_ino % 8)))) {
|
||||
image->used_inodes[ino_idx] |= (1 << (new_ino % 8));
|
||||
break;
|
||||
}
|
||||
new_ino++;
|
||||
}
|
||||
return_result:;
|
||||
image->inode_counter = new_ino;
|
||||
return image->inode_counter;
|
||||
}
|
||||
|
||||
|
||||
/* @param flag bit0= overwrite any ino, else only ino == 0
|
||||
bit1= install inode with non-data, non-directory files
|
||||
bit2= install inode with directories
|
||||
*/
|
||||
static
|
||||
int img_update_ino(IsoImage *image, IsoNode *node, int flag)
|
||||
{
|
||||
int ret;
|
||||
ino_t ino;
|
||||
unsigned int fs_id;
|
||||
dev_t dev_id;
|
||||
|
||||
ret = iso_node_get_id(node, &fs_id, &dev_id, &ino, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret == 0)
|
||||
ino = 0;
|
||||
if (((flag & 1) || ino == 0) &&
|
||||
(iso_node_get_type(node) == LIBISO_FILE || (flag & (2 | 4))) &&
|
||||
((flag & 4) || iso_node_get_type(node) != LIBISO_DIR)) {
|
||||
ret = iso_node_set_unique_id(node, image, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* @param flag bit0= overwrite any ino, else only ino == 0
|
||||
bit1= install inode with non-data, non-directory files
|
||||
bit2= install inode with directories
|
||||
bit3= with bit2: install inode on parameter dir
|
||||
*/
|
||||
int img_make_inos(IsoImage *image, IsoDir *dir, int flag)
|
||||
{
|
||||
int ret;
|
||||
IsoDirIter *iter = NULL;
|
||||
IsoNode *node;
|
||||
IsoDir *subdir;
|
||||
|
||||
if (flag & 8) {
|
||||
node = (IsoNode *) dir;
|
||||
ret = img_update_ino(image, node, flag & 7);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
ret = iso_dir_get_children(dir, &iter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
while (iso_dir_iter_next(iter, &node) == 1) {
|
||||
ret = img_update_ino(image, node, flag & 7);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
if (iso_node_get_type(node) == LIBISO_DIR) {
|
||||
subdir = (IsoDir *) node;
|
||||
ret = img_make_inos(image, subdir, flag & ~8);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
ex:;
|
||||
if (iter != NULL)
|
||||
iso_dir_iter_free(iter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
@ -13,6 +14,14 @@
|
||||
#include "fsource.h"
|
||||
#include "builder.h"
|
||||
|
||||
/* Size of a inode recycling window. Each new window causes a tree traversal.
|
||||
Window memory consumption is ISO_USED_INODE_RANGE / 8.
|
||||
This must be a power of 2 smaller than 30 bit and larger than 8 bit.
|
||||
Here: 32 kB memory for 256k inodes.
|
||||
*/
|
||||
#define ISO_USED_INODE_RANGE (1 << 18)
|
||||
|
||||
|
||||
/*
|
||||
* Image is a context for image manipulation.
|
||||
* Global objects such as the message_queues must belogn to that
|
||||
@ -121,6 +130,55 @@ struct Iso_Image
|
||||
*/
|
||||
void *user_data;
|
||||
void (*user_data_free)(void *ptr);
|
||||
|
||||
/**
|
||||
* Inode number management. inode_counter is taken over from
|
||||
* IsoImageFilesystem._ImageFsData after image import.
|
||||
* It is to be used with img_give_ino_number()
|
||||
*/
|
||||
ino_t inode_counter;
|
||||
/*
|
||||
* A bitmap of used inode numbers in an interval beginning at
|
||||
* used_inodes_start and holding ISO_USED_INODE_RANGE bits.
|
||||
* If a bit is set, then the corresponding inode number is occupied.
|
||||
* This interval is kept around inode_counter and eventually gets
|
||||
* advanced by ISO_USED_INODE_RANGE numbers in a tree traversal
|
||||
* done by img_collect_inos().
|
||||
*/
|
||||
uint8_t *used_inodes;
|
||||
ino_t used_inodes_start;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Collect the bitmap of used inode numbers in the range of
|
||||
_ImageFsData.used_inodes_start + ISO_USED_INODE_RANGE
|
||||
@param flag bit0= recursion is active
|
||||
*/
|
||||
int img_collect_inos(IsoImage *image, IsoDir *dir, int flag);
|
||||
|
||||
/**
|
||||
* A global counter for inode numbers for the ISO image filesystem.
|
||||
* On image import it gets maxed by the eventual inode numbers from PX
|
||||
* entries. Up to the first 32 bit rollover it simply increments the counter.
|
||||
* After the first rollover it uses a look ahead bitmap which gets filled
|
||||
* by a full tree traversal. It covers the next inode numbers to come
|
||||
* (somewhere between 1 and ISO_USED_INODE_RANGE which is quite many)
|
||||
* and advances when being exhausted.
|
||||
* @param image The image where the number shall be used
|
||||
* @param flag bit0= reset count (Caution: image must get new inos then)
|
||||
* @return
|
||||
* Since ino_t 0 is used as default and considered self-unique,
|
||||
* the value 0 should only be returned in case of error.
|
||||
*/
|
||||
ino_t img_give_ino_number(IsoImage *image, int flag);
|
||||
|
||||
/* @param flag bit0= overwrite any ino, else only ino == 0
|
||||
bit1= install inode with non-data, non-directory files
|
||||
bit2= install inode with directories
|
||||
bit3= with bit2: install inode on parameter dir
|
||||
*/
|
||||
int img_make_inos(IsoImage *image, IsoDir *dir, int flag);
|
||||
|
||||
#endif /*LIBISO_IMAGE_H_*/
|
||||
|
@ -759,8 +759,11 @@ typedef struct IsoStream_Iface IsoStreamIface;
|
||||
extern ino_t serial_id;
|
||||
|
||||
/**
|
||||
* Interface definition for IsoStream methods.
|
||||
*
|
||||
* Interface definition for IsoStream methods. It is public to allow
|
||||
* implementation of own stream types.
|
||||
* The methods defined here typically make use of stream.data which points
|
||||
* to the individual state data of stream instances.
|
||||
*
|
||||
* @since 0.6.4
|
||||
*/
|
||||
struct IsoStream_Iface
|
||||
@ -772,7 +775,9 @@ struct IsoStream_Iface
|
||||
* Version 1 (since 0.6.8)
|
||||
* update_size() added.
|
||||
* Version 2 (since 0.6.18)
|
||||
* get_input_stream() added. A filter stream should have version 2.
|
||||
* get_input_stream() added. A filter stream must have version 2.
|
||||
* Version 3 (since 0.6.20)
|
||||
* compare() added. A filter stream should have version 3.
|
||||
*/
|
||||
int version;
|
||||
|
||||
@ -784,6 +789,8 @@ struct IsoStream_Iface
|
||||
* "extf" -> External filter program
|
||||
* "ziso" -> zisofs compression
|
||||
* "osiz" -> zisofs uncompression
|
||||
* "gzip" -> gzip compression
|
||||
* "pizg" -> gzip uncompression (gunzip)
|
||||
* "user" -> User supplied stream
|
||||
*/
|
||||
char type[4];
|
||||
@ -854,7 +861,6 @@ struct IsoStream_Iface
|
||||
void (*free)(IsoStream *stream);
|
||||
|
||||
/**
|
||||
* Present if .version is 1 or higher:
|
||||
* Updates the size of the IsoStream with the current size of the
|
||||
* underlying source. After calling this, get_size() will return
|
||||
* the new size. This should never be called after
|
||||
@ -867,24 +873,70 @@ struct IsoStream_Iface
|
||||
* 1 if ok, < 0 on error (has to be a valid libisofs error code)
|
||||
*
|
||||
* @since 0.6.8
|
||||
* Present if .version is 1 or higher.
|
||||
*/
|
||||
int (*update_size)(IsoStream *stream);
|
||||
|
||||
/**
|
||||
* Present if .version is 2 or higher:
|
||||
* Obtains the eventual input stream of a filter stream.
|
||||
*
|
||||
* @param stream
|
||||
* The eventual filter stream to be inquired.
|
||||
* The eventual filter stream to be inquired.
|
||||
* @param flag
|
||||
* Bitfield for control purposes. Submit 0 for now.
|
||||
* Bitfield for control purposes. Submit 0 for now.
|
||||
* @return
|
||||
* The input stream, if one exists. Elsewise NULL.
|
||||
* No extra reference to the stream is taken by this call.
|
||||
* The input stream, if one exists. Elsewise NULL.
|
||||
* No extra reference to the stream is taken by this call.
|
||||
*
|
||||
* @since 0.6.18
|
||||
* Present if .version is 2 or higher.
|
||||
*/
|
||||
IsoStream *(*get_input_stream)(IsoStream *stream, int flag);
|
||||
|
||||
/**
|
||||
* Compare two streams whether they are based on the same input and will
|
||||
* produce the same output. If in any doubt, then this comparison should
|
||||
* indicate no match. A match might allow hardlinking of IsoFile objects.
|
||||
*
|
||||
* This function has to establish an equivalence and order relation:
|
||||
* cmp_ino(A,A) == 0
|
||||
* cmp_ino(A,B) == -cmp_ino(B,A)
|
||||
* if cmp_ino(A,B) == 0 && cmp_ino(B,C) == 0 then cmp_ino(A,C) == 0
|
||||
* if cmp_ino(A,B) < 0 && cmp_ino(B,C) < 0 then cmp_ino(A,C) < 0
|
||||
*
|
||||
* A big hazard to the last constraint are tests which do not apply to some
|
||||
* types of streams. In this case for any A that is applicable and any B
|
||||
* that is not applicable, cmp_ino(A,B) must have the same non-zero
|
||||
* result. I.e. a pair of applicable and non-applicable streams must
|
||||
* return that non-zero result before the test for a pair of applicable
|
||||
* streams would happen.
|
||||
*
|
||||
* A function s1.(*cmp_ino)() must only accept stream s2 if function
|
||||
* s2.(*cmp_ino)() would accept s1. Best is to accept only the own stream
|
||||
* type or to have the same function for a family of similar stream types.
|
||||
*
|
||||
* If the function cannot accept one of the given stream types, then
|
||||
* the decision must be delegated to
|
||||
* iso_stream_cmp_ino(s1, s2, 1);
|
||||
* This is also appropriate if one has reason to implement stream.cmp_ino()
|
||||
* without special comparison algorithm.
|
||||
* With filter streams the decision whether the underlying chains of
|
||||
* streams match should be delegated to
|
||||
* iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0),
|
||||
* iso_stream_get_input_stream(s2, 0), 0);
|
||||
*
|
||||
* @param s1
|
||||
* The first stream to compare. Expect foreign stream types.
|
||||
* @param s2
|
||||
* The second stream to compare. Expect foreign stream types.
|
||||
* @return
|
||||
* -1 if s1 is smaller s2 , 0 if s1 matches s2 , 1 if s1 is larger s2
|
||||
*
|
||||
* @since 0.6.20
|
||||
* Present if .version is 3 or higher.
|
||||
*/
|
||||
int (*cmp_ino)(IsoStream *s1, IsoStream *s2);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1038,7 +1090,7 @@ int iso_lib_is_compatible(int major, int minor, int micro);
|
||||
*/
|
||||
#define iso_lib_header_version_major 0
|
||||
#define iso_lib_header_version_minor 6
|
||||
#define iso_lib_header_version_micro 18
|
||||
#define iso_lib_header_version_micro 20
|
||||
|
||||
/**
|
||||
* Usage discussion:
|
||||
@ -1184,15 +1236,47 @@ int iso_write_opts_set_joliet(IsoWriteOpts *opts, int enable);
|
||||
*/
|
||||
int iso_write_opts_set_iso1999(IsoWriteOpts *opts, int enable);
|
||||
|
||||
/**
|
||||
* Control generation of non-unique inode numbers for the emerging image.
|
||||
* Inode numbers get written as "file serial number" with PX entries as of
|
||||
* RRIP-1.12. They may mark families of hardlinks.
|
||||
* RRIP-1.10 prescribes a PX entry without file serial number. If not overriden
|
||||
* by iso_write_opts_set_rrip_1_10_px_ino() there will be no file serial
|
||||
* written into RRIP-1.10 images.
|
||||
*
|
||||
* Inode number generation does not affect IsoNode objects which imported their
|
||||
* inode numbers from the old ISO image (see iso_read_opts_set_new_inos())
|
||||
* and which have not been altered since import. It rather applies to IsoNode
|
||||
* objects which were newly added to the image, or to IsoNode which brought no
|
||||
* inode number from the old image, or to IsoNode where certain properties
|
||||
* have been altered since image import.
|
||||
*
|
||||
* If two IsoNode are found with same imported inode number but differing
|
||||
* properties, then one of them will get assigned a new unique inode number.
|
||||
* I.e. the hardlink relation between both IsoNode objects ends.
|
||||
*
|
||||
* @param enable
|
||||
* 1 = Collect IsoNode objects which have identical data sources and
|
||||
* properties.
|
||||
* 0 = Generate unique inode numbers for all IsoNode objects which do not
|
||||
* have a valid inode number from an imported ISO image.
|
||||
* All other values are reserved.
|
||||
*
|
||||
* @since 0.6.20
|
||||
*/
|
||||
int iso_write_opts_set_hardlinks(IsoWriteOpts *opts, int enable);
|
||||
|
||||
/**
|
||||
* Control writing of AAIP informations for ACL and xattr.
|
||||
* For importing ACL and xattr when inserting nodes from external filesystems
|
||||
* (e.g. the local POSIX filesystem) see iso_image_set_ignore_aclea().
|
||||
* For loading of this information from images see iso_read_opts_set_no_aaip().
|
||||
*
|
||||
* @param enable 1 = write AAIP information from nodes into the image
|
||||
* 0 = do not write AAIP information into the image
|
||||
* All other values are reserved.
|
||||
* @param enable
|
||||
* 1 = write AAIP information from nodes into the image
|
||||
* 0 = do not write AAIP information into the image
|
||||
* All other values are reserved.
|
||||
*
|
||||
* @since 0.6.14
|
||||
*/
|
||||
int iso_write_opts_set_aaip(IsoWriteOpts *opts, int enable);
|
||||
@ -1288,6 +1372,18 @@ int iso_write_opts_set_joliet_longer_paths(IsoWriteOpts *opts, int allow);
|
||||
*/
|
||||
int iso_write_opts_set_rrip_version_1_10(IsoWriteOpts *opts, int oldvers);
|
||||
|
||||
/**
|
||||
* Write field PX with file serial number (i.e. inode number) even if
|
||||
* iso_write_opts_set_rrip_version_1_10(,1) is in effect.
|
||||
* This clearly violates the RRIP-1.10 specs. But it is done by mkisofs since
|
||||
* a while and no widespread protest is visible in the web.
|
||||
* If this option is not enabled, then iso_write_opts_set_hardlinks() will
|
||||
* only have an effect with iso_write_opts_set_rrip_version_1_10(,0).
|
||||
*
|
||||
* @since 0.6.20
|
||||
*/
|
||||
int iso_write_opts_set_rrip_1_10_px_ino(IsoWriteOpts *opts, int enable);
|
||||
|
||||
/**
|
||||
* Write AAIP as extension according to SUSP 1.10 rather than SUSP 1.12.
|
||||
* I.e. without announcing it by an ER field and thus without the need
|
||||
@ -1651,13 +1747,34 @@ int iso_read_opts_set_no_iso1999(IsoReadOpts *opts, int noiso1999);
|
||||
* (e.g. the local POSIX filesystem) see iso_image_set_ignore_aclea().
|
||||
* For eventual writing of this information see iso_write_opts_set_aaip().
|
||||
*
|
||||
* @param noaaip 1 = do not read AAIP information
|
||||
* 0 = read AAIP information if available
|
||||
* All other values are reserved.
|
||||
* @param noaaip
|
||||
* 1 = Do not read AAIP information
|
||||
* 0 = Read AAIP information if available
|
||||
* All other values are reserved.
|
||||
* @since 0.6.14
|
||||
*/
|
||||
int iso_read_opts_set_no_aaip(IsoReadOpts *opts, int noaaip);
|
||||
|
||||
/**
|
||||
* Control discarding of eventual inode numbers from existing images.
|
||||
* Such numbers may come from RRIP 1.12 entries PX. If not discarded they
|
||||
* get written unchanged when the file object gets written into an ISO image.
|
||||
* If this inode number is missing with a file in the imported image,
|
||||
* or if it has been discarded during image reading, then a unique inode number
|
||||
* will be generated at some time before the file gets written into an ISO
|
||||
* image.
|
||||
* Two image nodes which have the same inode number represent two hardlinks
|
||||
* of the same file object. So discarding the numbers splits hardlinks.
|
||||
*
|
||||
* @param new_inos
|
||||
* 1 = Discard imported inode numbers and finally hand out a unique new
|
||||
* one to each single file before it gets written into an ISO image.
|
||||
* 0 = Keep eventual inode numbers from PX entries.
|
||||
* All other values are reserved.
|
||||
* @since 0.6.20
|
||||
*/
|
||||
int iso_read_opts_set_new_inos(IsoReadOpts *opts, int new_inos);
|
||||
|
||||
/**
|
||||
* Whether to prefer Joliet over RR. libisofs usually prefers RR over
|
||||
* Joliet, as it give us much more info about files. So, if both extensions
|
||||
@ -2122,7 +2239,7 @@ void el_torito_set_load_size(ElToritoBootImage *bootimg, short sectors);
|
||||
void el_torito_set_no_bootable(ElToritoBootImage *bootimg);
|
||||
|
||||
/**
|
||||
* Specifies that this image needs to be patched. This involves the writting
|
||||
* Specifies that this image needs to be patched. This involves the writing
|
||||
* of a 56 bytes boot information table at offset 8 of the boot image file.
|
||||
* The original boot image file won't be modified.
|
||||
* This is needed for isolinux boot images.
|
||||
@ -2384,7 +2501,7 @@ time_t iso_node_get_ctime(const IsoNode *node);
|
||||
/**
|
||||
* Set if the node will be hidden in RR/ISO tree, Joliet tree or both.
|
||||
*
|
||||
* If the file is setted as hidden in one tree, it won't be included there, so
|
||||
* If the file is set as hidden in one tree, it won't be included there, so
|
||||
* it won't be visible in a OS accessing CD using that tree. For example,
|
||||
* GNU/Linux systems access to Rock Ridge / ISO9960 tree in order to see
|
||||
* what is recorded on CD, while MS Windows make use of the Joliet tree. If a
|
||||
@ -2402,6 +2519,22 @@ time_t iso_node_get_ctime(const IsoNode *node);
|
||||
*/
|
||||
void iso_node_set_hidden(IsoNode *node, int hide_attrs);
|
||||
|
||||
/**
|
||||
* Compare two nodes whether they are based on the same input and
|
||||
* can be considered as hardlinks to the same file objects.
|
||||
*
|
||||
* @param n1
|
||||
* The first node to compare.
|
||||
* @param n2
|
||||
* The second node to compare.
|
||||
* @return
|
||||
* -1 if s1 is smaller s2 , 0 if s1 matches s2 , 1 if s1 is larger s2
|
||||
* @param flag
|
||||
* Bitfield for control purposes, unused yet, submit 0
|
||||
* @since 0.6.20
|
||||
*/
|
||||
int iso_node_cmp_ino(IsoNode *n1, IsoNode *n2, int flag);
|
||||
|
||||
/**
|
||||
* Add a new node to a dir. Note that this function don't add a new ref to
|
||||
* the node, so you don't need to free it, it will be automatically freed
|
||||
@ -2503,7 +2636,7 @@ int iso_node_remove(IsoNode *node);
|
||||
* If node is the root node, the same node will be returned as its parent.
|
||||
*
|
||||
* This returns NULL if the node doesn't pertain to any tree
|
||||
* (it was removed/take).
|
||||
* (it was removed/taken).
|
||||
*
|
||||
* @since 0.6.2
|
||||
*/
|
||||
@ -4078,7 +4211,9 @@ void iso_stream_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id,
|
||||
/**
|
||||
* Try to get eventual source path string of a stream. Meaning and availability
|
||||
* of this string depends on the stream.class . Expect valid results with
|
||||
* types "fsrc" and "cout".
|
||||
* types "fsrc" and "cout". Result formats are
|
||||
* fsrc: result of file_source_get_path()
|
||||
* cout: result of file_source_get_path() " " offset " " size
|
||||
* @param stream
|
||||
* The stream to be inquired.
|
||||
* @param flag
|
||||
@ -4091,6 +4226,25 @@ void iso_stream_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id,
|
||||
*/
|
||||
char *iso_stream_get_source_path(IsoStream *stream, int flag);
|
||||
|
||||
/**
|
||||
* Compare two streams whether they are based on the same input and will
|
||||
* produce the same output. If in any doubt, then this comparison will
|
||||
* indicate no match.
|
||||
*
|
||||
* @param s1
|
||||
* The first stream to compare.
|
||||
* @param s2
|
||||
* The second stream to compare.
|
||||
* @return
|
||||
* -1 if s1 is smaller s2 , 0 if s1 matches s2 , 1 if s1 is larger s2
|
||||
* @param flag
|
||||
* bit0= do not use s1->class->compare() even if available
|
||||
* (e.g. because iso_stream_cmp_ino(0 is called as fallback
|
||||
* from said stream->class->compare())
|
||||
*
|
||||
* @since 0.6.20
|
||||
*/
|
||||
int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, int flag);
|
||||
|
||||
/* --------------------------------- AAIP --------------------------------- */
|
||||
|
||||
@ -4998,18 +5152,6 @@ int iso_gzip_get_refcounts(off_t *gzip_count, off_t *gunzip_count, int flag);
|
||||
/** El-Torito image is hidden (WARNING,HIGH, -335) */
|
||||
#define ISO_EL_TORITO_HIDDEN 0xD030FEB1
|
||||
|
||||
/** Read error occured with IsoDataSource (SORRY,HIGH, -513) */
|
||||
#define ISO_DATA_SOURCE_SORRY 0xE030FCFF
|
||||
|
||||
/** Read error occured with IsoDataSource (MISHAP,HIGH, -513) */
|
||||
#define ISO_DATA_SOURCE_MISHAP 0xE430FCFF
|
||||
|
||||
/** Read error occured with IsoDataSource (FAILURE,HIGH, -513) */
|
||||
#define ISO_DATA_SOURCE_FAILURE 0xE830FCFF
|
||||
|
||||
/** Read error occured with IsoDataSource (FATAL,HIGH, -513) */
|
||||
#define ISO_DATA_SOURCE_FATAL 0xF030FCFF
|
||||
|
||||
|
||||
/** AAIP info with ACL or xattr in ISO image will be ignored
|
||||
(NOTE, HIGH, -336) */
|
||||
@ -5066,6 +5208,25 @@ int iso_gzip_get_refcounts(off_t *gzip_count, off_t *gunzip_count, int flag);
|
||||
#define ISO_ZLIB_EARLY_EOF 0xE830FEA1
|
||||
|
||||
|
||||
/* ! PLACE NEW ERROR CODES HERE ! */
|
||||
|
||||
|
||||
/** Read error occured with IsoDataSource (SORRY,HIGH, -513) */
|
||||
#define ISO_DATA_SOURCE_SORRY 0xE030FCFF
|
||||
|
||||
/** Read error occured with IsoDataSource (MISHAP,HIGH, -513) */
|
||||
#define ISO_DATA_SOURCE_MISHAP 0xE430FCFF
|
||||
|
||||
/** Read error occured with IsoDataSource (FAILURE,HIGH, -513) */
|
||||
#define ISO_DATA_SOURCE_FAILURE 0xE830FCFF
|
||||
|
||||
/** Read error occured with IsoDataSource (FATAL,HIGH, -513) */
|
||||
#define ISO_DATA_SOURCE_FATAL 0xF030FCFF
|
||||
|
||||
|
||||
/* ! PLACE NEW ERROR CODES ABOVE. NOT HERE ! */
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef LIBISOFS_WITHOUT_LIBBURN
|
||||
@ -5253,30 +5414,36 @@ struct burn_source {
|
||||
|
||||
/* ---------------------------- Improvements --------------------------- */
|
||||
|
||||
|
||||
/* Cleanup : make call setlocale() at init time resp. never
|
||||
*/
|
||||
#define Libisofs_setlocale_in_iniT yes
|
||||
|
||||
|
||||
/* Protocol Upgrade : change to AAIP-2.0 with field signature "AL"
|
||||
*/
|
||||
#define Libisofs_aaip_2_0 yes
|
||||
|
||||
/* currently none being tested */
|
||||
|
||||
/* ---------------------------- Experiments ---------------------------- */
|
||||
|
||||
/* Hardlinks : During image generation accompany the tree of IsoFileSrc
|
||||
by a sorted array of Ecma119Node.
|
||||
The sorting order shall bring together candidates for being
|
||||
hardlink siblings resp. having identical content.
|
||||
|
||||
This is in sync with the IsoFileSrc unification by IsoRBTree
|
||||
and iso_file_src_cmp().
|
||||
That tree cannot be obsoleted because Joliet and ISO1999 depend
|
||||
on it. On the other hand, the Ecma119Node array includes objects
|
||||
which have no IsoFileSrc attached. So both, tree and array, are
|
||||
needed.
|
||||
*/
|
||||
#define Libisofs_hardlink_matcheR yes
|
||||
|
||||
|
||||
/* Hardlinks : Override Libisofs_new_fs_image_inO and preserve inode numbers
|
||||
from session to session.
|
||||
*/
|
||||
#define Libisofs_hardlink_prooF yes
|
||||
|
||||
|
||||
/* Experiment: Ignore PX inode numbers,
|
||||
have boot image inode number counted by fs_give_ino_number()
|
||||
*/
|
||||
#define Libisofs_new_fs_image_inO yes
|
||||
|
||||
|
||||
|
||||
/* Experiment: Revoke Ticket 144, use data file LBAs again.
|
||||
(will work only if not Libisofs_new_fs_image_inO)
|
||||
#define Libisofs_ino_from_lbA yes
|
||||
Overridden if Libisofs_hardlink_prooF is defined.
|
||||
#define Libisofs_new_fs_image_inO yes
|
||||
*/
|
||||
|
||||
|
||||
@ -5288,12 +5455,5 @@ struct burn_source {
|
||||
*/
|
||||
|
||||
|
||||
/* Experiment: Use iso_iconv*() wrappers.
|
||||
They can print errno messages and they
|
||||
can avoid iconv() if the identical mapping is desired.
|
||||
One could install own simple conversion capabilities.
|
||||
*/
|
||||
#define Libisofs_with_iso_iconV yes
|
||||
|
||||
|
||||
#endif /*LIBISO_LIBISOFS_H_*/
|
||||
|
@ -65,12 +65,9 @@ struct libiso_msgs *libiso_msgr = NULL;
|
||||
int iso_init_with_flag(int flag)
|
||||
{
|
||||
|
||||
#ifdef Libisofs_setlocale_in_iniT
|
||||
if (! (flag & 1)) {
|
||||
iso_init_locale(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (libiso_msgr == NULL) {
|
||||
if (libiso_msgs_new(&libiso_msgr, 0) <= 0)
|
||||
return ISO_FATAL_ERROR;
|
||||
|
336
libisofs/node.c
336
libisofs/node.c
@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include "libisofs.h"
|
||||
#include "image.h"
|
||||
#include "node.h"
|
||||
#include "stream.h"
|
||||
#include "aaip_0_2.h"
|
||||
@ -1308,6 +1309,13 @@ int iso_node_new_symlink(char *name, char *dest, IsoSymlink **link)
|
||||
new->node.name = name;
|
||||
new->dest = dest;
|
||||
new->node.mode = S_IFLNK;
|
||||
|
||||
#ifdef Libisofs_hardlink_matcheR
|
||||
new->fs_id = 0;
|
||||
new->st_dev = 0;
|
||||
new->st_ino = 0;
|
||||
#endif
|
||||
|
||||
*link = new;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
@ -1340,6 +1348,12 @@ int iso_node_new_special(char *name, mode_t mode, dev_t dev,
|
||||
new->node.mode = mode;
|
||||
new->dev = dev;
|
||||
|
||||
#ifdef Libisofs_hardlink_matcheR
|
||||
new->fs_id = 0;
|
||||
new->st_dev = 0;
|
||||
new->st_ino = 0;
|
||||
#endif
|
||||
|
||||
*special = new;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
@ -2239,3 +2253,325 @@ int iso_node_zf_by_magic(IsoNode *node, int flag)
|
||||
return total_ret;
|
||||
}
|
||||
|
||||
|
||||
int iso_px_ino_xinfo_func(void *data, int flag)
|
||||
{
|
||||
if (flag == 1) {
|
||||
free(data);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @param flag
|
||||
* bit0= do only retrieve id if node is in imported ISO image
|
||||
* or has an explicit xinfo inode number
|
||||
* @return
|
||||
* 1= reply is valid from stream, 2= reply is valid from xinfo
|
||||
* 0= no id available, <0= error
|
||||
* (fs_id, dev_id, ino_id) will be (0,0,0) in case of return <= 0
|
||||
*/
|
||||
int iso_node_get_id(IsoNode *node, unsigned int *fs_id, dev_t *dev_id,
|
||||
ino_t *ino_id, int flag)
|
||||
{
|
||||
int ret;
|
||||
IsoFile *file;
|
||||
IsoSymlink *symlink;
|
||||
IsoSpecial *special;
|
||||
void *xipt;
|
||||
|
||||
ret = iso_node_get_xinfo(node, iso_px_ino_xinfo_func, &xipt);
|
||||
if (ret < 0)
|
||||
goto no_id;
|
||||
if (ret == 1) {
|
||||
*fs_id = ISO_IMAGE_FS_ID;
|
||||
*dev_id = 0;
|
||||
*ino_id = *((ino_t *) xipt);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (node->type == LIBISO_FILE) {
|
||||
file= (IsoFile *) node;
|
||||
iso_stream_get_id(file->stream, fs_id, dev_id, ino_id);
|
||||
if (*fs_id != ISO_IMAGE_FS_ID && (flag & 1)) {
|
||||
ret = 0;
|
||||
goto no_id;
|
||||
}
|
||||
return 1;
|
||||
|
||||
#ifdef Libisofs_hardlink_matcheR
|
||||
|
||||
} else if (node->type == LIBISO_SYMLINK) {
|
||||
symlink = (IsoSymlink *) node;
|
||||
if (symlink->fs_id != ISO_IMAGE_FS_ID && (flag & 1)) {
|
||||
ret = 0;
|
||||
goto no_id;
|
||||
}
|
||||
*fs_id = symlink->fs_id;
|
||||
*dev_id = symlink->st_dev;
|
||||
*ino_id = symlink->st_ino;
|
||||
return 1;
|
||||
|
||||
} else if (node->type == LIBISO_SPECIAL) {
|
||||
special = (IsoSpecial *) node;
|
||||
if (special->fs_id != ISO_IMAGE_FS_ID && (flag & 1)) {
|
||||
ret = 0;
|
||||
goto no_id;
|
||||
}
|
||||
*fs_id = special->fs_id;
|
||||
*dev_id = special->st_dev;
|
||||
*ino_id = special->st_ino;
|
||||
return 1;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
no_id:;
|
||||
*fs_id = 0;
|
||||
*dev_id = 0;
|
||||
*ino_id = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int iso_node_set_ino_xinfo(IsoNode *node, ino_t ino, int flag)
|
||||
{
|
||||
int ret;
|
||||
void *xipt;
|
||||
|
||||
if (flag & 1) {
|
||||
ret = iso_node_remove_xinfo(node, iso_px_ino_xinfo_func);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
xipt = calloc(1, sizeof(ino_t));
|
||||
if (xipt == NULL)
|
||||
return ISO_OUT_OF_MEM;
|
||||
memcpy(xipt, &ino, sizeof(ino_t));
|
||||
ret = iso_node_add_xinfo(node, iso_px_ino_xinfo_func, xipt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int iso_node_set_ino(IsoNode *node, ino_t ino, int flag)
|
||||
{
|
||||
int ret;
|
||||
IsoFile *file;
|
||||
IsoSymlink *symlink;
|
||||
IsoSpecial *special;
|
||||
void *xipt;
|
||||
|
||||
ret = iso_node_get_xinfo(node, iso_px_ino_xinfo_func, &xipt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret == 1) {
|
||||
ret = iso_node_set_ino_xinfo(node, ino, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return 2;
|
||||
}
|
||||
if (node->type == LIBISO_FILE) {
|
||||
file= (IsoFile *) node;
|
||||
ret = iso_stream_set_image_ino(file->stream, ino, 0);
|
||||
if (ret < 0 || ret == 1)
|
||||
return ret;
|
||||
|
||||
#ifdef Libisofs_hardlink_matcheR
|
||||
|
||||
} else if (node->type == LIBISO_SYMLINK) {
|
||||
symlink = (IsoSymlink *) node;
|
||||
if (symlink->fs_id == ISO_IMAGE_FS_ID) {
|
||||
symlink->st_ino = ino;
|
||||
return 1;
|
||||
}
|
||||
|
||||
} else if (node->type == LIBISO_SPECIAL) {
|
||||
special = (IsoSpecial *) node;
|
||||
if (special->fs_id == ISO_IMAGE_FS_ID) {
|
||||
special->st_ino = ino;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
ret = iso_node_set_ino_xinfo(node, ino, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
int iso_node_set_unique_id(IsoNode *node, IsoImage *image, int flag)
|
||||
{
|
||||
int ret;
|
||||
ino_t ino;
|
||||
|
||||
ino = img_give_ino_number(image, 0);
|
||||
ret = iso_node_set_ino(node, ino, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note to programmers: It is crucial not to break the following constraints.
|
||||
* Anti-symmetry: cmp(X,Y) == - cmp(Y,X)
|
||||
* Transitivity : if cmp(A,B) < 0 && cmp(B,C) < 0 then cmp(A,C) < 0
|
||||
* if cmp(A,B) == 0 && cmp(B,C) == 0 then cmp(A,C) == 0
|
||||
* A big transitivity hazard are tests which do not apply to some nodes.
|
||||
* In this case for any A that is applicable and any B that is not applicable
|
||||
* the comparison must have the same non-zero result. I.e. a pair of applicable
|
||||
* and non-applicable node must return that non-zero result before the test
|
||||
* for a pair of applicable nodes would happen.
|
||||
*
|
||||
* @param flag
|
||||
* bit0= compare stat properties and attributes
|
||||
* bit1= treat all nodes with image ino == 0 as unique
|
||||
*/
|
||||
int iso_node_cmp_flag(IsoNode *n1, IsoNode *n2, int flag)
|
||||
{
|
||||
int ret1, ret2;
|
||||
unsigned int fs_id1, fs_id2;
|
||||
dev_t dev_id1, dev_id2;
|
||||
ino_t ino_id1, ino_id2;
|
||||
IsoFile *f1 = NULL, *f2 = NULL;
|
||||
IsoSymlink *l1 = NULL, *l2 = NULL;
|
||||
IsoSpecial *s1 = NULL, *s2 = NULL;
|
||||
void *x1, *x2;
|
||||
|
||||
if (n1 == n2)
|
||||
return 0;
|
||||
if (n1->type != n2->type)
|
||||
return (n1->type < n2->type ? -1 : 1);
|
||||
|
||||
/* Imported or explicite ISO image node id has priority */
|
||||
ret1 = (iso_node_get_id(n1, &fs_id1, &dev_id1, &ino_id1, 1) > 0);
|
||||
ret2 = (iso_node_get_id(n2, &fs_id2, &dev_id2, &ino_id2, 1) > 0);
|
||||
if (ret1 != ret2)
|
||||
return (ret1 < ret2 ? -1 : 1);
|
||||
if (ret1) {
|
||||
/* fs_id and dev_id do not matter here.
|
||||
Both nodes have explicit inode numbers of the emerging image.
|
||||
*/
|
||||
if (ino_id1 != ino_id2)
|
||||
return (ino_id1 < ino_id2 ? -1 : 1);
|
||||
if (ino_id1 == 0) /* Image ino 0 is always unique */
|
||||
return (n1 < n2 ? -1 : 1);
|
||||
goto image_inode_match;
|
||||
}
|
||||
|
||||
if (n1->type == LIBISO_FILE) {
|
||||
|
||||
f1 = (IsoFile *) n1;
|
||||
f2 = (IsoFile *) n2;
|
||||
ret1 = iso_stream_cmp_ino(f1->stream, f2->stream, 0);
|
||||
if (ret1)
|
||||
return ret1;
|
||||
goto inode_match;
|
||||
|
||||
#ifdef Libisofs_hardlink_matcheR
|
||||
|
||||
} else if (n1->type == LIBISO_SYMLINK) {
|
||||
|
||||
l1 = (IsoSymlink *) n1;
|
||||
l2 = (IsoSymlink *) n2;
|
||||
fs_id1 = l1->fs_id;
|
||||
dev_id1 = l1->st_dev;
|
||||
ino_id1 = l1->st_ino;
|
||||
fs_id2 = l2->fs_id;
|
||||
dev_id2 = l2->st_dev;
|
||||
ino_id2 = l2->st_ino;
|
||||
|
||||
} else if (n1->type == LIBISO_SPECIAL) {
|
||||
|
||||
s1 = (IsoSpecial *) n1;
|
||||
s2 = (IsoSpecial *) n2;
|
||||
fs_id1 = s1->fs_id;
|
||||
dev_id1 = s1->st_dev;
|
||||
ino_id1 = s1->st_ino;
|
||||
fs_id2 = s2->fs_id;
|
||||
dev_id2 = s2->st_dev;
|
||||
ino_id2 = s2->st_ino;
|
||||
|
||||
#endif /* Libisofs_hardlink_matcheR */
|
||||
|
||||
} else {
|
||||
return (n1 < n2 ? -1 : 1); /* case n1 == n2 is handled above */
|
||||
}
|
||||
if (fs_id1 != fs_id2)
|
||||
return (fs_id1 < fs_id2 ? -1 : 1);
|
||||
if (dev_id1 != dev_id2)
|
||||
return (dev_id1 < dev_id2 ? -1 : 1);
|
||||
if (ino_id1 != ino_id2)
|
||||
return (ino_id1 < ino_id2 ? -1 : 1);
|
||||
if (fs_id1 == 0 && dev_id1 == 0 && ino_id1 == 0)
|
||||
return (n1 < n2 ? -1 : 1);
|
||||
|
||||
inode_match:;
|
||||
|
||||
if (flag & 2) {
|
||||
/* What comes here has no predefined image ino resp. image_ino == 0 .
|
||||
Regard this as not equal.
|
||||
*/
|
||||
return (n1 < n2 ? -1 : 1);
|
||||
}
|
||||
|
||||
image_inode_match:;
|
||||
|
||||
if (!(flag & 1))
|
||||
return 0;
|
||||
if (n1->type == LIBISO_SYMLINK) {
|
||||
l1 = (IsoSymlink *) n1;
|
||||
l2 = (IsoSymlink *) n2;
|
||||
ret1 = strcmp(l1->dest, l2->dest);
|
||||
if (ret1)
|
||||
return ret1;
|
||||
} else if (n1->type == LIBISO_SPECIAL) {
|
||||
s1 = (IsoSpecial *) n1;
|
||||
s2 = (IsoSpecial *) n2;
|
||||
if (s1->dev != s2->dev)
|
||||
return (s1->dev < s2->dev ? -1 : 1);
|
||||
}
|
||||
|
||||
if (n1->mode != n2->mode)
|
||||
return (n1->mode < n2->mode ? -1 : 1);
|
||||
if (n1->uid != n2->uid)
|
||||
return (n1->uid < n2->uid ? -1 : 1);
|
||||
if (n1->gid != n2->gid)
|
||||
return (n1->gid < n2->gid ? -1 : 1);
|
||||
if (n1->atime != n2->atime)
|
||||
return (n1->atime < n2->atime ? -1 : 1);
|
||||
if (n1->mtime != n2->mtime)
|
||||
return (n1->mtime < n2->mtime ? -1 : 1);
|
||||
if (n1->ctime != n2->ctime)
|
||||
return (n1->ctime < n2->ctime ? -1 : 1);
|
||||
|
||||
/* Compare xinfo */
|
||||
/* :( cannot compare general xinfo because data length is not known :( */
|
||||
|
||||
/* compare aa_string */
|
||||
ret1 = iso_node_get_xinfo(n1, aaip_xinfo_func, &x1);
|
||||
ret2 = iso_node_get_xinfo(n2, aaip_xinfo_func, &x2);
|
||||
if (ret1 != ret2)
|
||||
return (ret1 < ret2 ? -1 : 1);
|
||||
if (ret1 == 1) {
|
||||
ret1 = aaip_count_bytes((unsigned char *) x1, 0);
|
||||
ret2 = aaip_count_bytes((unsigned char *) x2, 0);
|
||||
if (ret1 != ret2)
|
||||
return (ret1 < ret2 ? -1 : 1);
|
||||
ret1 = memcmp(x1, x2, ret1);
|
||||
if (ret1)
|
||||
return ret1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* API */
|
||||
int iso_node_cmp_ino(IsoNode *n1, IsoNode *n2, int flag)
|
||||
{
|
||||
return iso_node_cmp_flag(n1, n2, 1);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
@ -122,7 +123,7 @@ struct Iso_File
|
||||
* Higher weighting files are written at the beginning of image
|
||||
*/
|
||||
int sort_weight;
|
||||
IsoStream *stream;
|
||||
IsoStream *stream; /* Knows fs_id, st_dev, and st_ino */
|
||||
};
|
||||
|
||||
struct Iso_Symlink
|
||||
@ -130,12 +131,34 @@ struct Iso_Symlink
|
||||
IsoNode node;
|
||||
|
||||
char *dest;
|
||||
|
||||
#ifdef Libisofs_hardlink_matcheR
|
||||
/* If the IsoNode represents an object in an existing filesystem then
|
||||
the following three numbers should unique identify it.
|
||||
(0,0,0) will always be taken as unique.
|
||||
*/
|
||||
unsigned int fs_id;
|
||||
dev_t st_dev;
|
||||
ino_t st_ino;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
struct Iso_Special
|
||||
{
|
||||
IsoNode node;
|
||||
dev_t dev;
|
||||
|
||||
#ifdef Libisofs_hardlink_matcheR
|
||||
/* If the IsoNode represents an object in an existing filesystem then
|
||||
the following three numbers should unique identify it.
|
||||
(0,0,0) will always be taken as unique.
|
||||
*/
|
||||
unsigned int fs_id;
|
||||
dev_t st_dev;
|
||||
ino_t st_ino;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
struct iso_dir_iter_iface
|
||||
@ -398,5 +421,34 @@ struct zisofs_zf_info {
|
||||
*/
|
||||
int iso_file_zf_by_magic(IsoFile *file, int flag);
|
||||
|
||||
/*
|
||||
* @param flag
|
||||
* bit0= do only retrieve id if node is in imported ISO image
|
||||
* or has an explicit xinfo inode number
|
||||
* @return
|
||||
* 1= reply is valid from stream, 2= reply is valid from xinfo
|
||||
* 0= no id available, <0= error
|
||||
* (fs_id, dev_id, ino_id) will be (0,0,0) in case of return <= 0
|
||||
*/
|
||||
int iso_node_get_id(IsoNode *node, unsigned int *fs_id, dev_t *dev_id,
|
||||
ino_t *ino_id, int flag);
|
||||
|
||||
/* Set a new unique inode ISO image number to the given node.
|
||||
* This number shall eventually persist during image generation.
|
||||
*/
|
||||
int iso_node_set_unique_id(IsoNode *node, IsoImage *image, int flag);
|
||||
|
||||
/* Use this with extreme care. Duplicate inode numbers will indicate hardlink
|
||||
* relationship between the nodes.
|
||||
*/
|
||||
int iso_node_set_ino(IsoNode *node, ino_t ino, int flag);
|
||||
|
||||
/*
|
||||
* @param flag
|
||||
* bit0= compare stat properties and attributes
|
||||
* bit1= treat all nodes with image ino == 0 as unique
|
||||
* (those with 0,0,0 are treated as unique anyway)
|
||||
*/
|
||||
int iso_node_cmp_flag(IsoNode *n1, IsoNode *n2, int flag);
|
||||
|
||||
#endif /*LIBISO_NODE_H_*/
|
||||
|
@ -102,7 +102,7 @@ int rrip_add_PX(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp)
|
||||
|
||||
PX[0] = 'P';
|
||||
PX[1] = 'X';
|
||||
if (!t->rrip_version_1_10) {
|
||||
if (t->rrip_1_10_px_ino || !t->rrip_version_1_10 ) {
|
||||
PX[2] = 44;
|
||||
} else {
|
||||
PX[2] = 36;
|
||||
@ -112,7 +112,7 @@ int rrip_add_PX(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp)
|
||||
iso_bb(&PX[12], n->nlink, 4);
|
||||
iso_bb(&PX[20], px_get_uid(t, n), 4);
|
||||
iso_bb(&PX[28], px_get_gid(t, n), 4);
|
||||
if (!t->rrip_version_1_10) {
|
||||
if (t->rrip_1_10_px_ino || !t->rrip_version_1_10) {
|
||||
iso_bb(&PX[36], n->ino, 4);
|
||||
}
|
||||
|
||||
@ -662,9 +662,6 @@ int aaip_add_ER(Ecma119Image *t, struct susp_info *susp, int flag)
|
||||
ER[5] = 81;
|
||||
ER[6] = 62;
|
||||
ER[7] = 1;
|
||||
|
||||
#ifdef Libisofs_aaip_2_0
|
||||
|
||||
memcpy(ER + 8, "AAIP_0200", 9);
|
||||
memcpy(ER + 17,
|
||||
"AL PROVIDES VIA AAIP 2.0 SUPPORT FOR ARBITRARY FILE ATTRIBUTES"
|
||||
@ -673,18 +670,6 @@ int aaip_add_ER(Ecma119Image *t, struct susp_info *susp, int flag)
|
||||
"PLEASE CONTACT THE LIBBURNIA PROJECT VIA LIBBURNIA-PROJECT.ORG",
|
||||
62);
|
||||
|
||||
#else /* Libisofs_aaip_2_0 */
|
||||
|
||||
memcpy(ER + 8, "AAIP_0100", 9);
|
||||
memcpy(ER + 17,
|
||||
"AA PROVIDES VIA AAIP 1.0 SUPPORT FOR ARBITRARY FILE ATTRIBUTES"
|
||||
" IN ISO 9660 IMAGES", 81);
|
||||
memcpy(ER + 98,
|
||||
"PLEASE CONTACT THE LIBBURNIA PROJECT VIA LIBBURNIA-PROJECT.ORG",
|
||||
62);
|
||||
|
||||
#endif /* ! Libisofs_aaip_2_0 */
|
||||
|
||||
/** This always goes to continuation area */
|
||||
return susp_append_ce(t, susp, ER);
|
||||
}
|
||||
@ -1144,7 +1129,7 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t space,
|
||||
#endif
|
||||
|
||||
/* PX and TF, we are sure they always fit in SUA */
|
||||
if (!t->rrip_version_1_10) {
|
||||
if (t->rrip_1_10_px_ino || !t->rrip_version_1_10) {
|
||||
su_size += 44 + 26;
|
||||
} else {
|
||||
su_size += 36 + 26;
|
||||
|
@ -263,7 +263,9 @@ void susp_iter_free(SuspIterator *iter);
|
||||
* Fills a struct stat with the values of a Rock Ridge PX entry (RRIP, 4.1.1).
|
||||
*
|
||||
* @return
|
||||
* 1 on success, < 0 on error
|
||||
* < 0 on error
|
||||
* 1 on success with no inode number,
|
||||
* 2 on success with inode number,
|
||||
*/
|
||||
int read_rr_PX(struct susp_sys_user_entry *px, struct stat *st);
|
||||
|
||||
|
@ -169,11 +169,14 @@ int read_rr_PX(struct susp_sys_user_entry *px, struct stat *st)
|
||||
st->st_nlink = iso_read_bb(px->data.PX.links, 4, NULL);
|
||||
st->st_uid = iso_read_bb(px->data.PX.uid, 4, NULL);
|
||||
st->st_gid = iso_read_bb(px->data.PX.gid, 4, NULL);
|
||||
st->st_ino = 0;
|
||||
if (px->len_sue[0] == 44) {
|
||||
/* this corresponds to RRIP 1.12, so we have inode serial number */
|
||||
st->st_ino = iso_read_bb(px->data.PX.serial, 4, NULL);
|
||||
/* Indicate that st_ino is valid */
|
||||
return 2;
|
||||
}
|
||||
return ISO_SUCCESS;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -492,26 +495,14 @@ int read_aaip_AA(struct susp_sys_user_entry *sue,
|
||||
aapt = *aa_string + *aa_len;
|
||||
|
||||
aapt[0] = 'A';
|
||||
|
||||
#ifdef Libisofs_aaip_2_0
|
||||
aapt[1] = 'L';
|
||||
#else /* Libisofs_aaip_2_0 */
|
||||
aapt[1] = 'A';
|
||||
#endif /* ! Libisofs_aaip_2_0 */
|
||||
|
||||
aapt[2] = sue->len_sue[0];
|
||||
aapt[3] = 1;
|
||||
aapt[4] = 0;
|
||||
/* Append sue payload */
|
||||
|
||||
#ifdef Libisofs_aaip_2_0
|
||||
/* Append sue payload */
|
||||
memcpy(aapt + 5, sue->data.AL.comps, sue->len_sue[0] - 5);
|
||||
*is_done = !(sue->data.AL.flags[0] & 1);
|
||||
#else /* Libisofs_aaip_2_0 */
|
||||
memcpy(aapt + 5, sue->data.AA.comps, sue->len_sue[0] - 5);
|
||||
*is_done = !(sue->data.AA.flags[0] & 1);
|
||||
#endif /* ! Libisofs_aaip_2_0 */
|
||||
|
||||
*aa_len += sue->len_sue[0];
|
||||
|
||||
return ISO_SUCCESS;
|
||||
@ -554,26 +545,14 @@ int read_aaip_AL(struct susp_sys_user_entry *sue,
|
||||
aapt = *aa_string + *aa_len;
|
||||
|
||||
aapt[0] = 'A';
|
||||
|
||||
#ifdef Libisofs_aaip_2_0
|
||||
aapt[1] = 'L';
|
||||
#else /* Libisofs_aaip_2_0 */
|
||||
aapt[1] = 'A';
|
||||
#endif /* ! Libisofs_aaip_2_0 */
|
||||
|
||||
aapt[2] = sue->len_sue[0];
|
||||
aapt[3] = 1;
|
||||
aapt[4] = 0;
|
||||
/* Append sue payload */
|
||||
|
||||
#ifdef Libisofs_aaip_2_0
|
||||
/* Append sue payload */
|
||||
memcpy(aapt + 5, sue->data.AL.comps, sue->len_sue[0] - 5);
|
||||
*is_done = !(sue->data.AL.flags[0] & 1);
|
||||
#else /* Libisofs_aaip_2_0 */
|
||||
memcpy(aapt + 5, sue->data.AA.comps, sue->len_sue[0] - 5);
|
||||
*is_done = !(sue->data.AA.flags[0] & 1);
|
||||
#endif /* ! Libisofs_aaip_2_0 */
|
||||
|
||||
*aa_len += sue->len_sue[0];
|
||||
|
||||
return ISO_SUCCESS;
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
@ -672,8 +673,12 @@ void iso_stream_get_file_name(IsoStream *stream, char *name)
|
||||
|
||||
IsoStream *iso_stream_get_input_stream(IsoStream *stream, int flag)
|
||||
{
|
||||
IsoStreamIface* class = stream->class;
|
||||
IsoStreamIface* class;
|
||||
|
||||
if (stream == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
class = stream->class;
|
||||
if (class->version < 2)
|
||||
return NULL;
|
||||
return class->get_input_stream(stream, 0);
|
||||
@ -709,3 +714,119 @@ ex:;
|
||||
return path;
|
||||
}
|
||||
|
||||
/* @return 1 = ok , 0 = not an ISO image stream , <0 = error */
|
||||
int iso_stream_set_image_ino(IsoStream *stream, ino_t ino, int flag)
|
||||
{
|
||||
if (stream == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
if (stream->class == &fsrc_stream_class) {
|
||||
FSrcStreamData *fsrc_data = stream->data;
|
||||
fsrc_data->ino_id = ino;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* API */
|
||||
int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, int flag)
|
||||
{
|
||||
int ret;
|
||||
unsigned int fs_id1, fs_id2;
|
||||
dev_t dev_id1, dev_id2;
|
||||
ino_t ino_id1, ino_id2;
|
||||
off_t size1, size2;
|
||||
FSrcStreamData *fssd1, *fssd2;
|
||||
|
||||
|
||||
/* <<<
|
||||
#define Libisofs_stream_cmp_ino_debuG 1
|
||||
*/
|
||||
#ifdef Libisofs_stream_cmp_ino_debuG
|
||||
static int report_counter = 0;
|
||||
static int debug = 1;
|
||||
#endif /* Libisofs_stream_cmp_ino_debuG */
|
||||
|
||||
if (s1 == s2)
|
||||
return 0;
|
||||
if (s1 == NULL)
|
||||
return -1;
|
||||
if (s2 == NULL)
|
||||
return 1;
|
||||
|
||||
if (s1->class->version >= 3 && !(flag & 1)) {
|
||||
/* Filters may have smarter methods to compare themselves with others */
|
||||
ret = s1->class->cmp_ino(s1, s2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
iso_stream_get_id(s1, &fs_id1, &dev_id1, &ino_id1);
|
||||
iso_stream_get_id(s2, &fs_id2, &dev_id2, &ino_id2);
|
||||
if (fs_id1 < fs_id2) {
|
||||
return -1;
|
||||
} else if (fs_id1 > fs_id2) {
|
||||
return 1;
|
||||
}
|
||||
/* files belong to the same fs */
|
||||
if (dev_id1 > dev_id2) {
|
||||
return -1;
|
||||
} else if (dev_id1 < dev_id2) {
|
||||
return 1;
|
||||
} else if (ino_id1 < ino_id2) {
|
||||
return -1;
|
||||
} else if (ino_id1 > ino_id2) {
|
||||
return 1;
|
||||
}
|
||||
size1 = iso_stream_get_size(s1);
|
||||
size2 = iso_stream_get_size(s2);
|
||||
if (size1 < size2) {
|
||||
|
||||
#ifdef Libisofs_stream_cmp_ino_debuG
|
||||
if (debug) {
|
||||
if (report_counter < 5)
|
||||
fprintf(stderr,
|
||||
"\n\nlibisofs_DEBUG : Program error: same ino but differing size\n\n\n");
|
||||
else if (report_counter == 5)
|
||||
fprintf(stderr,
|
||||
"\n\nlibisofs_DEBUG : Inode error: more of same ino but differing size\n\n\n");
|
||||
report_counter++;
|
||||
}
|
||||
#endif /* Libisofs_stream_cmp_ino_debuG */
|
||||
|
||||
return -1;
|
||||
} else if (size1 > size2) {
|
||||
|
||||
#ifdef Libisofs_stream_cmp_ino_debuG
|
||||
if (debug) {
|
||||
if (report_counter < 5)
|
||||
fprintf(stderr,
|
||||
"\n\nlibisofs_DEBUG : Inode error: same ino but differing size\n\n\n");
|
||||
else if (report_counter == 5)
|
||||
fprintf(stderr,
|
||||
"\n\nlibisofs_DEBUG : Program error: more of same ino but differing size\n\n\n");
|
||||
report_counter++;
|
||||
}
|
||||
#endif /* Libisofs_stream_cmp_ino_debuG */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (s1->class != s2->class)
|
||||
return (s1->class < s2->class ? -1 : 1);
|
||||
if (s1->class == &fsrc_stream_class) {
|
||||
/* Compare eventual image data section LBA and sizes */
|
||||
fssd1= (FSrcStreamData *) s1->data;
|
||||
fssd2= (FSrcStreamData *) s2->data;
|
||||
ret = iso_ifs_sections_cmp(fssd1->src, fssd2->src, 0);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_hardlink_matcheR
|
||||
if (fs_id1 == 0 && dev_id1 == 0 && ino_id1 == 0) {
|
||||
return (s1 < s2 ? -1 : 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2009 Thomas Schmitt
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
@ -74,4 +75,12 @@ int iso_stream_get_src_zf(IsoStream *stream, int *header_size_div4,
|
||||
int *block_size_log2, uint32_t *uncompressed_size,
|
||||
int flag);
|
||||
|
||||
/**
|
||||
* Set the inode number of a stream that is based on FSrcStreamData, i.e.
|
||||
* stems from the imported ISO image.
|
||||
* @return 1 = ok , 0 = not an ISO image stream , <0 = error
|
||||
*/
|
||||
int iso_stream_set_image_ino(IsoStream *stream, ino_t ino, int flag);
|
||||
|
||||
|
||||
#endif /*STREAM_H_*/
|
||||
|
180
libisofs/util.c
180
libisofs/util.c
@ -32,9 +32,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
|
||||
|
||||
/* Produce possibly inflationary error messages directly to stderr */
|
||||
static int iso_iconv_debug = 0;
|
||||
|
||||
@ -141,8 +138,6 @@ int iso_iconv_close(struct iso_iconv_handle *handle, int flag)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_iso_iconV */
|
||||
|
||||
|
||||
int int_pow(int base, int power)
|
||||
{
|
||||
@ -183,13 +178,8 @@ int strconv(const char *str, const char *icharset, const char *ocharset,
|
||||
size_t inbytes;
|
||||
size_t outbytes;
|
||||
size_t n;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret;
|
||||
#else
|
||||
iconv_t conv;
|
||||
#endif
|
||||
|
||||
char *out = NULL;
|
||||
char *src;
|
||||
@ -204,43 +194,22 @@ int strconv(const char *str, const char *icharset, const char *ocharset,
|
||||
goto ex;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
conv_ret = iso_iconv_open(&conv, (char *) ocharset, (char *) icharset, 0);
|
||||
if (conv_ret <= 0) {
|
||||
#else
|
||||
conv = iconv_open(ocharset, icharset);
|
||||
if (conv == (iconv_t)(-1)) {
|
||||
#endif
|
||||
|
||||
retval = ISO_CHARSET_CONV_ERROR;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
src = (char *)str;
|
||||
ret = (char *)out;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
if (n == -1) {
|
||||
/* error */
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
if (n == -1) {
|
||||
/* error */
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
retval = ISO_CHARSET_CONV_ERROR;
|
||||
goto ex;
|
||||
}
|
||||
*ret = '\0';
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
*output = malloc(ret - out + 1);
|
||||
if (*output == NULL) {
|
||||
@ -261,14 +230,8 @@ int strnconv(const char *str, const char *icharset, const char *ocharset,
|
||||
size_t inbytes;
|
||||
size_t outbytes;
|
||||
size_t n;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret;
|
||||
#else
|
||||
iconv_t conv;
|
||||
#endif
|
||||
|
||||
char *out = NULL;
|
||||
char *src;
|
||||
char *ret;
|
||||
@ -281,43 +244,22 @@ int strnconv(const char *str, const char *icharset, const char *ocharset,
|
||||
retval = ISO_OUT_OF_MEM;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
conv_ret = iso_iconv_open(&conv, (char *) ocharset, (char *) icharset, 0);
|
||||
if (conv_ret <= 0) {
|
||||
#else
|
||||
conv = iconv_open(ocharset, icharset);
|
||||
if (conv == (iconv_t)(-1)) {
|
||||
#endif
|
||||
|
||||
retval = ISO_CHARSET_CONV_ERROR;
|
||||
goto ex;
|
||||
}
|
||||
src = (char *)str;
|
||||
ret = (char *)out;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
if (n == -1) {
|
||||
/* error */
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
if (n == -1) {
|
||||
/* error */
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
retval = ISO_CHARSET_CONV_ERROR;
|
||||
goto ex;
|
||||
}
|
||||
*ret = '\0';
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
*output = malloc(ret - out + 1);
|
||||
if (*output == NULL) {
|
||||
@ -342,13 +284,8 @@ ex:;
|
||||
static
|
||||
int str2wchar(const char *icharset, const char *input, wchar_t **output)
|
||||
{
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret;
|
||||
#else
|
||||
iconv_t conv;
|
||||
#endif
|
||||
|
||||
/* That while loop smells like a potential show stopper */
|
||||
size_t loop_counter = 0, loop_limit = 3;
|
||||
@ -364,15 +301,8 @@ int str2wchar(const char *icharset, const char *input, wchar_t **output)
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
conv_ret = iso_iconv_open(&conv, "WCHAR_T", (char *) icharset, 0);
|
||||
if (conv_ret <= 0) {
|
||||
#else
|
||||
conv = iconv_open("WCHAR_T", icharset);
|
||||
if (conv == (iconv_t)-1) {
|
||||
#endif
|
||||
|
||||
return ISO_CHARSET_CONV_ERROR;
|
||||
}
|
||||
|
||||
@ -388,13 +318,7 @@ int str2wchar(const char *icharset, const char *input, wchar_t **output)
|
||||
ret = (char *)wstr;
|
||||
src = (char *)input;
|
||||
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
#endif
|
||||
|
||||
while (n == -1) {
|
||||
|
||||
if (errno == E2BIG) {
|
||||
@ -424,34 +348,16 @@ int str2wchar(const char *icharset, const char *input, wchar_t **output)
|
||||
loop_counter++;
|
||||
if (loop_counter > loop_limit)
|
||||
goto conv_error;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
*( (wchar_t *)ret )='\0';
|
||||
*output = wstr;
|
||||
return ISO_SUCCESS;
|
||||
|
||||
conv_error:;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
free(wstr);
|
||||
return ISO_CHARSET_CONV_ERROR;
|
||||
}
|
||||
@ -463,13 +369,8 @@ int str2ascii(const char *icharset, const char *input, char **output)
|
||||
char *ret;
|
||||
char *ret_;
|
||||
char *src;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret;
|
||||
#else
|
||||
iconv_t conv;
|
||||
#endif
|
||||
|
||||
/* That while loop smells like a potential show stopper */
|
||||
size_t loop_counter = 0, loop_limit = 3;
|
||||
@ -509,27 +410,14 @@ int str2ascii(const char *icharset, const char *input, char **output)
|
||||
ret = ret_;
|
||||
|
||||
/* initialize iconv */
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
conv_ret = iso_iconv_open(&conv, "ASCII", "WCHAR_T", 0);
|
||||
if (conv_ret <= 0) {
|
||||
#else
|
||||
conv = iconv_open("ASCII", "WCHAR_T");
|
||||
if (conv == (iconv_t)-1) {
|
||||
#endif
|
||||
|
||||
free(wsrc_);
|
||||
free(ret_);
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
#endif
|
||||
|
||||
while (n == -1) {
|
||||
/* The destination buffer is too small. Stops here. */
|
||||
if (errno == E2BIG)
|
||||
@ -563,21 +451,9 @@ int str2ascii(const char *icharset, const char *input, char **output)
|
||||
loop_counter++;
|
||||
if (loop_counter > loop_limit)
|
||||
break;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
*ret='\0';
|
||||
free(wsrc_);
|
||||
|
||||
@ -628,13 +504,8 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
|
||||
char *src;
|
||||
char *ret;
|
||||
char *ret_;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret;
|
||||
#else
|
||||
iconv_t conv;
|
||||
#endif
|
||||
|
||||
/* That while loop smells like a potential show stopper */
|
||||
size_t loop_counter = 0, loop_limit = 3;
|
||||
@ -670,27 +541,14 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
|
||||
ret = ret_;
|
||||
|
||||
/* initialize iconv */
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
conv_ret = iso_iconv_open(&conv, "UCS-2BE", "WCHAR_T", 0);
|
||||
if (conv_ret <= 0) {
|
||||
#else
|
||||
conv = iconv_open("UCS-2BE", "WCHAR_T");
|
||||
if (conv == (iconv_t)-1) {
|
||||
#endif
|
||||
|
||||
free(wsrc_);
|
||||
free(ret_);
|
||||
return ISO_CHARSET_CONV_ERROR;
|
||||
}
|
||||
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
#endif
|
||||
|
||||
while (n == -1) {
|
||||
/* The destination buffer is too small. Stops here. */
|
||||
if (errno == E2BIG)
|
||||
@ -724,20 +582,9 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
|
||||
loop_counter++;
|
||||
if (loop_counter > loop_limit)
|
||||
break;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
/* close the ucs string */
|
||||
set_ucsbe((uint16_t*) ret, '\0');
|
||||
@ -1566,14 +1413,8 @@ char *ucs2str(const char *buf, size_t len)
|
||||
{
|
||||
size_t outbytes, inbytes;
|
||||
char *str, *src, *out = NULL, *retval = NULL;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret;
|
||||
#else
|
||||
iconv_t conv;
|
||||
#endif
|
||||
|
||||
size_t n;
|
||||
|
||||
inbytes = len;
|
||||
@ -1584,36 +1425,15 @@ char *ucs2str(const char *buf, size_t len)
|
||||
out = calloc(outbytes, 1);
|
||||
|
||||
/* convert to local charset */
|
||||
|
||||
#ifndef Libisofs_setlocale_in_iniT
|
||||
/* ??? ts Nov 25 2008 :
|
||||
Shouldn't this go to library initialization or even to app ?
|
||||
*/
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
conv_ret = iso_iconv_open(&conv, iso_get_local_charset(0), "UCS-2BE", 0);
|
||||
if (conv_ret <= 0) {
|
||||
#else
|
||||
conv = iconv_open(iso_get_local_charset(0), "UCS-2BE");
|
||||
if (conv == (iconv_t)(-1)) {
|
||||
#endif
|
||||
|
||||
goto ex;
|
||||
}
|
||||
src = (char *)buf;
|
||||
str = (char *)out;
|
||||
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &str, &outbytes, 0);
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &str, &outbytes);
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
if (n == -1) {
|
||||
/* error */
|
||||
goto ex;
|
||||
|
@ -198,7 +198,11 @@ int iso_rbtree_insert(IsoRBTree *tree, void *data, void **item)
|
||||
}
|
||||
}
|
||||
|
||||
comp = tree->compare(q->data, data);
|
||||
if (q->data == data) {
|
||||
comp = 0;
|
||||
} else {
|
||||
comp = tree->compare(q->data, data);
|
||||
}
|
||||
|
||||
/* Stop if found */
|
||||
if (comp == 0) {
|
||||
|
Reference in New Issue
Block a user