New API call iso_tree_resolve_symlink().

This commit is contained in:
2012-07-01 18:41:54 +02:00
parent 2c88e74798
commit 7a8995f322
4 changed files with 123 additions and 0 deletions

View File

@@ -1196,3 +1196,84 @@ int iso_tree_clone(IsoNode *node,
return ret;
}
int iso_tree_resolve_symlink(IsoImage *img, IsoSymlink *sym, IsoNode **res,
int *depth, int flag)
{
IsoDir *cur_dir = NULL;
IsoNode *n, *resolved_node;
char *dest, *dest_start, *dest_end;
int ret = 0;
unsigned int comp_len, dest_len;
dest = sym->dest;
dest_len = strlen(dest);
if (dest[0] == '/') {
/* >>> ??? How to resolve absolute links without knowing the
path of the future mount point ?
??? Would it be better to throw error ?
I can only assume that it gets mounted at / during some stage
of booting.
*/;
cur_dir = img->root;
dest_end = dest;
} else {
cur_dir = sym->node.parent;
if (cur_dir == NULL)
cur_dir = img->root;
dest_end = dest - 1;
}
while (dest_end < dest + dest_len) {
dest_start = dest_end + 1;
dest_end = strchr(dest_start, '/');
if (dest_end == NULL)
dest_end = dest_start + strlen(dest_start);
comp_len = dest_end - dest_start;
if (comp_len == 0 || (comp_len == 1 && dest_start[0] == '.'))
continue;
if (comp_len == 2 && dest_start[0] == '.' && dest_start[1] == '.') {
cur_dir = cur_dir->node.parent;
if (cur_dir == NULL) /* link shoots over root */
return ISO_DEAD_SYMLINK;
continue;
}
/* Search node in cur_dir */
for (n = cur_dir->children; n != NULL; n = n->next)
if (strncmp(dest_start, n->name, comp_len) == 0 &&
strlen(n->name) == comp_len)
break;
if (n == NULL)
return ISO_DEAD_SYMLINK;
if (n->type == LIBISO_DIR) {
cur_dir = (IsoDir *) n;
} else if (n->type == LIBISO_SYMLINK) {
if (*depth >= LIBISO_MAX_LINK_DEPTH)
return ISO_DEEP_SYMLINK;
(*depth)++;
ret = iso_tree_resolve_symlink(img, (IsoSymlink *) n,
&resolved_node, depth, 0);
if (ret < 0)
return ret;
if (resolved_node->type != LIBISO_DIR) {
n = resolved_node;
goto leaf_type;
}
cur_dir = (IsoDir *) resolved_node;
} else {
leaf_type:;
if (dest_end < dest + dest_len) /* attempt to dive into file */
return ISO_DEAD_SYMLINK;
*res = n;
return ISO_SUCCESS;
}
}
*res = cur_dir;
return ISO_SUCCESS;
}