diff --git a/libisofs/branches/thomas/Makefile.am b/libisofs/branches/thomas/Makefile.am index 6492a714..f992d25c 100644 --- a/libisofs/branches/thomas/Makefile.am +++ b/libisofs/branches/thomas/Makefile.am @@ -16,6 +16,7 @@ libisofs_libisofs_la_SOURCES = \ libisofs/node.c \ libisofs/tree.h \ libisofs/tree.c \ + libisofs/find.c \ libisofs/image.h \ libisofs/image.c \ libisofs/fsource.h \ @@ -28,6 +29,9 @@ libisofs_libisofs_la_SOURCES = \ libisofs/libiso_msgs.c \ libisofs/stream.h \ libisofs/stream.c \ + libisofs/filter.h \ + libisofs/filter.c \ + libisofs/filters/xor_encrypt.c \ libisofs/util.h \ libisofs/util.c \ libisofs/util_rbtree.c \ @@ -62,6 +66,7 @@ noinst_PROGRAMS = \ demo/cat \ demo/catbuffer \ demo/tree \ + demo/find \ demo/ecma119tree \ demo/iso \ demo/isoread \ @@ -86,6 +91,10 @@ demo_tree_CPPFLAGS = -Ilibisofs demo_tree_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS) demo_tree_SOURCES = demo/tree.c +demo_find_CPPFLAGS = -Ilibisofs +demo_find_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS) +demo_find_SOURCES = demo/find.c + demo_ecma119tree_CPPFLAGS = -Ilibisofs demo_ecma119tree_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS) demo_ecma119tree_SOURCES = demo/ecma119_tree.c diff --git a/libisofs/branches/thomas/libisofs/data_source.c b/libisofs/branches/thomas/libisofs/data_source.c index 98515c6c..4d7c3cc2 100644 --- a/libisofs/branches/thomas/libisofs/data_source.c +++ b/libisofs/branches/thomas/libisofs/data_source.c @@ -57,7 +57,7 @@ int ds_open(IsoDataSource *src) data = (struct file_data_src*) src->data; if (data->fd != -1) { - return ISO_FILE_ALREADY_OPENNED; + return ISO_FILE_ALREADY_OPENED; } fd = open(data->path, O_RDONLY); @@ -81,7 +81,7 @@ int ds_close(IsoDataSource *src) data = (struct file_data_src*) src->data; if (data->fd == -1) { - return ISO_FILE_NOT_OPENNED; + return ISO_FILE_NOT_OPENED; } /* close can fail if fd is not valid, but that should never happen */ @@ -102,7 +102,7 @@ static int ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer) data = (struct file_data_src*) src->data; if (data->fd == -1) { - return ISO_FILE_NOT_OPENNED; + return ISO_FILE_NOT_OPENED; } /* goes to requested block */ diff --git a/libisofs/branches/thomas/libisofs/eltorito.c b/libisofs/branches/thomas/libisofs/eltorito.c index f8e94c99..441b5c15 100644 --- a/libisofs/branches/thomas/libisofs/eltorito.c +++ b/libisofs/branches/thomas/libisofs/eltorito.c @@ -538,7 +538,7 @@ int catalog_open(IsoStream *stream) data = stream->data; if (data->offset != -1) { - return ISO_FILE_ALREADY_OPENNED; + return ISO_FILE_ALREADY_OPENED; } memset(data->buffer, 0, BLOCK_SIZE); @@ -563,7 +563,7 @@ int catalog_close(IsoStream *stream) data = stream->data; if (data->offset == -1) { - return ISO_FILE_NOT_OPENNED; + return ISO_FILE_NOT_OPENED; } data->offset = -1; return ISO_SUCCESS; @@ -589,7 +589,7 @@ int catalog_read(IsoStream *stream, void *buf, size_t count) data = stream->data; if (data->offset == -1) { - return ISO_FILE_NOT_OPENNED; + return ISO_FILE_NOT_OPENED; } len = MIN(count, BLOCK_SIZE - data->offset); @@ -617,12 +617,6 @@ void catalog_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, *ino_id = 0; } -static -char *catalog_get_name(IsoStream *stream) -{ - return strdup("El-Torito Boot Catalog"); -} - static void catalog_free(IsoStream *stream) { @@ -630,13 +624,14 @@ void catalog_free(IsoStream *stream) } IsoStreamIface catalog_stream_class = { + 0, + "boot", catalog_open, catalog_close, catalog_get_size, catalog_read, catalog_is_repeatable, catalog_get_id, - catalog_get_name, catalog_free }; diff --git a/libisofs/branches/thomas/libisofs/filesrc.c b/libisofs/branches/thomas/libisofs/filesrc.c index a4a2bfca..2c57ce53 100644 --- a/libisofs/branches/thomas/libisofs/filesrc.c +++ b/libisofs/branches/thomas/libisofs/filesrc.c @@ -15,6 +15,7 @@ #include #include +#include int iso_file_src_cmp(const void *n1, const void *n2) { @@ -243,7 +244,7 @@ int filesrc_writer_write_data(IsoImageWriter *writer) Ecma119Image *t; IsoFileSrc *file; IsoFileSrc **filelist; - char *name; + char name[PATH_MAX]; char buffer[BLOCK_SIZE]; if (writer == NULL) { @@ -266,16 +267,15 @@ int filesrc_writer_write_data(IsoImageWriter *writer) uint32_t nblocks = DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE); res = filesrc_open(file); + iso_stream_get_file_name(file->stream, name); if (res < 0) { /* * UPS, very ugly error, the best we can do is just to write * 0's to image */ - name = iso_stream_get_name(file->stream); iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0); res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res, "File \"%s\" can't be opened. Filling with 0s.", name); - free(name); if (res < 0) { return res; /* aborted due to error severity */ } @@ -289,12 +289,10 @@ int filesrc_writer_write_data(IsoImageWriter *writer) } continue; } else if (res > 1) { - name = iso_stream_get_name(file->stream); iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0); res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0, "Size of file \"%s\" has changed. It will be %s", name, (res == 2 ? "truncated" : "padded with 0's")); - free(name); if (res < 0) { filesrc_close(file); return res; /* aborted due to error severity */ @@ -302,9 +300,7 @@ int filesrc_writer_write_data(IsoImageWriter *writer) } #ifdef LIBISOFS_VERBOSE_DEBUG else { - name = iso_stream_get_name(file->stream); iso_msg_debug(t->image->id, "Writing file %s", name); - free(name); } #endif @@ -328,7 +324,6 @@ int filesrc_writer_write_data(IsoImageWriter *writer) if (b < nblocks) { /* premature end of file, due to error or eof */ - char *name = iso_stream_get_name(file->stream); iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0); if (res < 0) { /* error */ @@ -339,7 +334,6 @@ int filesrc_writer_write_data(IsoImageWriter *writer) res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0, "Premature end of file %s.", name); } - free(name); if (res < 0) { return res; /* aborted due error severity */ diff --git a/libisofs/branches/thomas/libisofs/fs_image.c b/libisofs/branches/thomas/libisofs/fs_image.c index 817668df..8394cfda 100644 --- a/libisofs/branches/thomas/libisofs/fs_image.c +++ b/libisofs/branches/thomas/libisofs/fs_image.c @@ -474,7 +474,7 @@ int ifs_open(IsoFileSource *src) data = (ImageFileSourceData*)src->data; if (data->opened) { - return ISO_FILE_ALREADY_OPENNED; + return ISO_FILE_ALREADY_OPENED; } if (S_ISDIR(data->info.st_mode)) { @@ -530,7 +530,7 @@ int ifs_close(IsoFileSource *src) data = (ImageFileSourceData*)src->data; if (!data->opened) { - return ISO_FILE_NOT_OPENNED; + return ISO_FILE_NOT_OPENED; } if (data->opened == 2) { @@ -569,7 +569,7 @@ int ifs_close(IsoFileSource *src) * Error codes: * ISO_FILE_ERROR * ISO_NULL_POINTER - * ISO_FILE_NOT_OPENNED + * ISO_FILE_NOT_OPENED * ISO_FILE_IS_DIR * ISO_OUT_OF_MEM * ISO_INTERRUPTED @@ -590,7 +590,7 @@ int ifs_read(IsoFileSource *src, void *buf, size_t count) data = (ImageFileSourceData*)src->data; if (!data->opened) { - return ISO_FILE_NOT_OPENNED; + return ISO_FILE_NOT_OPENED; } else if (data->opened != 1) { return ISO_FILE_IS_DIR; } @@ -644,7 +644,7 @@ int ifs_readdir(IsoFileSource *src, IsoFileSource **child) data = (ImageFileSourceData*)src->data; if (!data->opened) { - return ISO_FILE_NOT_OPENNED; + return ISO_FILE_NOT_OPENED; } else if (data->opened != 2) { return ISO_FILE_IS_NOT_DIR; } diff --git a/libisofs/branches/thomas/libisofs/fs_local.c b/libisofs/branches/thomas/libisofs/fs_local.c index e9a28b73..bf37337f 100644 --- a/libisofs/branches/thomas/libisofs/fs_local.c +++ b/libisofs/branches/thomas/libisofs/fs_local.c @@ -190,7 +190,7 @@ int lfs_open(IsoFileSource *src) data = src->data; if (data->openned) { - return ISO_FILE_ALREADY_OPENNED; + return ISO_FILE_ALREADY_OPENED; } /* is a file or a dir ? */ @@ -251,7 +251,7 @@ int lfs_close(IsoFileSource *src) ret = closedir(data->info.dir) == 0 ? ISO_SUCCESS : ISO_FILE_ERROR; break; default: - ret = ISO_FILE_NOT_OPENNED; + ret = ISO_FILE_NOT_OPENED; break; } if (ret == ISO_SUCCESS) { @@ -300,7 +300,7 @@ int lfs_read(IsoFileSource *src, void *buf, size_t count) case 2: /* directory */ return ISO_FILE_IS_DIR; default: - return ISO_FILE_NOT_OPENNED; + return ISO_FILE_NOT_OPENED; } } @@ -341,7 +341,7 @@ int lfs_readdir(IsoFileSource *src, IsoFileSource **child) return ret; } default: - return ISO_FILE_NOT_OPENNED; + return ISO_FILE_NOT_OPENED; } } diff --git a/libisofs/branches/thomas/libisofs/fsource.h b/libisofs/branches/thomas/libisofs/fsource.h index 44dda9a4..1ee8b185 100644 --- a/libisofs/branches/thomas/libisofs/fsource.h +++ b/libisofs/branches/thomas/libisofs/fsource.h @@ -20,6 +20,7 @@ #define ISO_IMAGE_FS_ID 2 #define ISO_ELTORITO_FS_ID 3 #define ISO_MEM_FS_ID 4 +#define ISO_FILTER_FS_ID 5 /** * Create a new IsoFilesystem to deal with local filesystem. diff --git a/libisofs/branches/thomas/libisofs/libisofs.h b/libisofs/branches/thomas/libisofs/libisofs.h index d7b50404..a48666d7 100644 --- a/libisofs/branches/thomas/libisofs/libisofs.h +++ b/libisofs/branches/thomas/libisofs/libisofs.h @@ -519,7 +519,7 @@ struct IsoFileSource_Iface * Opens the source. * @return 1 on success, < 0 on error * Error codes: - * ISO_FILE_ALREADY_OPENNED + * ISO_FILE_ALREADY_OPENED * ISO_FILE_ACCESS_DENIED * ISO_FILE_BAD_PATH * ISO_FILE_DOESNT_EXIST @@ -535,7 +535,7 @@ struct IsoFileSource_Iface * Error codes: * ISO_FILE_ERROR * ISO_NULL_POINTER - * ISO_FILE_NOT_OPENNED + * ISO_FILE_NOT_OPENED */ int (*close)(IsoFileSource *src); @@ -552,7 +552,7 @@ struct IsoFileSource_Iface * Error codes: * ISO_FILE_ERROR * ISO_NULL_POINTER - * ISO_FILE_NOT_OPENNED + * ISO_FILE_NOT_OPENED * ISO_WRONG_ARG_VALUE -> if count == 0 * ISO_FILE_IS_DIR * ISO_OUT_OF_MEM @@ -578,7 +578,7 @@ struct IsoFileSource_Iface * Error codes: * ISO_FILE_ERROR * ISO_NULL_POINTER - * ISO_FILE_NOT_OPENNED + * ISO_FILE_NOT_OPENED * ISO_FILE_IS_NOT_DIR * ISO_OUT_OF_MEM */ @@ -675,6 +675,18 @@ extern ino_t serial_id; */ struct IsoStream_Iface { + /* reserved for future usage, set to 0 */ + int version; + + /** + * Type of Stream. + * "fsrc" -> Read from file source + * "mem " -> Read from memory + * "boot" -> Boot catalog + * "user" -> User supplied stream + */ + char type[4]; + /** * Opens the stream. * @@ -727,14 +739,6 @@ struct IsoStream_Iface void (*get_id)(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id); - /** - * Get a name that identifies the Stream contents. It is used only for - * informational or debug purposes, so you can return anything you - * consider suitable for identification of the source, such as the path - * of the file on disc. - */ - char *(*get_name)(IsoStream *stream); - /** * Free implementation specific data. Should never be called by user. * Use iso_stream_unref() instead. @@ -2058,7 +2062,7 @@ IsoDir *iso_node_get_parent(IsoNode *node); * you should free the iterator with iso_dir_iter_free. * You musn't delete a child of the same dir, using iso_node_take() or * iso_node_remove(), while you're using the iterator. You can use - * iso_node_take_iter() or iso_node_remove_iter() instead. + * iso_dir_iter_take() or iso_dir_iter_remove() instead. * * You can use the iterator in the way like this * @@ -2160,6 +2164,191 @@ int iso_dir_iter_take(IsoDirIter *iter); */ int iso_dir_iter_remove(IsoDirIter *iter); + +/** + * @since 0.6.4 + */ +typedef struct iso_find_condition IsoFindCondition; + +/** + * Create a new condition that checks if the node name matches the given + * wildcard. + * + * @param wildcard + * @result + * The created IsoFindCondition, NULL on error. + * + * @since 0.6.4 + */ +IsoFindCondition *iso_new_find_conditions_name(const char *wildcard); + +/** + * Create a new condition that checks the node mode against a mode mask. It + * can be used to check both file type and permissions. + * + * For example: + * + * iso_new_find_conditions_mode(S_IFREG) : search for regular files + * iso_new_find_conditions_mode(S_IFCHR | S_IWUSR) : search for character + * devices where owner has write permissions. + * + * @param mask + * Mode mask to AND against node mode. + * @result + * The created IsoFindCondition, NULL on error. + * + * @since 0.6.4 + */ +IsoFindCondition *iso_new_find_conditions_mode(mode_t mask); + +/** + * Create a new condition that checks the node gid. + * + * @param gid + * Desired Group Id. + * @result + * The created IsoFindCondition, NULL on error. + * + * @since 0.6.4 + */ +IsoFindCondition *iso_new_find_conditions_gid(gid_t gid); + +/** + * Create a new condition that checks the node uid. + * + * @param uid + * Desired User Id. + * @result + * The created IsoFindCondition, NULL on error. + * + * @since 0.6.4 + */ +IsoFindCondition *iso_new_find_conditions_uid(uid_t uid); + +/** + * Possible comparison between IsoNode and given conditions. + * + * @since 0.6.4 + */ +enum iso_find_comparisons { + ISO_FIND_COND_GREATER, + ISO_FIND_COND_GREATER_OR_EQUAL, + ISO_FIND_COND_EQUAL, + ISO_FIND_COND_LESS, + ISO_FIND_COND_LESS_OR_EQUAL +}; + +/** + * Create a new condition that checks the time of last access. + * + * @param time + * Time to compare against IsoNode atime. + * @param comparison + * Comparison to be done between IsoNode atime and submitted time. + * Note that ISO_FIND_COND_GREATER, for example, is true if the node + * time is greater than the submitted time. + * @result + * The created IsoFindCondition, NULL on error. + * + * @since 0.6.4 + */ +IsoFindCondition *iso_new_find_conditions_atime(time_t time, + enum iso_find_comparisons comparison); + +/** + * Create a new condition that checks the time of last modification. + * + * @param time + * Time to compare against IsoNode mtime. + * @param comparison + * Comparison to be done between IsoNode mtime and submitted time. + * Note that ISO_FIND_COND_GREATER, for example, is true if the node + * time is greater than the submitted time. + * @result + * The created IsoFindCondition, NULL on error. + * + * @since 0.6.4 + */ +IsoFindCondition *iso_new_find_conditions_mtime(time_t time, + enum iso_find_comparisons comparison); + +/** + * Create a new condition that checks the time of last status change. + * + * @param time + * Time to compare against IsoNode ctime. + * @param comparison + * Comparison to be done between IsoNode ctime and submitted time. + * Note that ISO_FIND_COND_GREATER, for example, is true if the node + * time is greater than the submitted time. + * @result + * The created IsoFindCondition, NULL on error. + * + * @since 0.6.4 + */ +IsoFindCondition *iso_new_find_conditions_ctime(time_t time, + enum iso_find_comparisons comparison); + +/** + * Create a new condition that check if the two given conditions are + * valid. + * + * @param a + * @param b + * IsoFindCondition to compare + * @result + * The created IsoFindCondition, NULL on error. + * + * @since 0.6.4 + */ +IsoFindCondition *iso_new_find_conditions_and(IsoFindCondition *a, + IsoFindCondition *b); + +/** + * Create a new condition that check if at least one the two given conditions + * is valid. + * + * @param a + * @param b + * IsoFindCondition to compare + * @result + * The created IsoFindCondition, NULL on error. + * + * @since 0.6.4 + */ +IsoFindCondition *iso_new_find_conditions_or(IsoFindCondition *a, + IsoFindCondition *b); + +/** + * Create a new condition that check if the given conditions is false. + * + * @param negate + * @result + * The created IsoFindCondition, NULL on error. + * + * @since 0.6.4 + */ +IsoFindCondition *iso_new_find_conditions_not(IsoFindCondition *negate); + +/** + * Find all directory children that match the given condition. + * + * @param dir + * Directory where we will search children. + * @param cond + * Condition that the children must match in order to be returned. + * It will be free together with the iterator. Remember to delete it + * if this function return error. + * @param iter + * Iterator that returns only the children that match condition. + * @return + * 1 on success, < 0 on error + * + * @since 0.6.4 + */ +int iso_dir_find_children(IsoDir* dir, IsoFindCondition *cond, + IsoDirIter **iter); + /** * Get the destination of a node. * The returned string belongs to the node and should not be modified nor @@ -2226,6 +2415,35 @@ off_t iso_file_get_size(IsoFile *file); */ IsoStream *iso_file_get_stream(IsoFile *file); +/** + * Get the block lba of a file node, if it was imported from an old image. + * + * @param file + * The file + * @param lba + * Will be filled with the kba + * @param flag + * Reserved for future usage, submit 0 + * @return + * 1 if lba is valid (file comes from old image), 0 if file was newly + * added, i.e. it does not come from an old image, < 0 error + * + * @since 0.6.4 + */ +int iso_file_get_old_image_lba(IsoFile *file, uint32_t *lba, int flag); + +/* + * Like iso_file_get_old_image_lba(), but take an IsoNode. + * + * @return + * 1 if lba is valid (file comes from old image), 0 if file was newly + * added, i.e. it does not come from an old image, 2 node type has no + * LBA (no regular file), < 0 error + * + * @since 0.6.4 + */ +int iso_node_get_old_image_lba(IsoNode *node, uint32_t *lba, int flag); + /** * Add a new directory to the iso tree. Permissions, owner and hidden atts * are taken from parent, you can modify them later. @@ -2889,7 +3107,7 @@ int iso_file_source_stat(IsoFileSource *src, struct stat *info); * Opens the source. * @return 1 on success, < 0 on error * Error codes: - * ISO_FILE_ALREADY_OPENNED + * ISO_FILE_ALREADY_OPENED * ISO_FILE_ACCESS_DENIED * ISO_FILE_BAD_PATH * ISO_FILE_DOESNT_EXIST @@ -2907,7 +3125,7 @@ int iso_file_source_open(IsoFileSource *src); * Error codes: * ISO_FILE_ERROR * ISO_NULL_POINTER - * ISO_FILE_NOT_OPENNED + * ISO_FILE_NOT_OPENED * * @since 0.6.2 */ @@ -2933,7 +3151,7 @@ int iso_file_source_close(IsoFileSource *src); * Error codes: * ISO_FILE_ERROR * ISO_NULL_POINTER - * ISO_FILE_NOT_OPENNED + * ISO_FILE_NOT_OPENED * ISO_WRONG_ARG_VALUE -> if count == 0 * ISO_FILE_IS_DIR * ISO_OUT_OF_MEM @@ -2961,7 +3179,7 @@ int iso_file_source_read(IsoFileSource *src, void *buf, size_t count); * Error codes: * ISO_FILE_ERROR * ISO_NULL_POINTER - * ISO_FILE_NOT_OPENNED + * ISO_FILE_NOT_OPENED * ISO_FILE_IS_NOT_DIR * ISO_OUT_OF_MEM * @@ -3202,17 +3420,6 @@ int iso_stream_is_repeatable(IsoStream *stream); */ void iso_stream_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id); - -/** - * Get a name that identifies the Stream contents. It is used only for - * informational or debug purposes, so you can return anything you - * consider suitable for identification of the source, such as the path - * of the file on disc. - * Returned string should be freed when no more needed. - * - * @since 0.6.4 - */ -char *iso_stream_get_name(IsoStream *stream); /************ Error codes and return values for libisofs ********************/ @@ -3287,6 +3494,9 @@ char *iso_stream_get_name(IsoStream *stream); #define ISO_FILE_ERROR 0xE830FF80 /** Trying to open an already openned file (FAILURE,HIGH, -129) */ +#define ISO_FILE_ALREADY_OPENED 0xE830FF7F + +/* @deprecated use ISO_FILE_ALREADY_OPENED instead */ #define ISO_FILE_ALREADY_OPENNED 0xE830FF7F /** Access to file is not allowed (FAILURE,HIGH, -130) */ @@ -3299,7 +3509,10 @@ char *iso_stream_get_name(IsoStream *stream); #define ISO_FILE_DOESNT_EXIST 0xE830FF7C /** Trying to read or close a file not openned (FAILURE,HIGH, -133) */ -#define ISO_FILE_NOT_OPENNED 0xE830FF7B +#define ISO_FILE_NOT_OPENED 0xE830FF7B + +/* @deprecated use ISO_FILE_NOT_OPENED instead */ +#define ISO_FILE_NOT_OPENNED ISO_FILE_NOT_OPENED /** Directory used where no dir is expected (FAILURE,HIGH, -134) */ #define ISO_FILE_IS_DIR 0xE830FF7A diff --git a/libisofs/branches/thomas/libisofs/messages.c b/libisofs/branches/thomas/libisofs/messages.c index 44416ffc..8b55b45e 100644 --- a/libisofs/branches/thomas/libisofs/messages.c +++ b/libisofs/branches/thomas/libisofs/messages.c @@ -136,16 +136,16 @@ const char *iso_error_to_msg(int errcode) return "Trying to use an invalid file as boot image"; case ISO_FILE_ERROR: return "Error on file operation"; - case ISO_FILE_ALREADY_OPENNED: - return "Trying to open an already openned file"; + case ISO_FILE_ALREADY_OPENED: + return "Trying to open an already opened file"; case ISO_FILE_ACCESS_DENIED: return "Access to file is not allowed"; case ISO_FILE_BAD_PATH: return "Incorrect path to file"; case ISO_FILE_DOESNT_EXIST: return "The file does not exist in the filesystem"; - case ISO_FILE_NOT_OPENNED: - return "Trying to read or close a file not openned"; + case ISO_FILE_NOT_OPENED: + return "Trying to read or close a file not opened"; case ISO_FILE_IS_DIR: return "Directory used where no dir is expected"; case ISO_FILE_READ_ERROR: diff --git a/libisofs/branches/thomas/libisofs/node.c b/libisofs/branches/thomas/libisofs/node.c index 187e40a5..22f46d73 100644 --- a/libisofs/branches/thomas/libisofs/node.c +++ b/libisofs/branches/thomas/libisofs/node.c @@ -15,6 +15,17 @@ #include #include +struct dir_iter_data +{ + /* points to the last visited child, to NULL before start */ + IsoNode *pos; + + /* Some control flags. + * bit 0 -> 1 if next called, 0 reseted at start or on deletion + */ + int flag; +}; + /** * Increments the reference counting of the given node. */ @@ -354,42 +365,53 @@ int iso_dir_get_children_count(IsoDir *dir) return dir->nchildren; } -int iso_dir_get_children(const IsoDir *dir, IsoDirIter **iter) +static +int iter_next(IsoDirIter *iter, IsoNode **node) { - IsoDirIter *it; - - if (dir == NULL || iter == NULL) { - return ISO_NULL_POINTER; - } - it = malloc(sizeof(IsoDirIter)); - if (it == NULL) { - return ISO_OUT_OF_MEM; - } - - it->dir = dir; - it->pos = dir->children; - - *iter = it; - return ISO_SUCCESS; -} - -int iso_dir_iter_next(IsoDirIter *iter, IsoNode **node) -{ - IsoNode *n; + struct dir_iter_data *data; if (iter == NULL || node == NULL) { return ISO_NULL_POINTER; } - n = iter->pos; - if (n == NULL) { - *node = NULL; - return 0; + + data = iter->data; + + /* clear next flag */ + data->flag &= ~0x01; + + if (data->pos == NULL) { + /* we are at the beginning */ + data->pos = iter->dir->children; + if (data->pos == NULL) { + /* empty dir */ + *node = NULL; + return 0; + } + } else { + if (data->pos->parent != iter->dir) { + /* this can happen if the node has been moved to another dir */ + /* TODO specific error */ + return ISO_ERROR; + } + if (data->pos->next == NULL) { + /* no more children */ + *node = NULL; + return 0; + } else { + /* free reference to current position */ + iso_node_unref(data->pos); /* it is never last ref!! */ + + /* advance a position */ + data->pos = data->pos->next; + } } - if (n->parent != iter->dir) { - /* this can happen if the node has been moved to another dir */ - return ISO_ERROR; - } - *node = n; - iter->pos = n->next; + + /* ok, take a ref to the current position, to prevent internal errors + * if deleted somewhere */ + iso_node_ref(data->pos); + data->flag |= 0x01; /* set next flag */ + + /* return pointed node */ + *node = data->pos; return ISO_SUCCESS; } @@ -401,17 +423,30 @@ int iso_dir_iter_next(IsoDirIter *iter, IsoNode **node) * Possible errors: * ISO_NULL_POINTER, if iter is NULL */ -int iso_dir_iter_has_next(IsoDirIter *iter) +static +int iter_has_next(IsoDirIter *iter) { + struct dir_iter_data *data; if (iter == NULL) { return ISO_NULL_POINTER; } - return iter->pos == NULL ? 0 : 1; + data = iter->data; + if (data->pos == NULL) { + return iter->dir->children == NULL ? 0 : 1; + } else { + return data->pos->next == NULL ? 0 : 1; + } } -void iso_dir_iter_free(IsoDirIter *iter) +static +void iter_free(IsoDirIter *iter) { - free(iter); + struct dir_iter_data *data; + data = iter->data; + if (data->pos != NULL) { + iso_node_unref(data->pos); + } + free(data); } static IsoNode** iso_dir_find_node(IsoDir *dir, IsoNode *node) @@ -448,7 +483,7 @@ int iso_node_take(IsoNode *node) pos = iso_dir_find_node(dir, node); if (pos == NULL) { /* should never occur */ - return ISO_ERROR; + return ISO_ASSERT_FAILURE; } *pos = node->next; node->parent = NULL; @@ -492,43 +527,161 @@ IsoDir *iso_node_get_parent(IsoNode *node) } /* TODO #00005 optimize iso_dir_iter_take */ -int iso_dir_iter_take(IsoDirIter *iter) +static +int iter_take(IsoDirIter *iter) { - IsoNode *pos; + struct dir_iter_data *data; + IsoNode *pos, *pre; if (iter == NULL) { return ISO_NULL_POINTER; } - - pos = iter->dir->children; - if (iter->pos == pos) { - return ISO_ERROR; + + data = iter->data; + + if (!(data->flag & 0x01)) { + return ISO_ERROR; /* next not called or end of dir */ } - while (pos != NULL && pos->next == iter->pos) { + + if (data->pos == NULL) { + return ISO_ASSERT_FAILURE; + } + + /* clear next flag */ + data->flag &= ~0x01; + + pos = iter->dir->children; + pre = NULL; + while (pos != NULL && pos != data->pos) { + pre = pos; pos = pos->next; } if (pos == NULL) { + return ISO_ERROR; /* node not in dir */ + } + + if (pos != data->pos) { + return ISO_ASSERT_FAILURE; + } + + /* dispose iterator reference */ + iso_node_unref(data->pos); + + if (pre == NULL) { + /* node is a first position */ + iter->dir->children = pos->next; + data->pos = NULL; + } else { + pre->next = pos->next; + data->pos = pre; + iso_node_ref(pre); /* take iter ref */ + } + + /* take pos */ + pos->parent = NULL; + pos->next = NULL; + iter->dir->nchildren--; + return ISO_SUCCESS; +} + +static +int iter_remove(IsoDirIter *iter) +{ + int ret; + IsoNode *pos; + struct dir_iter_data *data; + + if (iter == NULL) { + return ISO_NULL_POINTER; + } + data = iter->data; + pos = data->pos; + + ret = iter_take(iter); + if (ret == ISO_SUCCESS) { + /* remove node */ + iso_node_unref(pos); + } + if (data->pos == pos) { return ISO_ERROR; } - return iso_node_take(pos); + return ret; +} + +static +struct iso_dir_iter_iface iter_class = { + iter_next, + iter_has_next, + iter_free, + iter_take, + iter_remove +}; + +int iso_dir_get_children(const IsoDir *dir, IsoDirIter **iter) +{ + IsoDirIter *it; + struct dir_iter_data *data; + + if (dir == NULL || iter == NULL) { + return ISO_NULL_POINTER; + } + it = malloc(sizeof(IsoDirIter)); + if (it == NULL) { + return ISO_OUT_OF_MEM; + } + data = malloc(sizeof(struct dir_iter_data)); + if (data == NULL) { + free(it); + return ISO_OUT_OF_MEM; + } + + it->class = &iter_class; + it->dir = (IsoDir*)dir; + data->pos = NULL; + data->flag = 0x00; + it->data = data; + + *iter = it; + return ISO_SUCCESS; +} + +int iso_dir_iter_next(IsoDirIter *iter, IsoNode **node) +{ + if (iter == NULL || node == NULL) { + return ISO_NULL_POINTER; + } + return iter->class->next(iter, node); +} + +int iso_dir_iter_has_next(IsoDirIter *iter) +{ + if (iter == NULL) { + return ISO_NULL_POINTER; + } + return iter->class->has_next(iter); +} + +void iso_dir_iter_free(IsoDirIter *iter) +{ + if (iter != NULL) { + iter->class->free(iter); + free(iter); + } +} + +int iso_dir_iter_take(IsoDirIter *iter) +{ + if (iter == NULL) { + return ISO_NULL_POINTER; + } + return iter->class->take(iter); } int iso_dir_iter_remove(IsoDirIter *iter) { - IsoNode *pos; if (iter == NULL) { return ISO_NULL_POINTER; } - pos = iter->dir->children; - if (iter->pos == pos) { - return ISO_ERROR; - } - while (pos != NULL && pos->next == iter->pos) { - pos = pos->next; - } - if (pos == NULL) { - return ISO_ERROR; - } - return iso_node_remove(pos); + return iter->class->remove(iter); } /** @@ -618,6 +771,58 @@ IsoStream *iso_file_get_stream(IsoFile *file) return file->stream; } +/** + * Get the block lba of a file node, if it was imported from an old image. + * + * @param file + * The file + * @param lba + * Will be filled with the kba + * @param flag + * Reserved for future usage, submit 0 + * @return + * 1 if lba is valid (file comes from old image), 0 if file was newly + * added, i.e. it does not come from an old image, < 0 error + * + * @since 0.6.4 + */ +int iso_file_get_old_image_lba(IsoFile *file, uint32_t *lba, int flag) +{ + if (file == NULL || lba == NULL) { + return ISO_NULL_POINTER; + } + if (flag != 0) { + return ISO_WRONG_ARG_VALUE; + } + if (file->msblock != 0) { + *lba = file->msblock; + return 1; + } + return 0; +} + +/* + * Like iso_file_get_old_image_lba(), but take an IsoNode. + * + * @return + * 1 if lba is valid (file comes from old image), 0 if file was newly + * added, i.e. it does not come from an old image, 2 node type has no + * LBA (no regular file), < 0 error + * + * @since 0.6.4 + */ +int iso_node_get_old_image_lba(IsoNode *node, uint32_t *lba, int flag) +{ + if (node == NULL) { + return ISO_NULL_POINTER; + } + if (ISO_NODE_IS_FILE(node)) { + return iso_file_get_old_image_lba((IsoFile*)node, lba, flag); + } else { + return 2; + } +} + /** * Check if a given name is valid for an iso node. * diff --git a/libisofs/branches/thomas/libisofs/node.h b/libisofs/branches/thomas/libisofs/node.h index b2764f9e..a1fc96d3 100644 --- a/libisofs/branches/thomas/libisofs/node.h +++ b/libisofs/branches/thomas/libisofs/node.h @@ -148,13 +148,32 @@ struct Iso_Special dev_t dev; }; +struct iso_dir_iter_iface +{ + + int (*next)(IsoDirIter *iter, IsoNode **node); + + int (*has_next)(IsoDirIter *iter); + + void (*free)(IsoDirIter *iter); + + int (*take)(IsoDirIter *iter); + + int (*remove)(IsoDirIter *iter); + +}; + /** * An iterator for directory children. */ struct Iso_Dir_Iter { - const IsoDir *dir; - IsoNode *pos; + struct iso_dir_iter_iface *class; + + /* the directory this iterator iterates over */ + IsoDir *dir; + + void *data; }; int iso_node_new_root(IsoDir **root); diff --git a/libisofs/branches/thomas/libisofs/stream.c b/libisofs/branches/thomas/libisofs/stream.c index 710ed8f1..6058e894 100644 --- a/libisofs/branches/thomas/libisofs/stream.c +++ b/libisofs/branches/thomas/libisofs/stream.c @@ -13,6 +13,7 @@ #include #include +#include ino_t serial_id = (ino_t)1; ino_t mem_serial_id = (ino_t)1; @@ -123,14 +124,6 @@ void fsrc_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, *ino_id = data->ino_id; } -static -char *fsrc_get_name(IsoStream *stream) -{ - FSrcStreamData *data; - data = (FSrcStreamData*)stream->data; - return iso_file_source_get_path(data->src); -} - static void fsrc_free(IsoStream *stream) { @@ -141,13 +134,14 @@ void fsrc_free(IsoStream *stream) } IsoStreamIface fsrc_stream_class = { + 0, + "fsrc", fsrc_open, fsrc_close, fsrc_get_size, fsrc_read, fsrc_is_repeatable, fsrc_get_id, - fsrc_get_name, fsrc_free }; @@ -237,7 +231,7 @@ int mem_open(IsoStream *stream) } data = (MemStreamData*)stream->data; if (data->offset != -1) { - return ISO_FILE_ALREADY_OPENNED; + return ISO_FILE_ALREADY_OPENED; } data->offset = 0; return ISO_SUCCESS; @@ -252,7 +246,7 @@ int mem_close(IsoStream *stream) } data = (MemStreamData*)stream->data; if (data->offset == -1) { - return ISO_FILE_NOT_OPENNED; + return ISO_FILE_NOT_OPENED; } data->offset = -1; return ISO_SUCCESS; @@ -281,7 +275,7 @@ int mem_read(IsoStream *stream, void *buf, size_t count) data = stream->data; if (data->offset == -1) { - return ISO_FILE_NOT_OPENNED; + return ISO_FILE_NOT_OPENED; } if (data->offset >= data->size) { @@ -311,12 +305,6 @@ void mem_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, *ino_id = data->ino_id; } -static -char *mem_get_name(IsoStream *stream) -{ - return strdup("[MEMORY SOURCE]"); -} - static void mem_free(IsoStream *stream) { @@ -327,13 +315,14 @@ void mem_free(IsoStream *stream) } IsoStreamIface mem_stream_class = { + 0, + "mem ", mem_open, mem_close, mem_get_size, mem_read, mem_is_repeatable, mem_get_id, - mem_get_name, mem_free }; @@ -427,8 +416,19 @@ void iso_stream_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, stream->class->get_id(stream, fs_id, dev_id, ino_id); } -inline -char *iso_stream_get_name(IsoStream *stream) +void iso_stream_get_file_name(IsoStream *stream, char *name) { - return stream->class->get_name(stream); + char *type = stream->class->type; + + if (!strncmp(type, "fsrc", 4)) { + FSrcStreamData *data = stream->data; + char *path = iso_file_source_get_path(data->src); + strncpy(name, path, PATH_MAX); + } else if (!strncmp(type, "boot", 4)) { + strcpy(name, "BOOT CATALOG"); + } else if (!strncmp(type, "mem ", 4)) { + strcpy(name, "MEM SOURCE"); + } else { + strcpy(name, "UNKNOWN SOURCE"); + } } diff --git a/libisofs/branches/thomas/libisofs/stream.h b/libisofs/branches/thomas/libisofs/stream.h index eb12cd9c..804faf14 100644 --- a/libisofs/branches/thomas/libisofs/stream.h +++ b/libisofs/branches/thomas/libisofs/stream.h @@ -13,12 +13,12 @@ */ #include "fsource.h" -/* TODO consider removing this header */ - -/* - * Some functions here will be moved to libisofs.h when we expose - * Streams. +/** + * Get an identifier for the file of the source, for debug purposes + * @param name + * Should provide at least PATH_MAX bytes */ +void iso_stream_get_file_name(IsoStream *stream, char *name); /** * Create a stream to read from a IsoFileSource.