diff --git a/src/ecma119_tree.c b/src/ecma119_tree.c index 15d5923..b6d2782 100644 --- a/src/ecma119_tree.c +++ b/src/ecma119_tree.c @@ -14,6 +14,7 @@ #include "filesrc.h" #include "messages.h" #include "image.h" +#include "stream.h" #include #include @@ -111,6 +112,15 @@ int create_file(Ecma119Image *img, IsoFile *iso, Ecma119Node **node) { int ret; IsoFileSrc *src; + off_t size; + + size = iso->stream->get_size(iso->stream); + if (size > (off_t)0xffffffff) { + iso_msg_note(img->image, LIBISO_FILE_IGNORED, + "File \"%s\" can't be added to image because is " + "greater than 4GB", iso->node.name); + return 0; + } ret = iso_file_src_create(img, iso, &src); if (ret < 0) { @@ -190,13 +200,6 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree, switch(iso->type) { case LIBISO_FILE: ret = create_file(image, (IsoFile*)iso, &node); - if (ret == ISO_FILE_TOO_BIG) { - iso_msg_note(image->image, LIBISO_FILE_IGNORED, - "File \"%s\" can't be added to image because is " - "greater than 4GB", iso->name); - free(iso_name); - return 0; - } break; case LIBISO_SYMLINK: //TODO only supported with RR @@ -247,7 +250,7 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree, /* should never happen */ return ISO_ERROR; } - if (ret < 0) { + if (ret <= 0) { free(iso_name); return ret; } diff --git a/src/filesrc.c b/src/filesrc.c index 575eee8..4fc5d97 100644 --- a/src/filesrc.c +++ b/src/filesrc.c @@ -20,23 +20,34 @@ static int comp_iso_file_src(const void *n1, const void *n2) { const IsoFileSrc *f1, *f2; + int res; + unsigned int fs_id1, fs_id2; + dev_t dev_id1, dev_id2; + ino_t ino_id1, ino_id2; + + f1 = (const IsoFileSrc *)n1; f2 = (const IsoFileSrc *)n2; - if (f1->fs_id < f2->fs_id) { + res = f1->stream->get_id(f1->stream, &fs_id1, &dev_id1, &ino_id1); + res = f2->stream->get_id(f2->stream, &fs_id2, &dev_id2, &ino_id2); + + //TODO take care about res <= 0 + + if (fs_id1 < fs_id2) { return -1; - } else if (f1->fs_id > f2->fs_id) { + } else if (fs_id1 > fs_id2) { return 1; } else { /* files belong to the same fs */ - if (f1->dev_id > f2->dev_id) { + if (dev_id1 > dev_id2) { return -1; - } else if (f1->dev_id < f2->dev_id) { + } else if (dev_id1 < dev_id2) { return 1; } else { /* files belong to same device in same fs */ - return (f1->ino_id < f2->ino_id) ? -1 : - (f1->ino_id > f2->ino_id) ? 1 : 0; + return (ino_id1 < ino_id2) ? -1 : + (ino_id1 > ino_id2) ? 1 : 0; } } } @@ -49,7 +60,6 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src) unsigned int fs_id; dev_t dev_id; ino_t ino_id; - off_t size; if (img == NULL || file == NULL || src == NULL) { return ISO_NULL_POINTER; @@ -61,33 +71,21 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src) return res; } else if (res == 0) { // TODO this corresponds to Stream that cannot provide a valid id - // Not implemented for now + // Not implemented for now, but that shouldn't be here, the get_id + // above is not needed at all, the comparison function should take + // care of it return ISO_ERROR; } else { IsoFileSrc **inserted; - size = stream->get_size(stream); - if (size == (off_t)-1) { - return ISO_FILE_ERROR; - } - - /* Files > 4GB not supported yet, they need ISO level 3 */ - if (size > (off_t)0xffffffff) { - return ISO_FILE_TOO_BIG; - } - fsrc = malloc(sizeof(IsoFileSrc)); if (fsrc == NULL) { return ISO_MEM_ERROR; } /* fill key and other atts */ - fsrc->fs_id = fs_id; - fsrc->dev_id = dev_id; - fsrc->ino_id = ino_id; fsrc->prev_img = file->msblock ? 1 : 0; fsrc->block = file->msblock; - fsrc->size = size; fsrc->sort_weight = file->sort_weight; fsrc->stream = file->stream; @@ -119,3 +117,8 @@ void iso_file_src_free(Ecma119Image *img) tdestroy(img->file_srcs, free_node); } } + +off_t iso_file_src_get_size(IsoFileSrc *file) +{ + return file->stream->get_size(file->stream); +} diff --git a/src/filesrc.h b/src/filesrc.h index d9747e4..61bce65 100644 --- a/src/filesrc.h +++ b/src/filesrc.h @@ -15,14 +15,7 @@ #include struct Iso_File_Src { - - /* key */ - unsigned int fs_id; - dev_t dev_id; - ino_t ino_id; - unsigned int prev_img:1; /**< if the file comes from a previous image */ - off_t size; /**< size of this file */ uint32_t block; /**< Block where this file will be written on image */ int sort_weight; IsoStream *stream; @@ -52,6 +45,11 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src); */ void iso_file_src_free(Ecma119Image *img); +/** + * Get the size of the file this IsoFileSrc represents + */ +off_t iso_file_src_get_size(IsoFileSrc *file); + // TODO not implemented int iso_file_src_open(IsoFileSrc *file); diff --git a/src/stream.c b/src/stream.c index 61d57ca..9abf101 100644 --- a/src/stream.c +++ b/src/stream.c @@ -16,7 +16,12 @@ typedef struct { IsoFileSource *src; -} _FSrcStream; + + /* key for file identification inside filesystem */ + dev_t dev_id; + ino_t ino_id; + off_t size; /**< size of this file */ +} FSrcStreamData; static int fsrc_open(IsoStream *stream) @@ -25,7 +30,7 @@ int fsrc_open(IsoStream *stream) if (stream == NULL) { return ISO_NULL_POINTER; } - src = (IsoFileSource*)stream->data; + src = ((FSrcStreamData*)stream->data)->src; return src->open(src); } @@ -36,25 +41,17 @@ int fsrc_close(IsoStream *stream) if (stream == NULL) { return ISO_NULL_POINTER; } - src = (IsoFileSource*)stream->data; + src = ((FSrcStreamData*)stream->data)->src; return src->close(src); } static off_t fsrc_get_size(IsoStream *stream) { - struct stat info; - IsoFileSource *src; - if (stream == NULL) { - return ISO_NULL_POINTER; - } - src = (IsoFileSource*)stream->data; + FSrcStreamData *data; + data = (FSrcStreamData*)stream->data; - if (src->lstat(src, &info) < 0) { - return (off_t) -1; - } - - return info.st_size; + return data->size; } static @@ -64,7 +61,7 @@ int fsrc_read(IsoStream *stream, void *buf, size_t count) if (stream == NULL) { return ISO_NULL_POINTER; } - src = (IsoFileSource*)stream->data; + src = ((FSrcStreamData*)stream->data)->src; return src->read(src, buf, count); } @@ -73,17 +70,18 @@ int fsrc_is_repeatable(IsoStream *stream) { int ret; struct stat info; - IsoFileSource *src; + FSrcStreamData *data; if (stream == NULL) { return ISO_NULL_POINTER; } - src = (IsoFileSource*)stream->data; + data = (FSrcStreamData*)stream->data; - ret = src->stat(src, &info); + /* mode is not cached, this function is only useful for filters */ + ret = data->src->stat(data->src, &info); if (ret < 0) { return ret; } - if (info.st_mode & (S_IFREG | S_IFBLK)) { + if (S_ISREG(info.st_mode) || S_ISBLK(info.st_mode)) { return 1; } else { return 0; @@ -94,38 +92,33 @@ static int fsrc_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id) { - int result; - struct stat info; - IsoFileSource *src; + FSrcStreamData *data; IsoFilesystem *fs; if (stream == NULL || fs_id == NULL || dev_id == NULL || ino_id == NULL) { return ISO_NULL_POINTER; } - src = (IsoFileSource*)stream->data; + data = (FSrcStreamData*)stream->data; - fs = src->get_filesystem(src); + fs = data->src->get_filesystem(data->src); *fs_id = fs->get_id(fs); if (fs_id == 0) { return 0; } - result = src->stat(src, &info); - if (result < 0) { - return result; - } - *dev_id = info.st_dev; - *ino_id = info.st_ino; + *dev_id = data->dev_id; + *ino_id = data->ino_id; return ISO_SUCCESS; } static void fsrc_free(IsoStream *stream) { - IsoFileSource *src; - src = (IsoFileSource*)stream->data; - iso_file_source_unref(src); + FSrcStreamData *data; + data = (FSrcStreamData*)stream->data; + iso_file_source_unref(data->src); + free(data); } int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream) @@ -133,6 +126,8 @@ int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream) int r; struct stat info; IsoStream *str; + FSrcStreamData *data; + if (src == NULL || stream == NULL) { return ISO_NULL_POINTER; } @@ -149,9 +144,20 @@ int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream) if (str == NULL) { return ISO_MEM_ERROR; } + data = malloc(sizeof(FSrcStreamData)); + if (str == NULL) { + free(str); + return ISO_MEM_ERROR; + } + + /* take the ref to IsoFileSource */ + data->src = src; + data->dev_id = info.st_dev; + data->ino_id = info.st_ino; + data->size = info.st_size; str->refcount = 1; - str->data = src; + str->data = data; str->open = fsrc_open; str->close = fsrc_close; str->get_size = fsrc_get_size; diff --git a/src/stream.h b/src/stream.h index d068bf1..ab5ad48 100644 --- a/src/stream.h +++ b/src/stream.h @@ -25,6 +25,8 @@ struct Iso_Stream /** * Opens the stream. * + * TODO it would be great to return a different success code if the + * underlying source size has changed. * @return * 1 on success, < 0 on error */ @@ -37,9 +39,8 @@ struct Iso_Stream int (*close)(IsoStream *stream); /** - * Get the size (in bytes) of the stream. - * @return - * The size, or -1 on error + * Get the size (in bytes) of the stream. This function should always + * return the same size, even if the underlying source size changes. */ off_t (*get_size)(IsoStream *stream);