diff --git a/src/libisofs.h b/src/libisofs.h index 6a1b867..ea4e3b7 100644 --- a/src/libisofs.h +++ b/src/libisofs.h @@ -68,6 +68,27 @@ enum eltorito_boot_media_type { ELTORITO_NO_EMUL }; +/** + * Replace mode used when addding a node to a file. + * TODO comment + */ +enum iso_replace_mode { + /** + * Never replace an existing node, and instead fail with + * ISO_NODE_NAME_NOT_UNIQUE. + */ + ISO_REPLACE_NEVER, + /** + * Always replace the old node with the new. + */ + ISO_REPLACE_ALWAYS + /* + * TODO #00006 define more values + * -to replace only if both are the same kind of file + * -if both are dirs, add contents (and what to do with conflicts?) + */ +}; + /** * Holds the options for the image generation. */ @@ -770,11 +791,6 @@ void iso_node_set_hidden(IsoNode *node, int hide_attrs); * @param replace * if the dir already contains a node with the same name, whether to * replace or not the old node with this. - * - 0 not replace (will fail with ISO_NODE_NAME_NOT_UNIQUE) - * - 1 replace - * TODO #00006 define more values - * to replace only if both are the same kind of file - * if both are dirs, add contents (and what to do with conflicts?) * @return * number of nodes in dir if succes, < 0 otherwise * Possible errors: @@ -783,7 +799,8 @@ void iso_node_set_hidden(IsoNode *node, int hide_attrs); * ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists * ISO_WRONG_ARG_VALUE, if child == dir, or replace != (0,1) */ -int iso_dir_add_node(IsoDir *dir, IsoNode *child, int replace); +int iso_dir_add_node(IsoDir *dir, IsoNode *child, + enum iso_replace_mode replace); /** * Locate a node inside a given dir. @@ -1251,7 +1268,7 @@ int iso_image_obtain_msgs(IsoImage *image, char *minimum_severity, /** * Return the messenger object handle used by the given image. This handle - * may be used by related libraries to replace their own compatible + * may be used by related libraries to their own compatible * messenger objects and thus to direct their messages to the libisofs * message queue. See also: libburn, API function burn_set_messenger(). * diff --git a/src/node.c b/src/node.c index 0628f49..1d19585 100644 --- a/src/node.c +++ b/src/node.c @@ -259,10 +259,14 @@ void iso_node_set_hidden(IsoNode *node, int hide_attrs) * to other dir, and that the node name is unique inside the child. * Otherwise this function will return a failure, and the child won't be * inserted. + * @param replace + * if the dir already contains a node with the same name, whether to + * replace or not the old node with this. * @return * number of nodes in dir if succes, < 0 otherwise */ -int iso_dir_add_node(IsoDir *dir, IsoNode *child, int replace) +int iso_dir_add_node(IsoDir *dir, IsoNode *child, + enum iso_replace_mode replace) { IsoNode **pos; @@ -281,32 +285,8 @@ int iso_dir_add_node(IsoDir *dir, IsoNode *child, int replace) return ISO_NODE_ALREADY_ADDED; } - pos = &(dir->children); - while (*pos != NULL && strcmp((*pos)->name, child->name) < 0) { - pos = &((*pos)->next); - } - if (*pos != NULL && !strcmp((*pos)->name, child->name)) { - /* a node with same name already exists */ - if (replace == 0) { - return ISO_NODE_NAME_NOT_UNIQUE; - } else if (replace == 1) { - child->next = (*pos)->next; - (*pos)->parent = NULL; - (*pos)->next = NULL; - iso_node_unref(*pos); - *pos = child; - child->parent = dir; - return dir->nchildren; - } else { - return ISO_WRONG_ARG_VALUE; - } - } - - child->next = *pos; - *pos = child; - child->parent = dir; - - return ++dir->nchildren; + iso_dir_find(dir, child->name, &pos); + return iso_dir_insert(dir, child, pos, replace); } /** @@ -328,17 +308,14 @@ int iso_dir_add_node(IsoDir *dir, IsoNode *child, int replace) */ int iso_dir_get_node(IsoDir *dir, const char *name, IsoNode **node) { - IsoNode *pos; + int ret; + IsoNode **pos; if (dir == NULL || name == NULL) { return ISO_NULL_POINTER; } - pos = dir->children; - while (pos != NULL && strcmp(pos->name, name) < 0) { - pos = pos->next; - } - - if (pos == NULL || strcmp(pos->name, name)) { + ret = iso_dir_exists(dir, name, &pos); + if (ret == 0) { if (node) { *node = NULL; } @@ -346,7 +323,7 @@ int iso_dir_get_node(IsoDir *dir, const char *name, IsoNode **node) } if (node) { - *node = pos; + *node = *pos; } return 1; } @@ -686,6 +663,53 @@ int iso_node_is_valid_link_dest(const char *dest) return ret; } +void iso_dir_find(IsoDir *dir, const char *name, IsoNode ***pos) +{ + *pos = &(dir->children); + while (**pos != NULL && strcmp((**pos)->name, name) < 0) { + *pos = &((**pos)->next); + } +} + +int iso_dir_exists(IsoDir *dir, const char *name, IsoNode ***pos) +{ + IsoNode **node; + + iso_dir_find(dir, name, &node); + if (pos) { + *pos = node; + } + return (*node != NULL && !strcmp((*node)->name, name)) ? 1 : 0; +} + +int iso_dir_insert(IsoDir *dir, IsoNode *node, IsoNode **pos, + enum iso_replace_mode replace) +{ + if (*pos != NULL && !strcmp((*pos)->name, node->name)) { + /* a node with same name already exists */ + if (replace == ISO_REPLACE_NEVER) { + return ISO_NODE_NAME_NOT_UNIQUE; + } else if (replace == ISO_REPLACE_ALWAYS) { + node->next = (*pos)->next; + (*pos)->parent = NULL; + (*pos)->next = NULL; + iso_node_unref(*pos); + *pos = node; + node->parent = dir; + return dir->nchildren; + } else { + /* CAN'T HAPPEN */ + return ISO_WRONG_ARG_VALUE; + } + } + + node->next = *pos; + *pos = node; + node->parent = dir; + + return ++dir->nchildren; +} + int iso_node_new_root(IsoDir **root) { IsoDir *dir; diff --git a/src/node.h b/src/node.h index d7cda2d..5b819f5 100644 --- a/src/node.h +++ b/src/node.h @@ -123,4 +123,50 @@ int iso_node_is_valid_name(const char *name); */ int iso_node_is_valid_link_dest(const char *dest); +/** + * Find the position where to insert a node + * + * @param dir + * A valid dir. It can't be NULL + * @param name + * The node name to search for. It can't be NULL + * @param pos + * Will be filled with the position where to insert. It can't be NULL + */ +void iso_dir_find(IsoDir *dir, const char *name, IsoNode ***pos); + +/** + * Check if a node with the given name exists in a dir. + * + * @param dir + * A valid dir. It can't be NULL + * @param name + * The node name to search for. It can't be NULL + * @param pos + * If not NULL, will be filled with the position where to insert. If the + * node exists, (**pos) will refer to the given node. + * @return + * 1 if node exists, 0 if not + */ +int iso_dir_exists(IsoDir *dir, const char *name, IsoNode ***pos); + +/** + * Inserts a given node in a dir, at the specified position. + * + * @param dir + * Dir where to insert. It can't be NULL + * @param node + * The node to insert. It can't be NULL + * @param pos + * Position where the node will be inserted. It is a pointer previously + * obtained with a call to iso_dir_exists() or iso_dir_find(). + * It can't be NULL. + * @param replace + * Whether to replace an old node with the same name with the new node. + * @return + * If success, number of children in dir. < 0 on error + */ +int iso_dir_insert(IsoDir *dir, IsoNode *node, IsoNode **pos, + enum iso_replace_mode replace); + #endif /*LIBISO_NODE_H_*/ diff --git a/src/tree.c b/src/tree.c index 7d380b9..b584dc6 100644 --- a/src/tree.c +++ b/src/tree.c @@ -62,12 +62,8 @@ int iso_tree_add_new_dir(IsoDir *parent, const char *name, IsoDir **dir) return ISO_WRONG_ARG_VALUE; } - /* find place where to insert */ - pos = &(parent->children); - while (*pos != NULL && strcmp((*pos)->name, name) < 0) { - pos = &((*pos)->next); - } - if (*pos != NULL && !strcmp((*pos)->name, name)) { + /* find place where to insert and check if it exists */ + if (iso_dir_exists(parent, name, &pos)) { /* a node with same name already exists */ return ISO_NODE_NAME_NOT_UNIQUE; } @@ -97,15 +93,12 @@ int iso_tree_add_new_dir(IsoDir *parent, const char *name, IsoDir **dir) node->node.ctime = now; node->node.mtime = now; - /* add to dir */ - node->node.parent = parent; - node->node.next = *pos; - *pos = (IsoNode*)node; - if (dir) { *dir = node; } - return ++parent->nchildren; + + /* add to dir */ + return iso_dir_insert(parent, (IsoNode*)node, pos, ISO_REPLACE_NEVER); } /** @@ -158,11 +151,7 @@ int iso_tree_add_new_symlink(IsoDir *parent, const char *name, } /* find place where to insert */ - pos = &(parent->children); - while (*pos != NULL && strcmp((*pos)->name, name) < 0) { - pos = &((*pos)->next); - } - if (*pos != NULL && !strcmp((*pos)->name, name)) { + if (iso_dir_exists(parent, name, &pos)) { /* a node with same name already exists */ return ISO_NODE_NAME_NOT_UNIQUE; } @@ -199,15 +188,12 @@ int iso_tree_add_new_symlink(IsoDir *parent, const char *name, node->node.ctime = now; node->node.mtime = now; - /* add to dir */ - node->node.parent = parent; - node->node.next = *pos; - *pos = (IsoNode*)node; - if (link) { *link = node; } - return ++parent->nchildren; + + /* add to dir */ + return iso_dir_insert(parent, (IsoNode*)node, pos, ISO_REPLACE_NEVER); } /** @@ -271,11 +257,7 @@ int iso_tree_add_new_special(IsoDir *parent, const char *name, mode_t mode, } /* find place where to insert */ - pos = &(parent->children); - while (*pos != NULL && strcmp((*pos)->name, name) < 0) { - pos = &((*pos)->next); - } - if (*pos != NULL && !strcmp((*pos)->name, name)) { + if (iso_dir_exists(parent, name, &pos)) { /* a node with same name already exists */ return ISO_NODE_NAME_NOT_UNIQUE; } @@ -307,15 +289,12 @@ int iso_tree_add_new_special(IsoDir *parent, const char *name, mode_t mode, node->node.ctime = now; node->node.mtime = now; - /* add to dir */ - node->node.parent = parent; - node->node.next = *pos; - *pos = (IsoNode*)node; - if (special) { *special = node; } - return ++parent->nchildren; + + /* add to dir */ + return iso_dir_insert(parent, (IsoNode*)node, pos, ISO_REPLACE_NEVER); } /** @@ -395,30 +374,24 @@ int iso_tree_add_node_builder(IsoImage *image, IsoDir *parent, name = iso_file_source_get_name(src); /* find place where to insert */ - pos = &(parent->children); - while (*pos != NULL && strcmp((*pos)->name, name) < 0) { - pos = &((*pos)->next); - } - if (*pos != NULL && !strcmp((*pos)->name, name)) { + result = iso_dir_exists(parent, name, &pos); + free(name); + if (result) { /* a node with same name already exists */ return ISO_NODE_NAME_NOT_UNIQUE; } - free(name); result = builder->create_node(builder, image, src, &new); if (result < 0) { return result; } - /* finally, add node to parent */ - new->parent = parent; - new->next = *pos; - *pos = new; - if (node) { *node = new; } - return ++parent->nchildren; + + /* finally, add node to parent */ + return iso_dir_insert(parent, (IsoNode*)new, pos, ISO_REPLACE_NEVER); } int iso_tree_add_node(IsoImage *image, IsoDir *parent, const char *path, @@ -513,11 +486,7 @@ int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir) /* find place where to insert */ flag = 0; - pos = &(parent->children); - while (*pos != NULL && strcmp((*pos)->name, name) < 0) { - pos = &((*pos)->next); - } - if (*pos != NULL && !strcmp((*pos)->name, name)) { + if (iso_dir_exists(parent, name, &pos)) { flag = 1; if (action == 1 && image->recOpts.replace == 0) { action = 2; @@ -569,21 +538,8 @@ int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir) } /* ok, node has correctly created, we need to add it */ - if (flag) { - /* replace node */ - new->next = (*pos)->next; - (*pos)->parent = NULL; - (*pos)->next = NULL; - iso_node_unref(*pos); - *pos = new; - new->parent = parent; - } else { - /* just add */ - new->next = *pos; - *pos = new; - new->parent = parent; - ++parent->nchildren; - } + iso_dir_insert(parent, new, pos, flag ? ISO_REPLACE_ALWAYS : + ISO_REPLACE_NEVER); /* finally, if the node is a directory we need to recurse */ if (new->type == LIBISO_DIR) {