Transfering inode numbers from PX entries to IsoNode during image import

and using these numbers in PX entries during next image generation.
This also answers the concerns about PX without ino in RRIP 1.12
and PX with ino in RRIP 1.10 images produced by mkisofs.
This commit is contained in:
Thomas Schmitt 2009-04-28 22:40:15 +02:00
parent 5009d1038d
commit d20da80767
13 changed files with 696 additions and 79 deletions

View File

@ -156,27 +156,31 @@ demo_isoms_SOURCES = demo/iso_ms.c
# demo_isogrow_SOURCES = demo/iso_grow.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 = \ # check_PROGRAMS = \
test/test # test/test
#
test_test_CPPFLAGS = -Ilibisofs # test_test_CPPFLAGS = -Ilibisofs
test_test_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # test_test_LDADD = $(libisofs_libisofs_la_OBJECTS) \
$(libisofs_libisofs_la_LIBADD) -lcunit # $(libisofs_libisofs_la_LIBADD) -lcunit
test_test_LDFLAGS = -L.. -lm # test_test_LDFLAGS = -L.. -lm
#
test_test_SOURCES = \ # test_test_SOURCES = \
test/test.h \ # test/test.h \
test/test.c \ # test/test.c \
test/test_node.c \ # test/test_node.c \
test/test_image.c \ # test/test_image.c \
test/test_tree.c \ # test/test_tree.c \
test/test_util.c \ # test/test_util.c \
test/test_rockridge.c \ # test/test_rockridge.c \
test/test_stream.c \ # test/test_stream.c \
test/mocked_fsrc.h \ # test/mocked_fsrc.h \
test/mocked_fsrc.c # test/mocked_fsrc.c
## ========================================================================= ## ## ========================================================================= ##

View File

@ -95,7 +95,10 @@ int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name)
static static
int create_ecma119_node(Ecma119Image *img, IsoNode *iso, Ecma119Node **node) int create_ecma119_node(Ecma119Image *img, IsoNode *iso, Ecma119Node **node)
{ {
int ret;
Ecma119Node *ecma; Ecma119Node *ecma;
unsigned int fs_id;
dev_t dev_id;
ecma = calloc(1, sizeof(Ecma119Node)); ecma = calloc(1, sizeof(Ecma119Node));
if (ecma == NULL) { if (ecma == NULL) {
@ -109,11 +112,28 @@ int create_ecma119_node(Ecma119Image *img, IsoNode *iso, Ecma119Node **node)
/* TODO #00009 : add true support for harlinks and inode numbers */ /* TODO #00009 : add true support for harlinks and inode numbers */
ecma->nlink = 1; ecma->nlink = 1;
/* >>> ts A90426 : unite this with fs_give_ino_number() when it gets /* >>> One needs to find groups of nodes with identical id numbers
an inode recycling mode resp. with other reasons for being hard links.
*/ This will replace the file source unifier by rbtree
in iso_file_src_create() and iso_file_src_add().
*/
/*ts A90428 */
#ifdef Libisofs_hardlink_prooF
ret = iso_node_get_id(iso, &fs_id, &dev_id, &(ecma->ino), 1);
if (ret < 0) {
return ret;
} else if (ret == 0) {
ecma->ino = img_give_ino_number(img->image, 0);
}
#else /* Libisofs_hardlink_prooF */
ecma->ino = ++img->ino; ecma->ino = ++img->ino;
#endif /* ! Libisofs_hardlink_prooF */
*node = ecma; *node = ecma;
return ISO_SUCCESS; return ISO_SUCCESS;
} }

View File

@ -17,6 +17,8 @@
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
/* ts A90427 : introduced test (n1 == n2) and flattened block nesting
*/
int iso_file_src_cmp(const void *n1, const void *n2) int iso_file_src_cmp(const void *n1, const void *n2)
{ {
const IsoFileSrc *f1, *f2; const IsoFileSrc *f1, *f2;
@ -24,6 +26,12 @@ int iso_file_src_cmp(const void *n1, const void *n2)
dev_t dev_id1, dev_id2; dev_t dev_id1, dev_id2;
ino_t ino_id1, ino_id2; ino_t ino_id1, ino_id2;
off_t size1, size2; 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; f1 = (const IsoFileSrc *)n1;
f2 = (const IsoFileSrc *)n2; f2 = (const IsoFileSrc *)n2;
@ -31,37 +39,36 @@ int iso_file_src_cmp(const void *n1, const void *n2)
iso_stream_get_id(f2->stream, &fs_id2, &dev_id2, &ino_id2); iso_stream_get_id(f2->stream, &fs_id2, &dev_id2, &ino_id2);
#ifdef Libisofs_file_src_cmp_non_zerO #ifdef Libisofs_file_src_cmp_non_zerO
if (fs_id1 == 0 && dev_id1 == 0 && ino_id1 == 0) if (fs_id1 == 0 && dev_id1 == 0 && ino_id1 == 0) {
return -1; return -1;
if (fs_id2 == 0 && dev_id2 == 0 && ino_id2 == 0) } else if (fs_id2 == 0 && dev_id2 == 0 && ino_id2 == 0)
return 1; return 1;
}
#endif #endif
if (fs_id1 < fs_id2) { if (fs_id1 < fs_id2) {
return -1; return -1;
} else if (fs_id1 > fs_id2) { } else if (fs_id1 > fs_id2) {
return 1; 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;
}
} }
/* 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(f1->stream);
size2 = iso_stream_get_size(f2->stream);
if (size1 < size2) {
return -1;
} else if (size1 > size2) {
return 1;
}
return 0;
} }
int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src) int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)

View File

@ -88,6 +88,14 @@ struct iso_read_opts
* attribute "isofs.cs" of root directory * attribute "isofs.cs" of root directory
*/ */
int auto_input_charset; int auto_input_charset;
/* ts A90425 */
/**
* Hand out new inode numbers and overwrite eventually read PX inode
* numbers. This will split apart any hardlinks.
*/
int make_new_ino : 1 ;
}; };
/** /**
@ -137,6 +145,7 @@ enum read_rr_ext {
RR_EXT_112 = 2 /*< RR extensions conforming version 1.12 */ RR_EXT_112 = 2 /*< RR extensions conforming version 1.12 */
}; };
/** /**
* Private data for the image IsoFilesystem * Private data for the image IsoFilesystem
*/ */
@ -264,6 +273,15 @@ typedef struct
/* Inode number generator counter */ /* Inode number generator counter */
ino_t inode_counter; ino_t inode_counter;
/* ts A90425 */
/* 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; } _ImageFsData;
typedef struct image_fs_data ImageFileSourceData; typedef struct image_fs_data ImageFileSourceData;
@ -1070,6 +1088,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. * A global counter for default inode numbers for the ISO image filesystem.
* @param fs The filesystem where the number shall be used * @param fs The filesystem where the number shall be used
@ -1087,11 +1107,13 @@ ino_t fs_give_ino_number(IsoImageFilesystem *fs, int flag)
if (fsdata->inode_counter == 0) { if (fsdata->inode_counter == 0) {
/* >>> raise alert because of inode rollover */; /* >>> raise alert because of inode rollover */;
} }
return fsdata->inode_counter; return fsdata->inode_counter;
} }
#endif /* ! Libisofs_hardlink_prooF */
/** /**
* *
@ -1135,6 +1157,8 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
size_t cs_value_length = 0; size_t cs_value_length = 0;
char msg[160]; char msg[160];
int has_px = 0;
#ifdef Libisofs_with_zliB #ifdef Libisofs_with_zliB
uint8_t zisofs_alg[2], zisofs_hs4 = 0, zisofs_bsl2 = 0; uint8_t zisofs_alg[2], zisofs_hs4 = 0, zisofs_bsl2 = 0;
uint32_t zisofs_usize = 0; uint32_t zisofs_usize = 0;
@ -1147,6 +1171,7 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
fsdata = (_ImageFsData*)fs->data; fsdata = (_ImageFsData*)fs->data;
memset(&atts, 0, sizeof(struct stat)); memset(&atts, 0, sizeof(struct stat));
atts.st_nlink = 1;
/* /*
* First of all, check for unsupported ECMA-119 features * First of all, check for unsupported ECMA-119 features
@ -1275,12 +1300,23 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
continue; continue;
if (SUSP_SIG(sue, 'P', 'X')) { if (SUSP_SIG(sue, 'P', 'X')) {
/* ts A90426 */
has_px = 1;
ret = read_rr_PX(sue, &atts); ret = read_rr_PX(sue, &atts);
if (ret < 0) { if (ret < 0) {
/* notify and continue */ /* notify and continue */
ret = iso_msg_submit(fsdata->msgid, ISO_WRONG_RR_WARN, ret, ret = iso_msg_submit(fsdata->msgid, ISO_WRONG_RR_WARN, ret,
"Invalid PX entry"); "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')) { } else if (SUSP_SIG(sue, 'T', 'F')) {
ret = read_rr_TF(sue, &atts); ret = read_rr_TF(sue, &atts);
if (ret < 0) { if (ret < 0) {
@ -1536,6 +1572,11 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
} }
} }
/* ts A90426 */
if (!has_px) {
fsdata->px_ino_status |= 4;
}
/* /*
* if we haven't RR extensions, or no NM entry is present, * if we haven't RR extensions, or no NM entry is present,
* we use the name in directory record * we use the name in directory record
@ -1596,12 +1637,29 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
/* but the real name is the name of the placeholder */ /* but the real name is the name of the placeholder */
ifsdata = (ImageFileSourceData*) (*src)->data; ifsdata = (ImageFileSourceData*) (*src)->data;
ifsdata->name = name; ifsdata->name = name;
/* >>> ts A90427 : What about final treatment ?
How does directory relocation relate to inode
numbers and hard links ?
*/
return ISO_SUCCESS; return ISO_SUCCESS;
} }
#ifdef Libisofs_hardlink_prooF
/* ts A90426 :
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 #ifdef Libisofs_new_fs_image_inO
/* >>> ts A90426 : this ifdef shall become a read option */
if (fsdata->rr != RR_EXT_112) { if (fsdata->rr != RR_EXT_112) {
if (fsdata->rr == 0) { if (fsdata->rr == 0) {
atts.st_nlink = 1; atts.st_nlink = 1;
@ -1611,6 +1669,7 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
#else /* Libisofs_new_fs_image_inO */ #else /* Libisofs_new_fs_image_inO */
/* ts Nov 25 2008: TODO /* ts Nov 25 2008: TODO
This seems not fully consistent with read_rr_PX() which decides 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. by (px->len_sue[0] == 44) whether an inode number is present or not.
@ -1642,7 +1701,8 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
/* Ticket 144: This produces duplicate numbers with empty files. /* Ticket 144: This produces duplicate numbers with empty files.
*/ */
atts.st_ino = (ino_t) iso_read_bb(record->block, 4, NULL); atts.st_ino = (ino_t) iso_read_bb(record->block, 4, NULL);
#endif #endif /* ! Libisofs_patch_ticket_144 */
if (fsdata->rr == 0) { if (fsdata->rr == 0) {
atts.st_nlink = 1; atts.st_nlink = 1;
} }
@ -1650,6 +1710,8 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
#endif /* ! Libisofs_new_fs_image_inO */ #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, * if we haven't RR extensions, or a needed TF time stamp is not present,
* we use plain iso recording time * we use plain iso recording time
@ -1974,7 +2036,6 @@ void ifs_fs_free(IsoFilesystem *fs)
free(data->copyright_file_id); free(data->copyright_file_id);
free(data->abstract_file_id); free(data->abstract_file_id);
free(data->biblio_file_id); free(data->biblio_file_id);
free(data->input_charset); free(data->input_charset);
free(data->local_charset); free(data->local_charset);
free(data); free(data);
@ -2273,6 +2334,8 @@ int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts,
data->msgid = msgid; data->msgid = msgid;
data->aaip_load = !opts->noaaip; data->aaip_load = !opts->noaaip;
data->aaip_version = -1; data->aaip_version = -1;
data->inode_counter = 0;
data->px_ino_status = 0;
#ifndef Libisofs_setlocale_in_iniT #ifndef Libisofs_setlocale_in_iniT
/* ??? ts Nov 25 2008 : /* ??? ts Nov 25 2008 :
@ -2718,15 +2781,35 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
ret = src_aa_to_node(src, new, 0); ret = src_aa_to_node(src, new, 0);
if (ret < 0) { if (ret < 0) {
/* todo: stuff any possible memory leak here */ goto failure;
if (name != NULL)
free(name);
free(new);
return ret;
} }
#ifdef Libisofs_hardlink_prooF
/* ts A90428 */
/* Attach ino as xinfo if valid and no IsoStream is involved */
if (info.st_ino != 0 && (info.st_mode & S_IFMT) != S_IFREG
&& (info.st_mode & S_IFMT) != S_IFDIR) {
/* >>> ??? is there any sense in equipping directories with
persistent inode numbers ? */
ret = iso_node_set_ino(new, info.st_ino, 0);
if (ret < 0)
goto failure;
}
#endif /* Libisofs_hardlink_prooF */
*node = new; *node = new;
return ISO_SUCCESS; return ISO_SUCCESS;
failure:;
/* todo: stuff any possible memory leak here */
if (name != NULL)
free(name);
free(new);
return ret;
} }
/** /**
@ -2763,7 +2846,8 @@ int iso_image_builder_new(IsoNodeBuilder *old, IsoNodeBuilder **builder)
* accessible from the ISO filesystem. * accessible from the ISO filesystem.
*/ */
static static
int create_boot_img_filesrc(IsoImageFilesystem *fs, IsoFileSource **src) int create_boot_img_filesrc(IsoImageFilesystem *fs, IsoImage *image,
IsoFileSource **src)
{ {
int ret; int ret;
struct stat atts; struct stat atts;
@ -2780,18 +2864,25 @@ int create_boot_img_filesrc(IsoImageFilesystem *fs, IsoFileSource **src)
memset(&atts, 0, sizeof(struct stat)); memset(&atts, 0, sizeof(struct stat));
atts.st_mode = S_IFREG; atts.st_mode = S_IFREG;
#ifdef Libisofs_hardlink_prooF
/* ts A90427 : img_give_ino_number() is coordinated with existing inos */
atts.st_ino = img_give_ino_number(image, 0);
#else /* Libisofs_hardlink_prooF */
#ifdef Libisofs_new_fs_image_inO #ifdef Libisofs_new_fs_image_inO
atts.st_ino = fs_give_ino_number(fs, 0); atts.st_ino = fs_give_ino_number(fs, 0);
#else /* Libisofs_new_fs_image_inO */ #else /* Libisofs_new_fs_image_inO */
/* ts A90426 : >>> need a unique inode for El-Torito boot image */
atts.st_ino = fsdata->imgblock; /* not the best solution, but... */ atts.st_ino = fsdata->imgblock; /* not the best solution, but... */
#endif /* ! Libisofs_new_fs_image_inO */ #endif /* ! Libisofs_new_fs_image_inO */
#endif /* ! Libisofs_hardlink_prooF */
atts.st_nlink = 1; atts.st_nlink = 1;
/* /*
@ -2953,12 +3044,40 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
goto import_revert; goto import_revert;
} }
#ifdef Libisofs_hardlink_prooF
/* ts A90428 */
/* Take over inode management from IsoImageFilesystem.
data->inode_counter is supposed to hold the maximum PX inode number.
*/
image->inode_counter = data->inode_counter;
/* ts A90426 */
if ((data->px_ino_status & (2 | 4 | 8)) || opts->make_new_ino) {
/* >>> ??? is there any benefit with stable ino for directories ?
if so: add 4 to img_make_inos(flag)
*/
ret = img_make_inos(image, image->root, 8 | 2 | !!opts->make_new_ino);
if (ret < 0) {
iso_node_builder_unref(image->builder);
goto import_revert;
}
/* <<< debugging */
} else {
/* <<< just for the duplicate inode check */
img_collect_inos(image, image->root, 0);
}
#endif /* ! Libisofs_hardlink_prooF */
if (data->eltorito) { if (data->eltorito) {
/* if catalog and image nodes were not filled, we create them here */ /* if catalog and image nodes were not filled, we create them here */
if (image->bootcat->image->image == NULL) { if (image->bootcat->image->image == NULL) {
IsoFileSource *src; IsoFileSource *src;
IsoNode *node; IsoNode *node;
ret = create_boot_img_filesrc(fs, &src); ret = create_boot_img_filesrc(fs, image, &src);
if (ret < 0) { if (ret < 0) {
iso_node_builder_unref(image->builder); iso_node_builder_unref(image->builder);
goto import_revert; goto import_revert;

View File

@ -14,6 +14,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h>
/** /**
* Create a new image, empty. * Create a new image, empty.
@ -73,6 +74,9 @@ int iso_image_new(const char *name, IsoImage **image)
} }
img->builder_ignore_acl = 1; img->builder_ignore_acl = 1;
img->builder_ignore_ea = 1; img->builder_ignore_ea = 1;
img->inode_counter = 0;
img->used_inodes = NULL;
img->used_inodes_start = 0;
*image = img; *image = img;
return ISO_SUCCESS; return ISO_SUCCESS;
} }
@ -119,6 +123,11 @@ void iso_image_unref(IsoImage *image)
free(image->copyright_file_id); free(image->copyright_file_id);
free(image->abstract_file_id); free(image->abstract_file_id);
free(image->biblio_file_id); free(image->biblio_file_id);
/* ts A90428 */
if (image->used_inodes != NULL)
free(image->used_inodes);
free(image); free(image);
} }
} }
@ -318,3 +327,217 @@ void iso_image_set_ignore_aclea(IsoImage *image, int what)
image->builder_ignore_ea = !!(what & 2); image->builder_ignore_ea = !!(what & 2);
} }
/* ts A90428 */
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) {
/* <<< */
if (ino &&
image->used_inodes[(ino - image->used_inodes_start) / 8]
& (1 << (ino % 8)))
fprintf(stderr,
"libisofs_DEBUG: found duplicate inode number %.f\n",
(double) ino);
image->used_inodes[(ino - image->used_inodes_start) / 8]
|= (1 << (ino % 8));
}
return 1;
}
/* ts A90428 */
/* 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;
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)
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:;
iso_dir_iter_free(iter);
return ret;
}
/* ts A90428 */
/**
* 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)) &&
((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;
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:;
iso_dir_iter_free(iter);
return ret;
}

View File

@ -13,6 +13,14 @@
#include "fsource.h" #include "fsource.h"
#include "builder.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. * Image is a context for image manipulation.
* Global objects such as the message_queues must belogn to that * Global objects such as the message_queues must belogn to that
@ -121,6 +129,59 @@ struct Iso_Image
*/ */
void *user_data; void *user_data;
void (*user_data_free)(void *ptr); void (*user_data_free)(void *ptr);
/* ts A90427 */
/**
* 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;
}; };
/* ts A90428 */
/* 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);
/* ts A90428 */
/**
* 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);
/* ts A90428 */
/* @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_*/ #endif /*LIBISO_IMAGE_H_*/

View File

@ -5002,18 +5002,6 @@ int iso_gzip_get_refcounts(off_t *gzip_count, off_t *gunzip_count, int flag);
/** El-Torito image is hidden (WARNING,HIGH, -335) */ /** El-Torito image is hidden (WARNING,HIGH, -335) */
#define ISO_EL_TORITO_HIDDEN 0xD030FEB1 #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 /** AAIP info with ACL or xattr in ISO image will be ignored
(NOTE, HIGH, -336) */ (NOTE, HIGH, -336) */
@ -5070,6 +5058,25 @@ int iso_gzip_get_refcounts(off_t *gzip_count, off_t *gunzip_count, int flag);
#define ISO_ZLIB_EARLY_EOF 0xE830FEA1 #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 #ifdef LIBISOFS_WITHOUT_LIBBURN
@ -5268,9 +5275,24 @@ struct burn_source {
#define Libisofs_aaip_2_0 yes #define Libisofs_aaip_2_0 yes
/* Encapsulation : 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
/* ---------------------------- Experiments ---------------------------- */ /* ---------------------------- Experiments ---------------------------- */
/* Hardlinks : Override Libisofs_new_fs_image_inO and preserve inode numbers
from session to session.
>>> STILL IMMATURE. DO NOT USE YET.
*/
#define Libisofs_hardlink_prooF yes
/* Experiment: Ignore PX inode numbers, /* Experiment: Ignore PX inode numbers,
have boot image inode number counted by fs_give_ino_number() have boot image inode number counted by fs_give_ino_number()
*/ */
@ -5301,12 +5323,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_*/ #endif /*LIBISO_LIBISOFS_H_*/

View File

@ -8,6 +8,7 @@
*/ */
#include "libisofs.h" #include "libisofs.h"
#include "image.h"
#include "node.h" #include "node.h"
#include "stream.h" #include "stream.h"
#include "aaip_0_2.h" #include "aaip_0_2.h"
@ -2239,3 +2240,112 @@ int iso_node_zf_by_magic(IsoNode *node, int flag)
return total_ret; return total_ret;
} }
/* <<< ts A90427 : to some other source module ? In what .h ? */
int iso_px_ino_xinfo_func(void *data, int flag)
{
if (flag == 1) {
free(data);
}
return 1;
}
/* ts A90427 */
/*
* @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
*/
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;
void *xipt;
ret = iso_node_get_xinfo(node, iso_px_ino_xinfo_func, &xipt);
if (ret < 0)
return ret;
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))
return 0;
return 1;
}
return 0;
}
/* ts A90427 */
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;
}
/* ts A90427 */
int iso_node_set_ino(IsoNode *node, ino_t ino, int flag)
{
int ret;
IsoFile *file;
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;
}
ret = iso_node_set_ino_xinfo(node, ino, 0);
if (ret < 0)
return ret;
return 2;
}
/* ts A90427 */
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;
}

View File

@ -399,4 +399,29 @@ struct zisofs_zf_info {
int iso_file_zf_by_magic(IsoFile *file, int flag); int iso_file_zf_by_magic(IsoFile *file, int flag);
/* ts A90427 : might become API */
/*
* @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
*/
int iso_node_get_id(IsoNode *node, unsigned int *fs_id, dev_t *dev_id,
ino_t *ino_id, int flag);
/* ts A90427 */
/* 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);
/* ts A90427 */
/* 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);
#endif /*LIBISO_NODE_H_*/ #endif /*LIBISO_NODE_H_*/

View File

@ -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). * Fills a struct stat with the values of a Rock Ridge PX entry (RRIP, 4.1.1).
* *
* @return * @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); int read_rr_PX(struct susp_sys_user_entry *px, struct stat *st);

View File

@ -169,11 +169,15 @@ 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_nlink = iso_read_bb(px->data.PX.links, 4, NULL);
st->st_uid = iso_read_bb(px->data.PX.uid, 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_gid = iso_read_bb(px->data.PX.gid, 4, NULL);
st->st_ino = 0;
if (px->len_sue[0] == 44) { if (px->len_sue[0] == 44) {
/* this corresponds to RRIP 1.12, so we have inode serial number */ /* this corresponds to RRIP 1.12, so we have inode serial number */
st->st_ino = iso_read_bb(px->data.PX.serial, 4, NULL); st->st_ino = iso_read_bb(px->data.PX.serial, 4, NULL);
/* ts A90426 : Indicate that st_ino is valid */
return 2;
} }
return ISO_SUCCESS; return 1;
} }
/** /**

View File

@ -672,8 +672,12 @@ void iso_stream_get_file_name(IsoStream *stream, char *name)
IsoStream *iso_stream_get_input_stream(IsoStream *stream, int flag) IsoStream *iso_stream_get_input_stream(IsoStream *stream, int flag)
{ {
IsoStreamIface* class = stream->class; IsoStreamIface* class;
if (stream == NULL) {
return ISO_NULL_POINTER;
}
class = stream->class;
if (class->version < 2) if (class->version < 2)
return NULL; return NULL;
return class->get_input_stream(stream, 0); return class->get_input_stream(stream, 0);
@ -709,3 +713,18 @@ ex:;
return path; return path;
} }
/* ts A90427 */
/* @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;
}

View File

@ -74,4 +74,12 @@ int iso_stream_get_src_zf(IsoStream *stream, int *header_size_div4,
int *block_size_log2, uint32_t *uncompressed_size, int *block_size_log2, uint32_t *uncompressed_size,
int flag); int flag);
/* ts A90427 */
/**
* 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_*/ #endif /*STREAM_H_*/