Encapsulate insertion of nodes in node.c. Define replace behavior.

This commit is contained in:
Vreixo Formoso 2008-01-12 18:03:59 +01:00
parent bff5cb9333
commit f118b0a48d
4 changed files with 151 additions and 108 deletions

View File

@ -68,6 +68,27 @@ enum eltorito_boot_media_type {
ELTORITO_NO_EMUL 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. * Holds the options for the image generation.
*/ */
@ -770,11 +791,6 @@ void iso_node_set_hidden(IsoNode *node, int hide_attrs);
* @param replace * @param replace
* if the dir already contains a node with the same name, whether to * if the dir already contains a node with the same name, whether to
* replace or not the old node with this. * 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 * @return
* number of nodes in dir if succes, < 0 otherwise * number of nodes in dir if succes, < 0 otherwise
* Possible errors: * 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_NODE_NAME_NOT_UNIQUE, a node with same name already exists
* ISO_WRONG_ARG_VALUE, if child == dir, or replace != (0,1) * 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. * 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 * 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 * messenger objects and thus to direct their messages to the libisofs
* message queue. See also: libburn, API function burn_set_messenger(). * message queue. See also: libburn, API function burn_set_messenger().
* *

View File

@ -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. * 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 * Otherwise this function will return a failure, and the child won't be
* inserted. * 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 * @return
* number of nodes in dir if succes, < 0 otherwise * 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; IsoNode **pos;
@ -281,32 +285,8 @@ int iso_dir_add_node(IsoDir *dir, IsoNode *child, int replace)
return ISO_NODE_ALREADY_ADDED; return ISO_NODE_ALREADY_ADDED;
} }
pos = &(dir->children); iso_dir_find(dir, child->name, &pos);
while (*pos != NULL && strcmp((*pos)->name, child->name) < 0) { return iso_dir_insert(dir, child, pos, replace);
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;
} }
/** /**
@ -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) int iso_dir_get_node(IsoDir *dir, const char *name, IsoNode **node)
{ {
IsoNode *pos; int ret;
IsoNode **pos;
if (dir == NULL || name == NULL) { if (dir == NULL || name == NULL) {
return ISO_NULL_POINTER; return ISO_NULL_POINTER;
} }
pos = dir->children; ret = iso_dir_exists(dir, name, &pos);
while (pos != NULL && strcmp(pos->name, name) < 0) { if (ret == 0) {
pos = pos->next;
}
if (pos == NULL || strcmp(pos->name, name)) {
if (node) { if (node) {
*node = NULL; *node = NULL;
} }
@ -346,7 +323,7 @@ int iso_dir_get_node(IsoDir *dir, const char *name, IsoNode **node)
} }
if (node) { if (node) {
*node = pos; *node = *pos;
} }
return 1; return 1;
} }
@ -686,6 +663,53 @@ int iso_node_is_valid_link_dest(const char *dest)
return ret; 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) int iso_node_new_root(IsoDir **root)
{ {
IsoDir *dir; IsoDir *dir;

View File

@ -123,4 +123,50 @@ int iso_node_is_valid_name(const char *name);
*/ */
int iso_node_is_valid_link_dest(const char *dest); 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_*/ #endif /*LIBISO_NODE_H_*/

View File

@ -62,12 +62,8 @@ int iso_tree_add_new_dir(IsoDir *parent, const char *name, IsoDir **dir)
return ISO_WRONG_ARG_VALUE; return ISO_WRONG_ARG_VALUE;
} }
/* find place where to insert */ /* find place where to insert and check if it exists */
pos = &(parent->children); if (iso_dir_exists(parent, name, &pos)) {
while (*pos != NULL && strcmp((*pos)->name, name) < 0) {
pos = &((*pos)->next);
}
if (*pos != NULL && !strcmp((*pos)->name, name)) {
/* a node with same name already exists */ /* a node with same name already exists */
return ISO_NODE_NAME_NOT_UNIQUE; 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.ctime = now;
node->node.mtime = now; node->node.mtime = now;
/* add to dir */
node->node.parent = parent;
node->node.next = *pos;
*pos = (IsoNode*)node;
if (dir) { if (dir) {
*dir = node; *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 */ /* find place where to insert */
pos = &(parent->children); if (iso_dir_exists(parent, name, &pos)) {
while (*pos != NULL && strcmp((*pos)->name, name) < 0) {
pos = &((*pos)->next);
}
if (*pos != NULL && !strcmp((*pos)->name, name)) {
/* a node with same name already exists */ /* a node with same name already exists */
return ISO_NODE_NAME_NOT_UNIQUE; 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.ctime = now;
node->node.mtime = now; node->node.mtime = now;
/* add to dir */
node->node.parent = parent;
node->node.next = *pos;
*pos = (IsoNode*)node;
if (link) { if (link) {
*link = node; *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 */ /* find place where to insert */
pos = &(parent->children); if (iso_dir_exists(parent, name, &pos)) {
while (*pos != NULL && strcmp((*pos)->name, name) < 0) {
pos = &((*pos)->next);
}
if (*pos != NULL && !strcmp((*pos)->name, name)) {
/* a node with same name already exists */ /* a node with same name already exists */
return ISO_NODE_NAME_NOT_UNIQUE; 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.ctime = now;
node->node.mtime = now; node->node.mtime = now;
/* add to dir */
node->node.parent = parent;
node->node.next = *pos;
*pos = (IsoNode*)node;
if (special) { if (special) {
*special = node; *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); name = iso_file_source_get_name(src);
/* find place where to insert */ /* find place where to insert */
pos = &(parent->children); result = iso_dir_exists(parent, name, &pos);
while (*pos != NULL && strcmp((*pos)->name, name) < 0) { free(name);
pos = &((*pos)->next); if (result) {
}
if (*pos != NULL && !strcmp((*pos)->name, name)) {
/* a node with same name already exists */ /* a node with same name already exists */
return ISO_NODE_NAME_NOT_UNIQUE; return ISO_NODE_NAME_NOT_UNIQUE;
} }
free(name);
result = builder->create_node(builder, image, src, &new); result = builder->create_node(builder, image, src, &new);
if (result < 0) { if (result < 0) {
return result; return result;
} }
/* finally, add node to parent */
new->parent = parent;
new->next = *pos;
*pos = new;
if (node) { if (node) {
*node = new; *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, 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 */ /* find place where to insert */
flag = 0; flag = 0;
pos = &(parent->children); if (iso_dir_exists(parent, name, &pos)) {
while (*pos != NULL && strcmp((*pos)->name, name) < 0) {
pos = &((*pos)->next);
}
if (*pos != NULL && !strcmp((*pos)->name, name)) {
flag = 1; flag = 1;
if (action == 1 && image->recOpts.replace == 0) { if (action == 1 && image->recOpts.replace == 0) {
action = 2; 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 */ /* ok, node has correctly created, we need to add it */
if (flag) { iso_dir_insert(parent, new, pos, flag ? ISO_REPLACE_ALWAYS :
/* replace node */ ISO_REPLACE_NEVER);
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;
}
/* finally, if the node is a directory we need to recurse */ /* finally, if the node is a directory we need to recurse */
if (new->type == LIBISO_DIR) { if (new->type == LIBISO_DIR) {